Skip to content

Commit

Permalink
test: create routers pattern for multi-version tests
Browse files Browse the repository at this point in the history
  • Loading branch information
SeanJCasey authored Nov 20, 2023
1 parent 02878f3 commit 36dcef6
Show file tree
Hide file tree
Showing 17 changed files with 679 additions and 69 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ artifacts/
cache/

# Ignore internal interfaces.
tests/interfaces/internal/
tests/interfaces/internal/*.sol
tests/interfaces/internal/*.abi.json
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ $(ARTIFACTS_DIR)/.sentinel: $(shell find $(CONTRACTS_DIR) -type f -name "*.sol")
$(INTERFACES_DIR)/.sentinel: $(INTERFACES_FILE) $(ARTIFACTS_DIR)/.sentinel
> mkdir -p $(@D)
>
> # Remove all existing interfaces and abis.
> find $(INTERFACES_DIR) -type f -name "*.sol" -delete
> find $(INTERFACES_DIR) -type f -name "*.abi.json" -delete
> # Remove all existing interfaces and abis (from the immediate directory only).
> find $(INTERFACES_DIR) -maxdepth 1 -type f -name "*.sol" -delete
> find $(INTERFACES_DIR) -maxdepth 1 -type f -name "*.abi.json" -delete
>
> echo "Generating interfaces ..."
>
Expand Down
125 changes: 124 additions & 1 deletion tests/bases/IntegrationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,19 @@
pragma solidity 0.8.19;

import {CoreUtils} from "tests/utils/CoreUtils.sol";
import {ChainlinkRateAsset} from "tests/utils/core/AssetUniverseUtils.sol";
import {ChainlinkRateAsset, TestAggregator} from "tests/utils/core/AssetUniverseUtils.sol";

import {
Contracts as PersistentContracts,
getMainnetDeployment as getMainnetPersistentContracts,
getPolygonDeployment as getPolygonPersistentContracts
} from "tests/utils/core/deployment/PersistentContracts.sol";
import {ReleaseConfig} from "tests/utils/core/deployment/DeploymentUtils.sol";
import {
Contracts as V4ReleaseContracts,
getMainnetDeployment as getV4MainnetReleaseContracts,
getPolygonDeployment as getV4PolygonReleaseContracts
} from "tests/utils/core/deployment/V4ReleaseContracts.sol";
import {
Contracts as ReleaseContracts,
getMainnetDeployment as getMainnetReleaseContracts,
Expand All @@ -18,6 +23,16 @@ import {

import {IERC20} from "tests/interfaces/external/IERC20.sol";

import {IComptrollerLib} from "tests/interfaces/internal/IComptrollerLib.sol";
import {IFundDeployer} from "tests/interfaces/internal/IFundDeployer.sol";
import {IIntegrationManager} from "tests/interfaces/internal/IIntegrationManager.sol";
import {IValueInterpreter} from "tests/interfaces/internal/IValueInterpreter.sol";
import {IVaultLib} from "tests/interfaces/internal/IVaultLib.sol";

// v4 interfaces
import {IComptrollerLib as IV4ComptrollerLib} from "tests/interfaces/internal/v4/IComptrollerLib.sol";
import {IFundDeployer as IV4FundDeployer} from "tests/interfaces/internal/v4/IFundDeployer.sol";

struct CorePrimitiveInput {
string symbol;
address assetAddress;
Expand All @@ -40,6 +55,7 @@ abstract contract IntegrationTest is CoreUtils {
IERC20 internal nonStandardPrimitive;

Deployment internal core;
V4ReleaseContracts internal v4ReleaseContracts;
// Don't allow access outside of this contract
mapping(string => IERC20) private symbolToCoreToken;
mapping(IERC20 => bool) private tokenToIsCore;
Expand Down Expand Up @@ -101,6 +117,8 @@ abstract contract IntegrationTest is CoreUtils {
function setUpMainnetEnvironment(uint256 _forkBlock) internal {
vm.createSelectFork("mainnet", _forkBlock);

v4ReleaseContracts = getV4MainnetReleaseContracts();

ReleaseConfig memory config = getDefaultMainnetConfig();

__setUpEnvironment({_config: config, _persistentContractsAlreadySet: false});
Expand Down Expand Up @@ -159,6 +177,8 @@ abstract contract IntegrationTest is CoreUtils {
function setUpPolygonEnvironment(uint256 _forkBlock) internal {
vm.createSelectFork("polygon", _forkBlock);

v4ReleaseContracts = getV4PolygonReleaseContracts();

ReleaseConfig memory config = getDefaultPolygonConfig();

__setUpEnvironment({_config: config, _persistentContractsAlreadySet: false});
Expand Down Expand Up @@ -440,4 +460,107 @@ abstract contract IntegrationTest is CoreUtils {
function isCoreToken(IERC20 _token) internal view returns (bool isCore_) {
return tokenToIsCore[_token];
}

// VERSIONED CONVENIENCE FUNCTIONS
// Not the most ideal place to dump all this stuff, but it's convenient for now

// Sorted descending, so default is most current version in the repo.
// V3 and earlier not supported.
// Version numbers refer to live contracts, not the contracts in this repo.
enum EnzymeVersion {
Current,
V4
}

// Versioned routers

function adapterActionForVersion(
EnzymeVersion _version,
address _comptrollerProxyAddress,
address _adapterAddress,
bytes4 _selector,
bytes memory _actionArgs
) internal {
// Only difference currently is the integration manager address
address integrationManagerAddress = getIntegrationManagerAddressForVersion(_version);

callOnIntegration({
_integrationManager: IIntegrationManager(integrationManagerAddress),
_comptrollerProxy: IComptrollerLib(_comptrollerProxyAddress),
_adapter: _adapterAddress,
_selector: _selector,
_actionArgs: _actionArgs
});
}

function createTradingFundForVersion(EnzymeVersion _version, IERC20 _denominationAsset)
internal
returns (address comptrollerProxyAddress_, address vaultProxyAddress_, address fundOwner_)
{
if (_version == EnzymeVersion.V4) {
return v4CreateFundSimple({
_fundDeployer: v4ReleaseContracts.fundDeployer,
_denominationAsset: _denominationAsset
});
} else {
IFundDeployer.ConfigInput memory comptrollerConfig;
comptrollerConfig.denominationAsset = address(_denominationAsset);

IComptrollerLib comptrollerProxy;
IVaultLib vaultProxy;
(comptrollerProxy, vaultProxy, fundOwner_) =
createFund({_fundDeployer: core.release.fundDeployer, _comptrollerConfig: comptrollerConfig});

comptrollerProxyAddress_ = address(comptrollerProxy);
vaultProxyAddress_ = address(vaultProxy);
}
}

function getIntegrationManagerAddressForVersion(EnzymeVersion _version)
internal
view
returns (address integrationManagerAddress_)
{
if (_version == EnzymeVersion.V4) {
return address(v4ReleaseContracts.integrationManager);
} else {
return address(core.release.integrationManager);
}
}

// v4 actions: fund creation

// Create simple fund that can trade, but no fees or policies
function v4CreateFundSimple(IV4FundDeployer _fundDeployer, IERC20 _denominationAsset)
internal
returns (address comptrollerProxyAddress_, address vaultProxyAddress_, address fundOwner_)
{
fundOwner_ = makeAddr("createFund: FundOwner");

(comptrollerProxyAddress_, vaultProxyAddress_) = _fundDeployer.createNewFund({
_fundOwner: fundOwner_,
_fundName: "Test Fund",
_fundSymbol: "TEST",
_denominationAsset: address(_denominationAsset),
_sharesActionTimelock: 0,
_feeManagerConfigData: "",
_policyManagerConfigData: ""
});
}

// v4 actions: system

// Where the interfaces/logic remain the same, we can reuse the current convenience functions for v4 (e.g., ValueInterpreter).
// By defining pass-through helpers in such a way, we can avoid more heavy refactoring later if we can no longer use the current convenience functions

function v4AddPrimitiveWithTestAggregator(address _tokenAddress, bool _skipIfRegistered)
internal
returns (TestAggregator aggregator_)
{
return addPrimitiveWithTestAggregator({
_valueInterpreter: IValueInterpreter(address(v4ReleaseContracts.valueInterpreter)),
_tokenAddress: _tokenAddress,
_skipIfRegistered: _skipIfRegistered
});
}
}
85 changes: 85 additions & 0 deletions tests/interfaces/internal/v4/IComptrollerLib.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.6.0 <0.9.0;

interface IComptrollerLib {
event AutoProtocolFeeSharesBuybackSet(bool autoProtocolFeeSharesBuyback);
event BuyBackMaxProtocolFeeSharesFailed(
bytes indexed failureReturnData, uint256 sharesAmount, uint256 buybackValueInMln, uint256 gav
);
event DeactivateFeeManagerFailed();
event GasRelayPaymasterSet(address gasRelayPaymaster);
event MigratedSharesDuePaid(uint256 sharesDue);
event PayProtocolFeeDuringDestructFailed();
event PreRedeemSharesHookFailed(bytes indexed failureReturnData, address indexed redeemer, uint256 sharesAmount);
event RedeemSharesInKindCalcGavFailed();
event SharesBought(address indexed buyer, uint256 investmentAmount, uint256 sharesIssued, uint256 sharesReceived);
event SharesRedeemed(
address indexed redeemer,
address indexed recipient,
uint256 sharesAmount,
address[] receivedAssets,
uint256[] receivedAssetAmounts
);
event VaultProxySet(address vaultProxy);

function activate(bool _isMigration) external;
function buyBackProtocolFeeShares(uint256 _sharesAmount) external;
function buyShares(uint256 _investmentAmount, uint256 _minSharesQuantity)
external
returns (uint256 sharesReceived_);
function buySharesOnBehalf(address _buyer, uint256 _investmentAmount, uint256 _minSharesQuantity)
external
returns (uint256 sharesReceived_);
function calcGav() external returns (uint256 gav_);
function calcGrossShareValue() external returns (uint256 grossShareValue_);
function callOnExtension(address _extension, uint256 _actionId, bytes memory _callArgs) external;
function deployGasRelayPaymaster() external;
function depositToGasRelayPaymaster() external;
function destructActivated(uint256 _deactivateFeeManagerGasLimit, uint256 _payProtocolFeeGasLimit) external;
function destructUnactivated() external;
function doesAutoProtocolFeeSharesBuyback() external view returns (bool doesAutoBuyback_);
function getDenominationAsset() external view returns (address denominationAsset_);
function getDispatcher() external view returns (address dispatcher_);
function getExternalPositionManager() external view returns (address externalPositionManager_);
function getFeeManager() external view returns (address feeManager_);
function getFundDeployer() external view returns (address fundDeployer_);
function getGasRelayPaymaster() external view returns (address gasRelayPaymaster_);
function getGasRelayPaymasterFactory() external view returns (address gasRelayPaymasterFactory_);
function getGasRelayTrustedForwarder() external view returns (address trustedForwarder_);
function getIntegrationManager() external view returns (address integrationManager_);
function getLastSharesBoughtTimestampForAccount(address _who)
external
view
returns (uint256 lastSharesBoughtTimestamp_);
function getMlnToken() external view returns (address mlnToken_);
function getPolicyManager() external view returns (address policyManager_);
function getProtocolFeeReserve() external view returns (address protocolFeeReserve_);
function getSharesActionTimelock() external view returns (uint256 sharesActionTimelock_);
function getValueInterpreter() external view returns (address valueInterpreter_);
function getVaultProxy() external view returns (address vaultProxy_);
function getWethToken() external view returns (address wethToken_);
function init(address _denominationAsset, uint256 _sharesActionTimelock) external;
function permissionedVaultAction(uint8 _action, bytes memory _actionData) external;
function preTransferSharesHook(address _sender, address _recipient, uint256 _amount) external;
function preTransferSharesHookFreelyTransferable(address _sender) external view;
function pullWethForGasRelayer(uint256 _amount) external;
function redeemSharesForSpecificAssets(
address _recipient,
uint256 _sharesQuantity,
address[] memory _payoutAssets,
uint256[] memory _payoutAssetPercentages
) external returns (uint256[] memory payoutAmounts_);
function redeemSharesInKind(
address _recipient,
uint256 _sharesQuantity,
address[] memory _additionalAssets,
address[] memory _assetsToSkip
) external returns (address[] memory payoutAssets_, uint256[] memory payoutAmounts_);
function setAutoProtocolFeeSharesBuyback(bool _nextAutoProtocolFeeSharesBuyback) external;
function setGasRelayPaymaster(address _nextGasRelayPaymaster) external;
function setVaultProxy(address _vaultProxy) external;
function shutdownGasRelayPaymaster() external;
function vaultCallOnContract(address _contract, bytes4 _selector, bytes memory _encodedArgs)
external
returns (bytes memory returnData_);
}
41 changes: 41 additions & 0 deletions tests/interfaces/internal/v4/IExternalPositionManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.6.0 <0.9.0;

interface IExternalPositionManager {
event CallOnExternalPositionExecutedForFund(
address indexed caller,
address indexed comptrollerProxy,
address indexed externalPosition,
uint256 actionId,
bytes actionArgs,
address[] assetsToTransfer,
uint256[] amountsToTransfer,
address[] assetsToReceive
);
event ExternalPositionDeployedForFund(
address indexed comptrollerProxy,
address indexed vaultProxy,
address externalPosition,
uint256 indexed externalPositionTypeId,
bytes data
);
event ExternalPositionTypeInfoUpdated(uint256 indexed typeId, address lib, address parser);
event ValidatedVaultProxySetForFund(address indexed comptrollerProxy, address indexed vaultProxy);

function activateForFund(bool) external;
function deactivateForFund() external;
function getExternalPositionFactory() external view returns (address externalPositionFactory_);
function getExternalPositionLibForType(uint256 _typeId) external view returns (address lib_);
function getExternalPositionParserForType(uint256 _typeId) external view returns (address parser_);
function getFundDeployer() external view returns (address fundDeployer_);
function getOwner() external view returns (address owner_);
function getPolicyManager() external view returns (address policyManager_);
function getVaultProxyForFund(address _comptrollerProxy) external view returns (address vaultProxy_);
function receiveCallFromComptroller(address _caller, uint256 _actionId, bytes memory _callArgs) external;
function setConfigForFund(address _comptrollerProxy, address _vaultProxy, bytes memory) external;
function updateExternalPositionTypesInfo(
uint256[] memory _typeIds,
address[] memory _libs,
address[] memory _parsers
) external;
}
32 changes: 32 additions & 0 deletions tests/interfaces/internal/v4/IFeeManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: Unlicense
pragma solidity >=0.6.0 <0.9.0;

interface IFeeManager {
event FeeEnabledForFund(address indexed comptrollerProxy, address indexed fee, bytes settingsData);
event FeeSettledForFund(
address indexed comptrollerProxy,
address indexed fee,
uint8 indexed settlementType,
address payer,
address payee,
uint256 sharesDue
);
event SharesOutstandingPaidForFund(
address indexed comptrollerProxy, address indexed fee, address indexed payee, uint256 sharesDue
);
event ValidatedVaultProxySetForFund(address indexed comptrollerProxy, address indexed vaultProxy);

function activateForFund(bool) external;
function deactivateForFund() external;
function getEnabledFeesForFund(address _comptrollerProxy) external view returns (address[] memory enabledFees_);
function getFeeSharesOutstandingForFund(address _comptrollerProxy, address _fee)
external
view
returns (uint256 sharesOutstanding_);
function getFundDeployer() external view returns (address fundDeployer_);
function getOwner() external view returns (address owner_);
function getVaultProxyForFund(address _comptrollerProxy) external view returns (address vaultProxy_);
function invokeHook(uint8 _hook, bytes memory _settlementData, uint256 _gav) external;
function receiveCallFromComptroller(address, uint256 _actionId, bytes memory _callArgs) external;
function setConfigForFund(address _comptrollerProxy, address _vaultProxy, bytes memory _configData) external;
}
Loading

0 comments on commit 36dcef6

Please sign in to comment.