From 668436aba305ead8a5fca12da77afd6d5f9fba38 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 10:34:31 -0600 Subject: [PATCH 01/11] chore: unchecked --- src/L1YearnEscrow.sol | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/src/L1YearnEscrow.sol b/src/L1YearnEscrow.sol index fb2702f..6030228 100644 --- a/src/L1YearnEscrow.sol +++ b/src/L1YearnEscrow.sol @@ -181,7 +181,10 @@ contract L1YearnEscrow is L1Escrow { // Check again to account for if there was loose underlying if (amount > maxWithdraw) { // Send an equivalent amount of shares for the difference. - uint256 shares = _vault.convertToShares(amount - maxWithdraw); + uint256 shares; + unchecked { + shares = _vault.convertToShares(amount - maxWithdraw); + } _vault.transfer(destinationAddress, shares); if (maxWithdraw == 0) return; amount = maxWithdraw; @@ -249,11 +252,14 @@ contract L1YearnEscrow is L1Escrow { // Deposit any loose funds over minimum buffer uint256 balance = originToken.balanceOf(address(this)); uint256 _minimumBuffer = $.minimumBuffer; - if (balance > _minimumBuffer) - IVault(_vaultAddress).deposit( - balance - _minimumBuffer, - address(this) - ); + if (balance > _minimumBuffer) { + unchecked { + IVault(_vaultAddress).deposit( + balance - _minimumBuffer, + address(this) + ); + } + } } // Update Storage @@ -285,10 +291,15 @@ contract L1YearnEscrow is L1Escrow { if (balance > _minimumBuffer) { // Deposit the difference. - $.vaultAddress.deposit(balance - _minimumBuffer, address(this)); + unchecked { + $.vaultAddress.deposit(balance - _minimumBuffer, address(this)); + } } else if (balance < _minimumBuffer) { // Withdraw the difference - uint256 diff = _minimumBuffer - balance; + uint256 diff; + unchecked { + diff = _minimumBuffer - balance; + } uint256 available = $.vaultAddress.maxWithdraw(address(this)); // Withdraw the min between the difference or what is available. From 4935736a2be19fdfdf9d9bf81878a80ef5a91621 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:11:51 -0600 Subject: [PATCH 02/11] chore: use local version --- src/L1YearnEscrow.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/L1YearnEscrow.sol b/src/L1YearnEscrow.sol index 6030228..b0313c7 100644 --- a/src/L1YearnEscrow.sol +++ b/src/L1YearnEscrow.sol @@ -97,7 +97,7 @@ contract L1YearnEscrow is L1Escrow { ); // Max approve the vault - originTokenAddress().forceApprove(_vaultAddress, 2 ** 256 - 1); + IERC20(_originTokenAddress).forceApprove(_vaultAddress, 2 ** 256 - 1); // Set the vault variable VaultStorage storage $ = _getVaultStorage(); $.vaultAddress = IVault(_vaultAddress); From 5d9809930915c43d2045a11087d4db4f9fbcf225 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:15:08 -0600 Subject: [PATCH 03/11] feat: check unlock time --- src/RoleManager.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/RoleManager.sol b/src/RoleManager.sol index 0eee8f4..6cd3544 100644 --- a/src/RoleManager.sol +++ b/src/RoleManager.sol @@ -523,6 +523,8 @@ contract RoleManager is Positions { function setDefaultProfitMaxUnlock( uint256 _newDefaultProfitMaxUnlock ) external virtual onlyPositionHolder(GOVERNATOR) { + require(_newDefaultProfitMaxUnlock != 0, "too short"); + require(_newDefaultProfitMaxUnlock <= 31_556_952, "too long"); defaultProfitMaxUnlock = _newDefaultProfitMaxUnlock; emit UpdateDefaultProfitMaxUnlock(_newDefaultProfitMaxUnlock); From 127b7356b4c63ce0cc895527c90f7f40df8ba722 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:16:16 -0600 Subject: [PATCH 04/11] fix: initialize 0 --- src/RoleManager.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/RoleManager.sol b/src/RoleManager.sol index 6cd3544..c482711 100644 --- a/src/RoleManager.sol +++ b/src/RoleManager.sol @@ -470,7 +470,7 @@ contract RoleManager is Positions { uint256 _role ) external virtual onlyPositionHolder(CZAR) { address _vault; - for (uint256 i = 0; i < _vaults.length; ++i) { + for (uint256 i; i < _vaults.length; ++i) { _vault = _vaults[i]; // Make sure the vault is added to this Role Manager. require(vaultConfig[_vault].asset != address(0), "vault not added"); From 8c7cdf8fb3013f767791acb8fb3e9109befc6938 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:29:37 -0600 Subject: [PATCH 05/11] fix: check address 0 --- src/L1Deployer.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/L1Deployer.sol b/src/L1Deployer.sol index 8cbae3a..6f24595 100644 --- a/src/L1Deployer.sol +++ b/src/L1Deployer.sol @@ -163,6 +163,7 @@ contract L1Deployer is DeployerBase { address _l2Deployer ) external virtual { require(getRollupContract(_rollupID) == address(0), "registered"); + require(_l1EscrowManager != address(0), "ZERO ADDRESS"); require(_l2Deployer != address(0), "ZERO ADDRESS"); IPolygonRollupContract _rollupContract = rollupManager From 1a8c7743fb3d97acbf10c84ea5d250797ec78f27 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:39:58 -0600 Subject: [PATCH 06/11] chore: add modifier --- src/RoleManager.sol | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/RoleManager.sol b/src/RoleManager.sol index c482711..64717f0 100644 --- a/src/RoleManager.sol +++ b/src/RoleManager.sol @@ -42,6 +42,17 @@ contract RoleManager is Positions { uint96 index; } + /// @notice Make sure the vault has been added to the role manager. + modifier vaultIsAdded(address _vault) { + _vaultIsAdded(_vault); + _; + } + + /// @notice Check if the vault is added to the Role Manager. + function _vaultIsAdded(address _vault) internal view virtual { + require(vaultConfig[_vault].asset != address(0), "vault not added"); + } + /// @notice ID to use for the L1 uint32 internal constant ORIGIN_NETWORK_ID = 0; @@ -378,10 +389,7 @@ contract RoleManager is Positions { function updateDebtAllocator( address _vault, address _debtAllocator - ) public virtual onlyPositionHolder(MANAGEMENT) { - // Make sure the vault has been added to the role manager. - require(vaultConfig[_vault].asset != address(0), "vault not added"); - + ) public virtual vaultIsAdded(_vault) onlyPositionHolder(MANAGEMENT) { // Remove the roles from the old allocator. _setRole(_vault, Position(vaultConfig[_vault].debtAllocator, 0)); @@ -406,10 +414,7 @@ contract RoleManager is Positions { function updateKeeper( address _vault, address _keeper - ) external virtual onlyPositionHolder(MANAGEMENT) { - // Make sure the vault has been added to the role manager. - require(vaultConfig[_vault].asset != address(0), "vault not added"); - + ) external virtual vaultIsAdded(_vault) onlyPositionHolder(MANAGEMENT) { // Remove the roles from the old keeper if active. address defaultKeeper = getPositionHolder(KEEPER); if ( @@ -429,18 +434,16 @@ contract RoleManager is Positions { */ function removeVault( address _vault - ) external virtual onlyPositionHolder(CZAR) { - // Get the vault specific config. - VaultConfig memory config = vaultConfig[_vault]; - // Make sure the vault has been added to the role manager. - require(config.asset != address(0), "vault not added"); - + ) external virtual vaultIsAdded(_vault) onlyPositionHolder(CZAR) { // Transfer the role manager position. IVault(_vault).transfer_role_manager(chad); // Address of the vault to replace it with. address vaultToMove = vaults[vaults.length - 1]; + // Get the vault specific config. + VaultConfig memory config = vaultConfig[_vault]; + // Move the last vault to the index of `_vault` vaults[config.index] = vaultToMove; vaultConfig[vaultToMove].index = config.index; From c2d9f9b797a7524558141078cb4fb77a4ae7ed3c Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:50:37 -0600 Subject: [PATCH 07/11] chore: concat strings --- src/RoleManager.sol | 16 +++++++++++----- test/L1Deployer.t.sol | 2 ++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/RoleManager.sol b/src/RoleManager.sol index 64717f0..2dc34ab 100644 --- a/src/RoleManager.sol +++ b/src/RoleManager.sol @@ -196,15 +196,21 @@ contract RoleManager is Positions { // Append the rollup ID for the name and symbol of custom vaults. string memory _id = _rollupID == ORIGIN_NETWORK_ID ? "" - : string(abi.encodePacked("-", Strings.toString(_rollupID))); + : string.concat("-", Strings.toString(_rollupID)); // Name is "{SYMBOL}-STB yVault" - string memory _name = string( - abi.encodePacked(ERC20(_asset).symbol(), "-STB", _id, " yVault") + string memory _name = string.concat( + ERC20(_asset).symbol(), + "-STB", + _id, + " yVault" ); + // Symbol is "stb{SYMBOL}". - string memory _symbol = string( - abi.encodePacked("stb", ERC20(_asset).symbol(), _id) + string memory _symbol = string.concat( + "stb", + ERC20(_asset).symbol(), + _id ); // Deploy through the registry so it is automatically endorsed. diff --git a/test/L1Deployer.t.sol b/test/L1Deployer.t.sol index 6886917..2ca35b4 100644 --- a/test/L1Deployer.t.sol +++ b/test/L1Deployer.t.sol @@ -161,6 +161,8 @@ contract L1DeployerTest is Setup { IVault vault = IVault(_vault); + assertEq(vault.name(), "DAI-STB yVault"); + assertEq(vault.symbol(), "stbDAI"); assertEq(vault.accountant(), address(accountant)); assertEq(vault.asset(), address(asset)); assertEq(vault.deposit_limit(), 2 ** 256 - 1); From 5e34d2302c270e4bf169888b6240198c7d8d4bf9 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 17:52:56 -0600 Subject: [PATCH 08/11] chore: withdraw comment --- src/L1YearnEscrow.sol | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/L1YearnEscrow.sol b/src/L1YearnEscrow.sol index b0313c7..d2b6200 100644 --- a/src/L1YearnEscrow.sol +++ b/src/L1YearnEscrow.sol @@ -223,6 +223,8 @@ contract L1YearnEscrow is L1Escrow { /** * @dev Update the vault to deploy funds into. * Will fully withdraw from the old vault. + * The current vault must be completely liquid for this to succeed. + * * @param _vaultAddress Address of the new vault to use. */ function updateVault( From 54346daa947e5bc0a1b2e9413440f7aa10f32dd6 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 18:21:21 -0600 Subject: [PATCH 09/11] chore: chache --- src/L1YearnEscrow.sol | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/L1YearnEscrow.sol b/src/L1YearnEscrow.sol index d2b6200..77d5358 100644 --- a/src/L1YearnEscrow.sol +++ b/src/L1YearnEscrow.sol @@ -114,19 +114,14 @@ contract L1YearnEscrow is L1Escrow { function _receiveTokens( uint256 amount ) internal virtual override whenNotPaused { - originTokenAddress().safeTransferFrom( - msg.sender, - address(this), - amount - ); + IERC20 originToken = originTokenAddress(); + originToken.safeTransferFrom(msg.sender, address(this), amount); VaultStorage storage $ = _getVaultStorage(); uint256 _minimumBuffer = $.minimumBuffer; // Deposit to the vault if above buffer if (_minimumBuffer != 0) { - uint256 underlyingBalance = originTokenAddress().balanceOf( - address(this) - ); + uint256 underlyingBalance = originToken.balanceOf(address(this)); if (underlyingBalance <= _minimumBuffer) return; From de11c988ee188f4d3531f156cd165e276923612a Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Wed, 22 May 2024 18:25:15 -0600 Subject: [PATCH 10/11] chore: external functions --- src/L1Deployer.sol | 2 +- src/RoleManager.sol | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/L1Deployer.sol b/src/L1Deployer.sol index 6f24595..55a6bb7 100644 --- a/src/L1Deployer.sol +++ b/src/L1Deployer.sol @@ -367,7 +367,7 @@ contract L1Deployer is DeployerBase { */ function getEscrowManager( uint32 _rollupID - ) public view virtual returns (address) { + ) external view virtual returns (address) { return _chainConfig[_rollupID].escrowManager; } diff --git a/src/RoleManager.sol b/src/RoleManager.sol index 2dc34ab..e1a8779 100644 --- a/src/RoleManager.sol +++ b/src/RoleManager.sol @@ -579,7 +579,7 @@ contract RoleManager is Positions { * @param _asset The underlying asset used. * @return The default vault for the specified `_asset`. */ - function getVault(address _asset) public view virtual returns (address) { + function getVault(address _asset) external view virtual returns (address) { return getVault(_asset, ORIGIN_NETWORK_ID); } @@ -611,7 +611,7 @@ contract RoleManager is Positions { */ function isVaultsRoleManager( address _vault - ) public view virtual returns (bool) { + ) external view virtual returns (bool) { return vaultConfig[_vault].asset != address(0); } From 95febd007e77a60b095d127c3107b774016daccf Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Thu, 23 May 2024 10:53:30 -0600 Subject: [PATCH 11/11] fix: custom vault flow --- src/L1Deployer.sol | 26 ++++++++------------------ 1 file changed, 8 insertions(+), 18 deletions(-) diff --git a/src/L1Deployer.sol b/src/L1Deployer.sol index 55a6bb7..f5f851a 100644 --- a/src/L1Deployer.sol +++ b/src/L1Deployer.sol @@ -219,6 +219,8 @@ contract L1Deployer is DeployerBase { /** * @notice Creates a new custom vault and escrow for a specific asset on the specified rollup. + * @dev If the L1 escrow already exists the Rollup admin + * will need to update the vault manually on the escrow. * @param _rollupID The ID of the rollup. * @param _asset The address of the asset for which the vault and escrow are created. * @return _l1Escrow The address of the L1 escrow. @@ -234,7 +236,11 @@ contract L1Deployer is DeployerBase { returns (address _l1Escrow, address _vault) { _vault = roleManager.newVault(_rollupID, _asset); - _l1Escrow = _newCustomVault(_rollupID, _asset, _vault); + // Deploy an L1 escrow if it does not already exist. + _l1Escrow = getEscrow(_rollupID, _asset); + if (_l1Escrow == address(0)) { + _l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault); + } } /** @@ -251,23 +257,7 @@ contract L1Deployer is DeployerBase { ) external virtual onlyRollupAdmin(_rollupID) returns (address _l1Escrow) { // Make sure the vault has been registered. require(roleManager.isVaultsRoleManager(_vault), "!role manager"); - _l1Escrow = _newCustomVault(_rollupID, _asset, _vault); - } - - /** - * @dev Deploys an L1 Escrow for a custom vault if one does not exist. - * Will store all relevant information as well. - */ - function _newCustomVault( - uint32 _rollupID, - address _asset, - address _vault - ) internal virtual returns (address _l1Escrow) { - _l1Escrow = getEscrow(_rollupID, _asset); - - if (_l1Escrow == address(0)) { - _l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault); - } + _l1Escrow = _deployL1Escrow(_rollupID, _asset, _vault); } /*//////////////////////////////////////////////////////////////