Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move Foundry TestHelper variables to storage to fix forge coverage #791

Merged
merged 5 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/few-hornets-love.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@layerzerolabs/test-devtools-evm-foundry": patch
---

Enable coverage in TestHelper
4 changes: 3 additions & 1 deletion packages/test-devtools-evm-foundry/.eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.turbo
dist
node_modules
node_modules
out
cache
8 changes: 8 additions & 0 deletions packages/test-devtools-evm-foundry/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
cache
# Ignore everything in the artifacts folder
artifacts/*

# Do not ignore the directory structure up to the specific file
!artifacts/
!artifacts/TestHelperOz5.sol/
!artifacts/TestHelperOz5.sol/TestHelperOz5.json

Large diffs are not rendered by default.

Large diffs are not rendered by default.

202 changes: 114 additions & 88 deletions packages/test-devtools-evm-foundry/contracts/TestHelperOz5.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,34 @@ interface IOAppSetPeer {
* @dev Extends Foundry's Test contract and provides utility functions for setting up mock endpoints and OApps.
*/
contract TestHelperOz5 is Test, OptionsHelper {

enum LibraryType {
UltraLightNode,
SimpleMessageLib
}

struct EndpointSetup {
EndpointV2[] endpointList;
uint32[] eidList;
address[] sendLibs;
address[] receiveLibs;
address[] signers;
PriceFeed priceFeed;
}

struct LibrarySetup {
SendUln302 sendUln;
ReceiveUln302 receiveUln;
Executor executor;
DVN dvn;
ExecutorFeeLib executorLib;
DVNFeeLib dvnLib;
}

struct ConfigParams {
IExecutor.DstConfigParam[] executorConfigParams;
IDVN.DstConfigParam[] dvnConfigParams;
}

using DoubleEndedQueue for DoubleEndedQueue.Bytes32Deque;
using PacketV1Codec for bytes;

Expand All @@ -64,6 +86,9 @@ contract TestHelperOz5 is Test, OptionsHelper {

uint128 public executorValueCap = 0.1 ether;

EndpointSetup internal endpointSetup;
LibrarySetup internal libSetup;

/// @dev Initializes test environment setup, to be overridden by specific tests.
function setUp() public virtual {
_setUpUlnOptions();
Expand All @@ -77,122 +102,118 @@ contract TestHelperOz5 is Test, OptionsHelper {
function setExecutorValueCap(uint128 _valueCap) public {
executorValueCap = _valueCap;
}

/**
* @notice Sets up endpoints for testing.
* @param _endpointNum The number of endpoints to create.
* @param _libraryType The type of message library to use (UltraLightNode or SimpleMessageLib).
*/
function setUpEndpoints(uint8 _endpointNum, LibraryType _libraryType) public {
EndpointV2[] memory endpointList = new EndpointV2[](_endpointNum);
uint32[] memory eidList = new uint32[](_endpointNum);

// deploy _excludedContracts
for (uint8 i = 0; i < _endpointNum; i++) {
uint32 eid = i + 1;
eidList[i] = eid;
endpointList[i] = new EndpointV2(eid, address(this));
registerEndpoint(endpointList[i]);
endpointSetup.endpointList = new EndpointV2[](_endpointNum);
endpointSetup.eidList = new uint32[](_endpointNum);
endpointSetup.sendLibs = new address[](_endpointNum);
endpointSetup.receiveLibs = new address[](_endpointNum);
endpointSetup.signers = new address[](1);
endpointSetup.signers[0] = vm.addr(1);

{
// deploy endpoints
for (uint8 i = 0; i < _endpointNum; i++) {
uint32 eid = i + 1;
endpointSetup.eidList[i] = eid;
endpointSetup.endpointList[i] = new EndpointV2(eid, address(this));
registerEndpoint(endpointSetup.endpointList[i]);
}
}

// deploy
address[] memory sendLibs = new address[](_endpointNum);
address[] memory receiveLibs = new address[](_endpointNum);

address[] memory signers = new address[](1);
signers[0] = vm.addr(1);

// @dev oz4/5 breaking change... constructor init
PriceFeed priceFeed = new PriceFeed(address(this));
endpointSetup.priceFeed = new PriceFeed(address(this));

for (uint8 i = 0; i < _endpointNum; i++) {
if (_libraryType == LibraryType.UltraLightNode) {
address endpointAddr = address(endpointList[i]);
address endpointAddr = address(endpointSetup.endpointList[i]);

libSetup.sendUln = new SendUln302(
payable(this),
endpointAddr,
TREASURY_GAS_CAP,
TREASURY_GAS_FOR_FEE_CAP
);
libSetup.receiveUln = new ReceiveUln302(endpointAddr);
endpointSetup.endpointList[i].registerLibrary(address(libSetup.sendUln));
endpointSetup.endpointList[i].registerLibrary(address(libSetup.receiveUln));
endpointSetup.sendLibs[i] = address(libSetup.sendUln);
endpointSetup.receiveLibs[i] = address(libSetup.receiveUln);

SendUln302 sendUln;
ReceiveUln302 receiveUln;
{
sendUln = new SendUln302(payable(this), endpointAddr, TREASURY_GAS_CAP, TREASURY_GAS_FOR_FEE_CAP);
receiveUln = new ReceiveUln302(endpointAddr);
endpointList[i].registerLibrary(address(sendUln));
endpointList[i].registerLibrary(address(receiveUln));
sendLibs[i] = address(sendUln);
receiveLibs[i] = address(receiveUln);
}

Executor executor;
DVN dvn;
{
address[] memory admins = new address[](1);
admins[0] = address(this);

address[] memory messageLibs = new address[](2);
messageLibs[0] = address(sendUln);
messageLibs[1] = address(receiveUln);
executor = new Executor(
messageLibs[0] = address(libSetup.sendUln);
messageLibs[1] = address(libSetup.receiveUln);

libSetup.executor = new Executor(
endpointAddr,
address(0x0),
messageLibs,
address(priceFeed),
address(endpointSetup.priceFeed),
address(this),
admins
);

ExecutorFeeLib executorLib = new ExecutorFeeLib();
executor.setWorkerFeeLib(address(executorLib));
libSetup.executorLib = new ExecutorFeeLib();
libSetup.executor.setWorkerFeeLib(address(libSetup.executorLib));

dvn = new DVN(i + 1, messageLibs, address(priceFeed), signers, 1, admins);
DVNFeeLib dvnLib = new DVNFeeLib(1e18);
dvn.setWorkerFeeLib(address(dvnLib));
libSetup.dvn = new DVN(
i + 1,
messageLibs,
address(endpointSetup.priceFeed),
endpointSetup.signers,
1,
admins
);
libSetup.dvnLib = new DVNFeeLib(1e18);
libSetup.dvn.setWorkerFeeLib(address(libSetup.dvnLib));
}

uint32 endpointNum = _endpointNum;
IExecutor.DstConfigParam[] memory dstConfigParams = new IExecutor.DstConfigParam[](endpointNum);
IDVN.DstConfigParam[] memory dvnConfigParams = new IDVN.DstConfigParam[](endpointNum);
for (uint8 j = 0; j < endpointNum; j++) {
ConfigParams memory configParams;
configParams.executorConfigParams = new IExecutor.DstConfigParam[](_endpointNum);
configParams.dvnConfigParams = new IDVN.DstConfigParam[](_endpointNum);

for (uint8 j = 0; j < _endpointNum; j++) {
if (i == j) continue;
uint32 dstEid = j + 1;

address[] memory defaultDVNs = new address[](1);
address[] memory optionalDVNs = new address[](0);
defaultDVNs[0] = address(dvn);

{
SetDefaultUlnConfigParam[] memory params = new SetDefaultUlnConfigParam[](1);
UlnConfig memory ulnConfig = UlnConfig(
100,
uint8(defaultDVNs.length),
uint8(optionalDVNs.length),
0,
defaultDVNs,
optionalDVNs
);
params[0] = SetDefaultUlnConfigParam(dstEid, ulnConfig);
sendUln.setDefaultUlnConfigs(params);
}
defaultDVNs[0] = address(libSetup.dvn);

SetDefaultUlnConfigParam[] memory ulnParams = new SetDefaultUlnConfigParam[](1);
UlnConfig memory ulnConfig = UlnConfig(
100,
uint8(defaultDVNs.length),
uint8(optionalDVNs.length),
0,
defaultDVNs,
optionalDVNs
);

{
SetDefaultExecutorConfigParam[] memory params = new SetDefaultExecutorConfigParam[](1);
ExecutorConfig memory executorConfig = ExecutorConfig(10000, address(executor));
params[0] = SetDefaultExecutorConfigParam(dstEid, executorConfig);
sendUln.setDefaultExecutorConfigs(params);
ulnParams[0] = SetDefaultUlnConfigParam(dstEid, ulnConfig);
libSetup.sendUln.setDefaultUlnConfigs(ulnParams);
libSetup.receiveUln.setDefaultUlnConfigs(ulnParams);
}

{
SetDefaultUlnConfigParam[] memory params = new SetDefaultUlnConfigParam[](1);
UlnConfig memory ulnConfig = UlnConfig(
100,
uint8(defaultDVNs.length),
uint8(optionalDVNs.length),
0,
defaultDVNs,
optionalDVNs
);
params[0] = SetDefaultUlnConfigParam(dstEid, ulnConfig);
receiveUln.setDefaultUlnConfigs(params);
SetDefaultExecutorConfigParam[] memory execParams = new SetDefaultExecutorConfigParam[](1);
ExecutorConfig memory execConfig = ExecutorConfig(10000, address(libSetup.executor));
execParams[0] = SetDefaultExecutorConfigParam(dstEid, execConfig);
libSetup.sendUln.setDefaultExecutorConfigs(execParams);
}

// executor config
dstConfigParams[j] = IExecutor.DstConfigParam({
configParams.executorConfigParams[j] = IExecutor.DstConfigParam({
dstEid: dstEid,
lzReceiveBaseGas: 5000,
lzComposeBaseGas: 5000,
Expand All @@ -202,40 +223,44 @@ contract TestHelperOz5 is Test, OptionsHelper {
});

// dvn config
dvnConfigParams[j] = IDVN.DstConfigParam({
configParams.dvnConfigParams[j] = IDVN.DstConfigParam({
dstEid: dstEid,
gas: 5000,
multiplierBps: 10000,
floorMarginUSD: 1e10
});

uint128 denominator = priceFeed.getPriceRatioDenominator();
uint128 denominator = endpointSetup.priceFeed.getPriceRatioDenominator();
ILayerZeroPriceFeed.UpdatePrice[] memory prices = new ILayerZeroPriceFeed.UpdatePrice[](1);
prices[0] = ILayerZeroPriceFeed.UpdatePrice(
dstEid,
ILayerZeroPriceFeed.Price(1 * denominator, 1, 1)
);
priceFeed.setPrice(prices);
endpointSetup.priceFeed.setPrice(prices);
}
executor.setDstConfig(dstConfigParams);
dvn.setDstConfig(dvnConfigParams);

libSetup.executor.setDstConfig(configParams.executorConfigParams);
libSetup.dvn.setDstConfig(configParams.dvnConfigParams);
} else if (_libraryType == LibraryType.SimpleMessageLib) {
SimpleMessageLibMock messageLib = new SimpleMessageLibMock(payable(this), address(endpointList[i]));
endpointList[i].registerLibrary(address(messageLib));
sendLibs[i] = address(messageLib);
receiveLibs[i] = address(messageLib);
SimpleMessageLibMock messageLib = new SimpleMessageLibMock(
payable(this),
address(endpointSetup.endpointList[i])
);
endpointSetup.endpointList[i].registerLibrary(address(messageLib));
endpointSetup.sendLibs[i] = address(messageLib);
endpointSetup.receiveLibs[i] = address(messageLib);
} else {
revert("invalid library type");
}
}

// config up
for (uint8 i = 0; i < _endpointNum; i++) {
EndpointV2 endpoint = endpointList[i];
EndpointV2 endpoint = endpointSetup.endpointList[i];
for (uint8 j = 0; j < _endpointNum; j++) {
if (i == j) continue;
endpoint.setDefaultSendLibrary(j + 1, sendLibs[i]);
endpoint.setDefaultReceiveLibrary(j + 1, receiveLibs[i], 0);
endpoint.setDefaultSendLibrary(j + 1, endpointSetup.sendLibs[i]);
endpoint.setDefaultReceiveLibrary(j + 1, endpointSetup.receiveLibs[i], 0);
}
}
}
Expand All @@ -260,6 +285,7 @@ contract TestHelperOz5 is Test, OptionsHelper {
// config
wireOApps(oapps);
}

/**
* @notice Configures the peers between multiple OApp instances.
* @dev Sets each OApp as a peer to every other OApp in the provided array, except itself.
Expand Down
4 changes: 3 additions & 1 deletion packages/test-devtools-evm-foundry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
"artifacts/"
],
"scripts": {
"coverage": "forge coverage --ir-minimum",
"lint": "$npm_execpath eslint '**/*.{js,ts,json}'",
"lint:fix": "eslint --fix '**/*.{js,ts,json}'"
"lint:fix": "eslint --fix '**/*.{js,ts,json}'",
"test": "forge test"
},
"devDependencies": {
"@layerzerolabs/lz-evm-messagelib-v2": "^2.3.25",
Expand Down
Loading