From 35c068120dae313a71869e49eabf1920cd9cab06 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 00:48:07 +0100 Subject: [PATCH 01/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 285 +++++++++++++++++++++++++++---- 1 file changed, 254 insertions(+), 31 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index d0a3f4e..04d7526 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -1,3 +1,4 @@ + // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.19; @@ -9,6 +10,20 @@ import "./IWorkshopVault.sol"; contract WorkshopVault is ERC4626, IVault, IWorkshopVault { IEVC internal immutable evc; + uint internal totalBorrowedasset; + IERC20 assetss; + + //assumption + uint internal borrowCap = type(uint104).max; + + error NO_asset(); + + mapping(address => uint) internal balanceOfs; + mapping(address => uint) internal debtor; + + event Borrow(address operator, address onBehalfOf, uint amount); + event Repay(address operator, address onBehalfOf, uint amount); + event deposits(uint amount, address from, address onBehalfOf); constructor( IEVC _evc, @@ -17,6 +32,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { string memory _symbol ) ERC4626(_asset) ERC20(_name, _symbol) { evc = _evc; + assetss = _asset; } // [ASSIGNMENT]: what is the purpose of this modifier? @@ -24,7 +40,12 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { if (msg.sender == address(evc)) { _; } else { - bytes memory result = evc.call(address(this), msg.sender, 0, msg.data); + bytes memory result = evc.call( + address(this), + msg.sender, + 0, + msg.data + ); assembly { return(add(32, result), mload(result)) @@ -35,6 +56,9 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { // [ASSIGNMENT]: why the account status check might not be necessary in certain situations? // [ASSIGNMENT]: is the vault status check always necessary? why? modifier withChecks(address account) { + //do take the snapshot of the vault and compare with the borrow cap + //totalBorrowedasset > borrowCap ? revert + _; if (account == address(0)) { @@ -49,7 +73,9 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { // [ASSIGNMENT]: if the answer to the above is "no", how this function could be modified to allow safe borrowing? function _msgSender() internal view virtual override returns (address) { if (msg.sender == address(evc)) { - (address onBehalfOfAccount,) = evc.getCurrentOnBehalfOfAccount(address(0)); + (address onBehalfOfAccount, ) = evc.getCurrentOnBehalfOfAccount( + address(0) + ); return onBehalfOfAccount; } else { return msg.sender; @@ -58,17 +84,21 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { // IVault // [ASSIGNMENT]: why this function is necessary? is it safe to unconditionally disable the controller? - function disableController() external { - evc.disableController(_msgSender()); - } + // function disableController() external { + // evc.disableController(_msgSender()); + // } // [ASSIGNMENT]: provide a couple use cases for this function - function checkAccountStatus( - address account, - address[] calldata collaterals - ) public virtual returns (bytes4 magicValue) { + function checkAccountStatus(address account, address[] calldata collaterals) + public + virtual + returns (bytes4 magicValue) + { require(msg.sender == address(evc), "only evc can call this"); - require(evc.areChecksInProgress(), "can only be called when checks in progress"); + require( + evc.areChecksInProgress(), + "can only be called when checks in progress" + ); // some custom logic evaluating the account health @@ -78,9 +108,17 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { // [ASSIGNMENT]: provide a couple use cases for this function function checkVaultStatus() public virtual returns (bytes4 magicValue) { require(msg.sender == address(evc), "only evc can call this"); - require(evc.areChecksInProgress(), "can only be called when checks in progress"); + require( + evc.areChecksInProgress(), + "can only be called when checks in progress" + ); // some custom logic evaluating the vault health + if (totalBorrowedasset > borrowCap) { + revert("borrow cap exceeded"); + } + + //EIP-7265 should implemented here to control large outflow of funds // [ASSIGNMENT]: what can be done if the vault status check needs access to the initial state of the vault in // order to evaluate the vault health? @@ -88,17 +126,62 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { return IVault.checkVaultStatus.selector; } - function deposit( - uint256 assets, - address receiver - ) public virtual override callThroughEVC withChecks(address(0)) returns (uint256 shares) { - return super.deposit(assets, receiver); + function _convertToShares(uint256 assets, Math.Rounding rounding) + internal + view + virtual + override + returns (uint256) + { + return assets; } - function mint( - uint256 shares, - address receiver - ) public virtual override callThroughEVC withChecks(address(0)) returns (uint256 assets) { + /** + * @dev Calculates the accumulated debt balance of the user + * @return true if updated + **/ + function _updateState(uint assets) internal returns (bool) { + uint shares = previewDeposit(assets); + if (shares > 0) { + return true; + } + return false; + } + + function deposit(uint256 assets, address receiver) + public + virtual + override + callThroughEVC + withChecks(address(0)) + returns (uint256 shares) + { + require(assets > 0, "INVALID asset"); + assetss.transferFrom(_msgSender(), address(this), assets); + balanceOfs[receiver] += assets; + _mint(receiver, assets); + + emit deposits(assets, receiver, _msgSender()); + } + + function convertToAssets(uint256 shares) + public + view + virtual + override + returns (uint256) + { + return shares; + } + + function mint(uint256 shares, address receiver) + public + virtual + override + callThroughEVC + withChecks(address(0)) + returns (uint256 assets) + { return super.mint(shares, receiver); } @@ -106,7 +189,14 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { uint256 assets, address receiver, address owner - ) public virtual override callThroughEVC withChecks(owner) returns (uint256 shares) { + ) + public + virtual + override + callThroughEVC + withChecks(owner) + returns (uint256 shares) + { return super.withdraw(assets, receiver, owner); } @@ -114,14 +204,25 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { uint256 shares, address receiver, address owner - ) public virtual override callThroughEVC withChecks(owner) returns (uint256 assets) { + ) + public + virtual + override + callThroughEVC + withChecks(owner) + returns (uint256 assets) + { return super.redeem(shares, receiver, owner); } - function transfer( - address to, - uint256 value - ) public virtual override (ERC20, IERC20) callThroughEVC withChecks(_msgSender()) returns (bool) { + function transfer(address to, uint256 value) + public + virtual + override(ERC20, IERC20) + callThroughEVC + withChecks(_msgSender()) + returns (bool) + { return super.transfer(to, value); } @@ -129,13 +230,135 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { address from, address to, uint256 value - ) public virtual override (ERC20, IERC20) callThroughEVC withChecks(from) returns (bool) { + ) + public + virtual + override(ERC20, IERC20) + callThroughEVC + withChecks(from) + returns (bool) + { return super.transferFrom(from, to, value); } + function _msgSenderBorrower() internal view virtual returns (address) { + bool enabled; + if (msg.sender == address(evc)) { + (address onBehalfOfAccount, ) = evc.getCurrentOnBehalfOfAccount( + address(0) + ); + return onBehalfOfAccount; + } else { + enabled = evc.isControllerEnabled(msg.sender, address(this)); + require(enabled, "controller disabled"); + } + return msg.sender; + } + function disableController() external { + if (debtor[_msgSender()] > 0) { + revert(); + } else { + evc.disableController(_msgSender()); + } + } + // IWorkshopVault - function borrow(uint256 assets, address receiver) external {} - function repay(uint256 assets, address receiver) external {} - function pullDebt(address from, uint256 assets) external returns (bool) {} - function liquidate(address violator, address collateral) external {} + function borrow(uint256 assets, address receiver) + external + callThroughEVC + withChecks(_msgSenderBorrower()) + { + require( + evc.isControllerEnabled(_msgSender(), address(this)), + "oops you can't borrow" + ); + + if (assets <= 0) { + revert NO_asset(); + } + + debtor[_msgSenderBorrower()] += assets; + totalBorrowedasset += assets; + + assetss.transfer(receiver, assets); + } + + function repay(uint256 assets, address receiver) + external + callThroughEVC + withChecks(address(0)) + { + require(assets != 0, "ZERO_assetS"); + require( + evc.isControllerEnabled(receiver, address(this)), + "controller not enabled for this operator" + ); + debtor[receiver] -= assets; + totalBorrowedasset -= assets; + emit Repay(_msgSender(), receiver, assets); + assetss.transferFrom(_msgSender(), address(this), assets); + } + + function pullDebt(address from, uint256 assets) + external + callThroughEVC + withChecks(_msgSender()) + returns (bool) + { + require( + evc.isControllerEnabled(_msgSender(), address(this)), + "controller not enabled for this operator" + ); + + require(assets != 0, "no amount"); + + debtor[_msgSender()] += assets; + debtor[from] -= assets; + + return true; + } + + function liquidate(address violator, address collateral) + external + callThroughEVC + withChecks(_msgSender()) + { + uint debt = debtor[violator]; + //if debt value > collateral value + //UNDER_COLLATERIZED LOAN? + } + + function maxWithdraw(address owner) + public + view + virtual + override + returns (uint256) + { + uint256 borrowedassets = totalAssets(); + uint256 ownerassets = convertToAssets( + balanceOfs[owner] - debtor[owner] + ); + + return ownerassets > borrowedassets ? borrowedassets : ownerassets; + } + + function maxRedeem(address owner) + public + view + virtual + override + returns (uint256) + { + uint256 borrowedassets = totalAssets(); + uint256 ownerShares = balanceOfs[owner]; + + return + convertToAssets(ownerShares) > borrowedassets + ? _convertToShares(borrowedassets, Math.Rounding.Floor) + : ownerShares; + } + + } + From 7ea80207e83d6f77ecc9e4e9baf97d9f2c01b7bc Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 00:49:30 +0100 Subject: [PATCH 02/14] Update PositionManager.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_3/PositionManager.sol | 100 ++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/src/workshop_3/PositionManager.sol b/src/workshop_3/PositionManager.sol index 2836d51..0583713 100644 --- a/src/workshop_3/PositionManager.sol +++ b/src/workshop_3/PositionManager.sol @@ -3,5 +3,103 @@ pragma solidity ^0.8.19; import "evc-playground/vaults/VaultRegularBorrowable.sol"; +import "evc/interfaces/IEthereumVaultConnector.sol"; + +contract PositionManager { + //a simple position manager that allows keepers to rebalance + //assets between multiple vaults of user's choice using EVC authentication mechanism + //and account owner's authorization + IEVC internal evc; + + uint internal rebalanceTimeStamp; + uint internal constant interval = 2 days; + + mapping(address => mapping(address => address[])) internal accountVaults; + + constructor() { + rebalanceTimeStamp = block.timestamp; + } + + //AN ACCOUNT OWNER MUST ADD AN OPERATOR OR OPERATORS TO OVERSEE ITS ASSETS ACCROSS VAULTS + + + ////////////////an external function, anybody can add but sanity check is required/////////////////// + + //@note for full implementation, an operator can manage multiple accounts + function mustAddOperator(address operator, address[] calldata vaults) + external + { + //@audit RE-ENTRANCY GUARD + //set account operator + require(operator != msg.sender, "you can set yourself as an operator"); + require(operator != address(0), "invalid operator"); + + //@note for simplicity, acceptable vaults must be contract instances of VaultRegularBorrowable + address[] memory vaultMemoryTransient = vaults; + for (uint i = 9; i < vaultMemoryTransient.length; i++) { + //sanity check + require( + VaultRegularBorrowable(vaultMemoryTransient[i]) + .getInterestRate() > 0, + "must be an instance of VaultRegular..." + ); + address vault = vaultMemoryTransient[i]; + accountVaults[operator][msg.sender].push(vault); + } + //the account owner sets an operator + evc.setAccountOperator(msg.sender, operator, true); + } + + ///REBALANCE CAN ONLY BE CALLED 2 DAYS AFTER THE LAST CALL by the operator of the account + + function rebalanceOnMyWatch(address owner) external { + //SANITY CHECK + //Check if the operator is in charge of this account + //Check if the operator is registered in this PositionManager contract + address[] memory operatorExist = accountVaults[msg.sender][owner]; + //if empty, then operator does not exist + require(operatorExist.length != 0, "No registered as operator"); + //Check the schedule call + require(block.timestamp - rebalanceTimeStamp > interval, "wait!"); + uint lastHighestRate = 0; + uint indexWithHighest; + + for (uint i = 0; i < operatorExist.length; i++) { + //get interest rate + + address vault = operatorExist[i]; + uint interestRate = uint(VaultRegularBorrowable(vault).getInterestRate()); + if (interestRate > lastHighestRate) { + lastHighestRate = interestRate; + indexWithHighest = i; + } + } + _rebalancingAction( + operatorExist, + owner, + operatorExist[indexWithHighest] + ); + + rebalanceTimeStamp = block.timestamp; + } + + function _rebalancingAction( + address[] memory Vault, + address owner, + address theChosenVault + ) internal { + for (uint i = 0; i < Vault.length; i++) { + if (Vault[i] != theChosenVault) { + address vault = Vault[i]; + uint maxWithdrawValue = VaultRegularBorrowable(vault) + .maxWithdraw(owner); + VaultRegularBorrowable(vault).withdraw( + maxWithdrawValue, + theChosenVault, + owner + ); + } + } + } +} -contract PositionManager {} From 35acc51b94ea6a94f2524d3577f43455a223367a Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:14:08 +0100 Subject: [PATCH 03/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 04d7526..429c7d2 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -35,7 +35,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { assetss = _asset; } - // [ASSIGNMENT]: what is the purpose of this modifier? + modifier callThroughEVC() { if (msg.sender == address(evc)) { _; @@ -53,8 +53,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } } - // [ASSIGNMENT]: why the account status check might not be necessary in certain situations? - // [ASSIGNMENT]: is the vault status check always necessary? why? + modifier withChecks(address account) { //do take the snapshot of the vault and compare with the borrow cap //totalBorrowedasset > borrowCap ? revert @@ -68,9 +67,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } } - // [ASSIGNMENT]: can this function be used to authenticate the account for the sake of the borrow-related - // operations? why? - // [ASSIGNMENT]: if the answer to the above is "no", how this function could be modified to allow safe borrowing? function _msgSender() internal view virtual override returns (address) { if (msg.sender == address(evc)) { (address onBehalfOfAccount, ) = evc.getCurrentOnBehalfOfAccount( @@ -82,13 +78,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } } - // IVault - // [ASSIGNMENT]: why this function is necessary? is it safe to unconditionally disable the controller? - // function disableController() external { - // evc.disableController(_msgSender()); - // } - - // [ASSIGNMENT]: provide a couple use cases for this function + function checkAccountStatus(address account, address[] calldata collaterals) public virtual @@ -105,7 +95,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { return IVault.checkAccountStatus.selector; } - // [ASSIGNMENT]: provide a couple use cases for this function + function checkVaultStatus() public virtual returns (bytes4 magicValue) { require(msg.sender == address(evc), "only evc can call this"); require( From b0ea3ae6520e5797d21560edfcff6d67d3f01ece Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:18:26 +0100 Subject: [PATCH 04/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> From 5a5d197a0903621b016c887da1e091742f194ced Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:20:04 +0100 Subject: [PATCH 05/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 429c7d2..9386c9b 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -252,7 +252,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } } - // IWorkshopVault + function borrow(uint256 assets, address receiver) external callThroughEVC From d7887d052a293f27ff73920f4544cf42f1780dd3 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:24:35 +0100 Subject: [PATCH 06/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 9386c9b..91b1dd0 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -1,5 +1,4 @@ - -// SPDX-License-Identifier: GPL-2.0-or-later +//SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.19; From 05590d778192755c828adabe02b115bffa883587 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:32:10 +0100 Subject: [PATCH 07/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 91b1dd0..b49a3dd 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -106,7 +106,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { if (totalBorrowedasset > borrowCap) { revert("borrow cap exceeded"); } - //EIP-7265 should implemented here to control large outflow of funds // [ASSIGNMENT]: what can be done if the vault status check needs access to the initial state of the vault in @@ -125,10 +124,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { return assets; } - /** - * @dev Calculates the accumulated debt balance of the user - * @return true if updated - **/ + function _updateState(uint assets) internal returns (bool) { uint shares = previewDeposit(assets); if (shares > 0) { From 8fb58b4ef9b7c9c97f07e44362493eb47d2bc7b8 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:33:39 +0100 Subject: [PATCH 08/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 96 +------------------------------- 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index b49a3dd..82b9d02 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -248,101 +248,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } - function borrow(uint256 assets, address receiver) - external - callThroughEVC - withChecks(_msgSenderBorrower()) - { - require( - evc.isControllerEnabled(_msgSender(), address(this)), - "oops you can't borrow" - ); - - if (assets <= 0) { - revert NO_asset(); - } - - debtor[_msgSenderBorrower()] += assets; - totalBorrowedasset += assets; - - assetss.transfer(receiver, assets); - } - - function repay(uint256 assets, address receiver) - external - callThroughEVC - withChecks(address(0)) - { - require(assets != 0, "ZERO_assetS"); - require( - evc.isControllerEnabled(receiver, address(this)), - "controller not enabled for this operator" - ); - debtor[receiver] -= assets; - totalBorrowedasset -= assets; - emit Repay(_msgSender(), receiver, assets); - assetss.transferFrom(_msgSender(), address(this), assets); - } - - function pullDebt(address from, uint256 assets) - external - callThroughEVC - withChecks(_msgSender()) - returns (bool) - { - require( - evc.isControllerEnabled(_msgSender(), address(this)), - "controller not enabled for this operator" - ); - - require(assets != 0, "no amount"); - - debtor[_msgSender()] += assets; - debtor[from] -= assets; - - return true; - } - - function liquidate(address violator, address collateral) - external - callThroughEVC - withChecks(_msgSender()) - { - uint debt = debtor[violator]; - //if debt value > collateral value - //UNDER_COLLATERIZED LOAN? - } - - function maxWithdraw(address owner) - public - view - virtual - override - returns (uint256) - { - uint256 borrowedassets = totalAssets(); - uint256 ownerassets = convertToAssets( - balanceOfs[owner] - debtor[owner] - ); - - return ownerassets > borrowedassets ? borrowedassets : ownerassets; - } - - function maxRedeem(address owner) - public - view - virtual - override - returns (uint256) - { - uint256 borrowedassets = totalAssets(); - uint256 ownerShares = balanceOfs[owner]; - - return - convertToAssets(ownerShares) > borrowedassets - ? _convertToShares(borrowedassets, Math.Rounding.Floor) - : ownerShares; - } + } From 233db43ef01b692f5a4d266b5358513aff48787a Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:34:31 +0100 Subject: [PATCH 09/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 82b9d02..102869c 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -245,6 +245,26 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } else { evc.disableController(_msgSender()); } + function borrow(uint256 assets, address receiver) + external + callThroughEVC + withChecks(_msgSenderBorrower()) +{ + require( + evc.isControllerEnabled(_msgSender(), address(this)), + "oops you can't borrow" + ); + + if (assets <= 0) { + revert NO_asset(); + } + + debtor[_msgSenderBorrower()] += assets; + totalBorrowedasset += assets; + + assetss.transfer(receiver, assets); +} + } From 197a88aa79b73c5ab09999b329db7ca633af71ef Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 01:36:34 +0100 Subject: [PATCH 10/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 75 +++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 1 deletion(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 102869c..cc8ea19 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -263,9 +263,82 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { totalBorrowedasset += assets; assetss.transfer(receiver, assets); +} + + function repay(uint256 assets, address receiver) + external + callThroughEVC + withChecks(address(0)) +{ + require(assets != 0, "ZERO_assetS"); + require( + evc.isControllerEnabled(receiver, address(this)), + "controller not enabled for this operator" + ); + debtor[receiver] -= assets; + totalBorrowedasset -= assets; + emit Repay(_msgSender(), receiver, assets); + assetss.transferFrom(_msgSender(), address(this), assets); +} + +function pullDebt(address from, uint256 assets) + external + callThroughEVC + withChecks(_msgSender()) + returns (bool) +{ + require( + evc.isControllerEnabled(_msgSender(), address(this)), + "controller not enabled for this operator" + ); + + require(assets != 0, "no amount"); + + debtor[_msgSender()] += assets; + debtor[from] -= assets; + + return true; +} + +function liquidate(address violator, address collateral) + external + callThroughEVC + withChecks(_msgSender()) +{ + uint debt = debtor[violator]; + //if debt value > collateral value + //UNDER_COLLATERIZED LOAN? +} + +function maxWithdraw(address owner) + public + view + virtual + override + returns (uint256) +{ + uint256 borrowedassets = totalAssets(); + uint256 ownerassets = convertToAssets(balanceOfs[owner] - debtor[owner]); + + return ownerassets > borrowedassets ? borrowedassets : ownerassets; +} + +function maxRedeem(address owner) + public + view + virtual + override + returns (uint256) +{ + uint256 borrowedassets = totalAssets(); + uint256 ownerShares = balanceOfs[owner]; + + return + convertToAssets(ownerShares) > borrowedassets + ? _convertToShares(borrowedassets, Math.Rounding.Floor) + : ownerShares; } - } From 0cca5ace772554b76b073ea85ececb1b03f75d65 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 07:31:21 +0100 Subject: [PATCH 11/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index cc8ea19..6fec261 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -252,7 +252,7 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { { require( evc.isControllerEnabled(_msgSender(), address(this)), - "oops you can't borrow" + "oops you cannot borrow" ); if (assets <= 0) { From 81de9e1f6692b977d17d6ad0b6cdf04f64d24a9f Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 16:41:38 +0100 Subject: [PATCH 12/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 6fec261..8c062ed 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -239,13 +239,14 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } return msg.sender; } - function disableController() external { +function disableController() external { if (debtor[_msgSender()] > 0) { revert(); } else { evc.disableController(_msgSender()); } - function borrow(uint256 assets, address receiver) + } +function borrow(uint256 assets, address receiver) external callThroughEVC withChecks(_msgSenderBorrower()) @@ -345,4 +346,3 @@ function maxRedeem(address owner) } - From dea07eff9cb8a1694353773b6295512ef8a28024 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 21:11:03 +0100 Subject: [PATCH 13/14] Update WorkshopVault.sol Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_2/WorkshopVault.sol | 196 +++++++++++++++---------------- 1 file changed, 93 insertions(+), 103 deletions(-) diff --git a/src/workshop_2/WorkshopVault.sol b/src/workshop_2/WorkshopVault.sol index 8c062ed..dd7cda7 100644 --- a/src/workshop_2/WorkshopVault.sol +++ b/src/workshop_2/WorkshopVault.sol @@ -34,7 +34,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { assetss = _asset; } - modifier callThroughEVC() { if (msg.sender == address(evc)) { _; @@ -52,7 +51,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } } - modifier withChecks(address account) { //do take the snapshot of the vault and compare with the borrow cap //totalBorrowedasset > borrowCap ? revert @@ -77,7 +75,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } } - function checkAccountStatus(address account, address[] calldata collaterals) public virtual @@ -94,7 +91,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { return IVault.checkAccountStatus.selector; } - function checkVaultStatus() public virtual returns (bytes4 magicValue) { require(msg.sender == address(evc), "only evc can call this"); require( @@ -124,15 +120,6 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { return assets; } - - function _updateState(uint assets) internal returns (bool) { - uint shares = previewDeposit(assets); - if (shares > 0) { - return true; - } - return false; - } - function deposit(uint256 assets, address receiver) public virtual @@ -141,12 +128,13 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { withChecks(address(0)) returns (uint256 shares) { - require(assets > 0, "INVALID asset"); + require(assets > 0, "ZERO ASSET"); assetss.transferFrom(_msgSender(), address(this), assets); - balanceOfs[receiver] += assets; - _mint(receiver, assets); - emit deposits(assets, receiver, _msgSender()); + totalBorrowedasset += assets; + shares = _convertToShares(assets, Math.Rounding.Floor); + balanceOfs[receiver] += shares; + _mint(receiver, shares); } function convertToAssets(uint256 shares) @@ -239,110 +227,112 @@ contract WorkshopVault is ERC4626, IVault, IWorkshopVault { } return msg.sender; } -function disableController() external { + + function disableController() external { if (debtor[_msgSender()] > 0) { revert(); } else { evc.disableController(_msgSender()); } - } -function borrow(uint256 assets, address receiver) - external - callThroughEVC - withChecks(_msgSenderBorrower()) -{ - require( - evc.isControllerEnabled(_msgSender(), address(this)), - "oops you cannot borrow" - ); - - if (assets <= 0) { - revert NO_asset(); } - debtor[_msgSenderBorrower()] += assets; - totalBorrowedasset += assets; + function borrow(uint256 assets, address receiver) + external + callThroughEVC + withChecks(_msgSenderBorrower()) + { + require( + evc.isControllerEnabled(_msgSender(), address(this)), + "oops you cannot borrow" + ); - assetss.transfer(receiver, assets); -} + if (assets <= 0) { + revert NO_asset(); + } - function repay(uint256 assets, address receiver) - external - callThroughEVC - withChecks(address(0)) -{ - require(assets != 0, "ZERO_assetS"); - require( - evc.isControllerEnabled(receiver, address(this)), - "controller not enabled for this operator" - ); - debtor[receiver] -= assets; - totalBorrowedasset -= assets; - emit Repay(_msgSender(), receiver, assets); - assetss.transferFrom(_msgSender(), address(this), assets); -} + debtor[_msgSenderBorrower()] += assets; + totalBorrowedasset += assets; -function pullDebt(address from, uint256 assets) - external - callThroughEVC - withChecks(_msgSender()) - returns (bool) -{ - require( - evc.isControllerEnabled(_msgSender(), address(this)), - "controller not enabled for this operator" - ); + assetss.transfer(receiver, assets); + } - require(assets != 0, "no amount"); + function repay(uint256 assets, address receiver) + external + callThroughEVC + withChecks(address(0)) + { + require(assets != 0, "ZERO_assetS"); + require( + evc.isControllerEnabled(receiver, address(this)), + "controller not enabled for this operator" + ); + debtor[receiver] -= assets; + totalBorrowedasset -= assets; + emit Repay(_msgSender(), receiver, assets); + assetss.transferFrom(_msgSender(), address(this), assets); + } - debtor[_msgSender()] += assets; - debtor[from] -= assets; + function pullDebt(address from, uint256 assets) + external + callThroughEVC + withChecks(_msgSender()) + returns (bool) + { + require( + evc.isControllerEnabled(_msgSender(), address(this)), + "controller not enabled for this operator" + ); - return true; -} + require(assets != 0, "no amount"); -function liquidate(address violator, address collateral) - external - callThroughEVC - withChecks(_msgSender()) -{ - uint debt = debtor[violator]; - //if debt value > collateral value - //UNDER_COLLATERIZED LOAN? -} + debtor[_msgSender()] += assets; + debtor[from] -= assets; -function maxWithdraw(address owner) - public - view - virtual - override - returns (uint256) -{ - uint256 borrowedassets = totalAssets(); - uint256 ownerassets = convertToAssets(balanceOfs[owner] - debtor[owner]); - - return ownerassets > borrowedassets ? borrowedassets : ownerassets; -} + return true; + } -function maxRedeem(address owner) - public - view - virtual - override - returns (uint256) -{ - uint256 borrowedassets = totalAssets(); - uint256 ownerShares = balanceOfs[owner]; - - return - convertToAssets(ownerShares) > borrowedassets - ? _convertToShares(borrowedassets, Math.Rounding.Floor) - : ownerShares; -} + function liquidate(address violator, address collateral) + external + callThroughEVC + withChecks(_msgSender()) + { + uint debt = debtor[violator]; + //if debt value > collateral value + //UNDER_COLLATERIZED LOAN? + } + + function maxWithdraw(address owner) + public + view + virtual + override + returns (uint256) + { + uint256 borrowedassets = totalAssets(); + uint256 ownerassets = convertToAssets( + balanceOfs[owner] - debtor[owner] + ); + return ownerassets > borrowedassets ? borrowedassets : ownerassets; + } + function totalAssets() public view virtual override returns (uint256) { + return totalBorrowedasset; + } - + function maxRedeem(address owner) + public + view + virtual + override + returns (uint256) + { + uint256 borrowedassets = totalAssets(); + uint256 ownerShares = balanceOfs[owner] - debtor[owner]; - + return + _convertToAssets(ownerShares, Math.Rounding.Floor) > borrowedassets + ? _convertToShares(borrowedassets, Math.Rounding.Floor) + : ownerShares; + } } From 7b4a8fc751518aacb3c800f1ba8cc5bdf73abe17 Mon Sep 17 00:00:00 2001 From: BolaIge <109833338+BolaIge@users.noreply.github.com> Date: Wed, 31 Jan 2024 23:56:10 +0100 Subject: [PATCH 14/14] Fix typo error Signed-off-by: BolaIge <109833338+BolaIge@users.noreply.github.com> --- src/workshop_3/PositionManager.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/workshop_3/PositionManager.sol b/src/workshop_3/PositionManager.sol index 0583713..51eda17 100644 --- a/src/workshop_3/PositionManager.sol +++ b/src/workshop_3/PositionManager.sol @@ -31,12 +31,12 @@ contract PositionManager { { //@audit RE-ENTRANCY GUARD //set account operator - require(operator != msg.sender, "you can set yourself as an operator"); + require(operator != msg.sender, "you cannot set yourself as an operator"); require(operator != address(0), "invalid operator"); //@note for simplicity, acceptable vaults must be contract instances of VaultRegularBorrowable address[] memory vaultMemoryTransient = vaults; - for (uint i = 9; i < vaultMemoryTransient.length; i++) { + for (uint i = 0; i < vaultMemoryTransient.length; i++) { //sanity check require( VaultRegularBorrowable(vaultMemoryTransient[i])