|
| 1 | +// SPDX-License-Identifier: GPL-3.0 |
| 2 | +pragma solidity 0.8.19; |
| 3 | + |
| 4 | +import {IERC20 as IERC20Prod} from "openzeppelin-solc-0.8/token/ERC20/IERC20.sol"; |
| 5 | + |
| 6 | +import { |
| 7 | + IExternalPosition as IExternalPositionProd |
| 8 | +} from "contracts/release/extensions/external-position-manager/IExternalPosition.sol"; |
| 9 | +import { |
| 10 | + IExternalPositionParser as IExternalPositionParserProd |
| 11 | +} from "contracts/release/extensions/external-position-manager/IExternalPositionParser.sol"; |
| 12 | + |
| 13 | +import {IntegrationTest} from "tests/bases/IntegrationTest.sol"; |
| 14 | +import {IERC20} from "tests/interfaces/external/IERC20.sol"; |
| 15 | +import {IComptrollerLib} from "tests/interfaces/internal/IComptrollerLib.sol"; |
| 16 | +import {IDeprecatedPosition} from "tests/interfaces/internal/IDeprecatedPosition.sol"; |
| 17 | +import {IVaultLib} from "tests/interfaces/internal/IVaultLib.sol"; |
| 18 | + |
| 19 | +contract MockExternalPositionLib is IExternalPositionProd { |
| 20 | + function init(bytes memory) external pure override {} |
| 21 | + |
| 22 | + function receiveCallFromVault(bytes memory) external pure override {} |
| 23 | + |
| 24 | + function getDebtAssets() external pure override returns (address[] memory, uint256[] memory) {} |
| 25 | + |
| 26 | + function getManagedAssets() external pure override returns (address[] memory, uint256[] memory) {} |
| 27 | +} |
| 28 | + |
| 29 | +contract MockExternalPositionParser is IExternalPositionParserProd { |
| 30 | + function parseAssetsForAction(address, uint256, bytes memory) |
| 31 | + external |
| 32 | + returns (address[] memory, uint256[] memory, address[] memory) |
| 33 | + {} |
| 34 | + |
| 35 | + function parseInitArgs(address, bytes memory) external returns (bytes memory) {} |
| 36 | +} |
| 37 | + |
| 38 | +contract DeprecatedPositionTest is IntegrationTest { |
| 39 | + IERC20 usdtToken = IERC20(ETHEREUM_USDT); // Use USDT because it has annoying behavior |
| 40 | + |
| 41 | + IDeprecatedPosition deprecatedPosition; |
| 42 | + |
| 43 | + address fundOwner; |
| 44 | + address comptrollerProxyAddress; |
| 45 | + address vaultProxyAddress; |
| 46 | + |
| 47 | + // Creates a fund that holds a deprecated position |
| 48 | + function setUp() public override { |
| 49 | + setUpMainnetEnvironment(); |
| 50 | + |
| 51 | + // Deploy initial EP contracts |
| 52 | + address initialLibAddress = address(new MockExternalPositionLib()); |
| 53 | + address initialParserAddress = address(new MockExternalPositionParser()); |
| 54 | + |
| 55 | + // Register the EP type with its initial contracts |
| 56 | + uint256 typeId = registerExternalPositionType({ |
| 57 | + _externalPositionManager: core.release.externalPositionManager, |
| 58 | + _label: "POSITION_TO_BE_DEPRECATED", |
| 59 | + _lib: initialLibAddress, |
| 60 | + _parser: initialParserAddress |
| 61 | + }); |
| 62 | + |
| 63 | + // Create a fund |
| 64 | + IComptrollerLib comptrollerProxy; |
| 65 | + IVaultLib vaultProxy; |
| 66 | + (comptrollerProxy, vaultProxy, fundOwner) = createFundMinimal({_fundDeployer: core.release.fundDeployer}); |
| 67 | + comptrollerProxyAddress = address(comptrollerProxy); |
| 68 | + vaultProxyAddress = address(vaultProxy); |
| 69 | + |
| 70 | + // Deploy the position to be deprecated |
| 71 | + vm.prank(fundOwner); |
| 72 | + address positionAddress = createExternalPosition({ |
| 73 | + _externalPositionManager: core.release.externalPositionManager, |
| 74 | + _comptrollerProxy: IComptrollerLib(comptrollerProxyAddress), |
| 75 | + _typeId: typeId, |
| 76 | + _initializationData: "", |
| 77 | + _callOnExternalPositionCallArgs: "" |
| 78 | + }); |
| 79 | + |
| 80 | + // Update to the deprecated lib and no parser |
| 81 | + address deprecatedLibAddress = __deployDeprecatedPositionLib(); |
| 82 | + address deprecatedParserAddress = address(0); |
| 83 | + vm.prank(core.release.fundDeployer.getOwner()); |
| 84 | + core.release.externalPositionManager |
| 85 | + .updateExternalPositionTypesInfo({ |
| 86 | + _typeIds: toArray(typeId), |
| 87 | + _libs: toArray(deprecatedLibAddress), |
| 88 | + _parsers: toArray(deprecatedParserAddress) |
| 89 | + }); |
| 90 | + |
| 91 | + // Assign the deprecated position |
| 92 | + deprecatedPosition = IDeprecatedPosition(positionAddress); |
| 93 | + } |
| 94 | + |
| 95 | + // DEPLOYMENT HELPERS |
| 96 | + |
| 97 | + function __deployDeprecatedPositionLib() internal returns (address libAddress_) { |
| 98 | + return deployCode("DeprecatedPositionLib.sol"); |
| 99 | + } |
| 100 | + |
| 101 | + // TESTS |
| 102 | + |
| 103 | + function test_callFromVaultOwner_fail_notVaultOwner() public { |
| 104 | + address assetManager = makeAddr("assetManager"); |
| 105 | + address randomUser = makeAddr("randomUser"); |
| 106 | + |
| 107 | + bytes4 revertSelector = IDeprecatedPosition.DeprecatedPositionLib__OnlyVaultOwner.selector; |
| 108 | + |
| 109 | + vm.expectRevert(revertSelector); |
| 110 | + vm.prank(assetManager); |
| 111 | + deprecatedPosition.callFromVaultOwner({_target: address(0), _data: "", _value: 0}); |
| 112 | + |
| 113 | + vm.expectRevert(revertSelector); |
| 114 | + vm.prank(randomUser); |
| 115 | + deprecatedPosition.callFromVaultOwner({_target: address(0), _data: "", _value: 0}); |
| 116 | + } |
| 117 | + |
| 118 | + function test_callFromVaultOwner_success_transferToken() public { |
| 119 | + uint256 tokenBalance = 1000e6; |
| 120 | + increaseTokenBalance({_token: usdtToken, _to: address(deprecatedPosition), _amount: tokenBalance}); |
| 121 | + |
| 122 | + address recipient = makeAddr("transferRecipient"); |
| 123 | + uint256 transferAmount = tokenBalance / 3; |
| 124 | + |
| 125 | + vm.prank(fundOwner); |
| 126 | + deprecatedPosition.callFromVaultOwner({ |
| 127 | + _target: address(usdtToken), |
| 128 | + _data: abi.encodeWithSelector(IERC20Prod.transfer.selector, recipient, transferAmount), |
| 129 | + _value: 0 |
| 130 | + }); |
| 131 | + |
| 132 | + assertEq(usdtToken.balanceOf(address(deprecatedPosition)), tokenBalance - transferAmount); |
| 133 | + assertEq(usdtToken.balanceOf(recipient), transferAmount); |
| 134 | + } |
| 135 | + |
| 136 | + // ALL INTERFACE FUNCTIONS SHOULD REVERT |
| 137 | + bytes4 deprecatedRevertSelector = IDeprecatedPosition.DeprecatedPositionLib__Deprecated.selector; |
| 138 | + |
| 139 | + function test_init_fail() public { |
| 140 | + vm.expectRevert(deprecatedRevertSelector); |
| 141 | + deprecatedPosition.init(""); |
| 142 | + } |
| 143 | + |
| 144 | + function test_receiveCallFromVault_fail() public { |
| 145 | + vm.expectRevert(deprecatedRevertSelector); |
| 146 | + vm.prank(address(vaultProxyAddress)); |
| 147 | + deprecatedPosition.receiveCallFromVault(""); |
| 148 | + } |
| 149 | + |
| 150 | + function test_getDebtAssets_fail() public { |
| 151 | + vm.expectRevert(deprecatedRevertSelector); |
| 152 | + deprecatedPosition.getDebtAssets(); |
| 153 | + } |
| 154 | + |
| 155 | + function test_getManagedAssets_fail() public { |
| 156 | + vm.expectRevert(deprecatedRevertSelector); |
| 157 | + deprecatedPosition.getManagedAssets(); |
| 158 | + } |
| 159 | +} |
0 commit comments