diff --git a/examples/oapp/test/foundry/MyOApp.t.sol b/examples/oapp/test/foundry/MyOApp.t.sol index 9fbf8f97a9..b83649965d 100644 --- a/examples/oapp/test/foundry/MyOApp.t.sol +++ b/examples/oapp/test/foundry/MyOApp.t.sol @@ -11,11 +11,9 @@ import { OptionsBuilder } from "@layerzerolabs/oapp-evm/contracts/oapp/libs/Opti // OZ imports import { IERC20 } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -// Forge imports -import "forge-std/console.sol"; - // DevTools imports import { TestHelperOz5 } from "@layerzerolabs/test-devtools-evm-foundry/contracts/TestHelperOz5.sol"; +import { console } from "forge-std/console.sol"; contract MyOAppTest is TestHelperOz5 { using OptionsBuilder for bytes; @@ -35,11 +33,17 @@ contract MyOAppTest is TestHelperOz5 { vm.deal(userB, 1000 ether); super.setUp(); - setUpEndpoints(2, LibraryType.UltraLightNode); - aOApp = MyOApp(_deployOApp(type(MyOApp).creationCode, abi.encode(address(endpoints[aEid]), address(this)))); + string[] memory forkUrls = new string[](2); + forkUrls[0] = "https://eth.drpc.org"; + forkUrls[1] = "https://arb1.arbitrum.io/rpc"; + + createEndpoints(2, LibraryType.UltraLightNode, new address[](2), forkUrls); - bOApp = MyOApp(_deployOApp(type(MyOApp).creationCode, abi.encode(address(endpoints[bEid]), address(this)))); + vm.selectFork(eidForkMap[aEid]); + aOApp = new MyOApp(address(endpoints[aEid]), address(this)); + vm.selectFork(eidForkMap[bEid]); + bOApp = new MyOApp(address(endpoints[bEid]), address(this)); address[] memory oapps = new address[](2); oapps[0] = address(aOApp); @@ -47,12 +51,22 @@ contract MyOAppTest is TestHelperOz5 { this.wireOApps(oapps); } - function test_constructor() public { - assertEq(aOApp.owner(), address(this)); - assertEq(bOApp.owner(), address(this)); + function test_sendMessage() public { + vm.selectFork(eidForkMap[bEid]); + assertEq(bOApp.data(), "Nothing received yet."); + + vm.selectFork(eidForkMap[aEid]); + vm.prank(userA); + bytes memory options = OptionsBuilder.newOptions().addExecutorLzReceiveOption(200000, 0); + + uint256 nativeFee = aOApp.quote(bEid, "hello", options, false).nativeFee; + + aOApp.send{ value: nativeFee }(bEid, "hello", options); + + vm.selectFork(eidForkMap[bEid]); + verifyPackets(bEid, addressToBytes32(address(bOApp))); - assertEq(address(aOApp.endpoint()), address(endpoints[aEid])); - assertEq(address(bOApp.endpoint()), address(endpoints[bEid])); + assertEq(bOApp.data(), "hello"); } function test_send_string() public { diff --git a/packages/test-devtools-evm-foundry/contracts/TestHelperOz5.sol b/packages/test-devtools-evm-foundry/contracts/TestHelperOz5.sol index 32842867f8..da7e3381d0 100644 --- a/packages/test-devtools-evm-foundry/contracts/TestHelperOz5.sol +++ b/packages/test-devtools-evm-foundry/contracts/TestHelperOz5.sol @@ -66,7 +66,7 @@ contract TestHelperOz5 is Test, OptionsHelper { address[] receiveLibs; address[] readLibs; address[] signers; - PriceFeed priceFeed; + PriceFeed[] priceFeed; } struct LibrarySetup { @@ -93,6 +93,7 @@ contract TestHelperOz5 is Test, OptionsHelper { mapping(bytes32 => bytes) optionsLookup; // guid => options mapping(uint32 => address) endpoints; // eid => endpoint + mapping(uint32 => uint256) eidForkMap; // eid => fork id uint256 public constant TREASURY_GAS_CAP = 1000000000000; uint256 public constant TREASURY_GAS_FOR_FEE_CAP = 100000; @@ -123,8 +124,9 @@ contract TestHelperOz5 is Test, OptionsHelper { } function setUpEndpoints(uint8 _endpointNum, LibraryType _libraryType) public { - createEndpoints(_endpointNum, _libraryType, new address[](_endpointNum)); + createEndpoints(_endpointNum, _libraryType, new address[](_endpointNum), new string[](_endpointNum)); } + /** * @notice Sets up endpoints for testing. * @param _endpointNum The number of endpoints to create. @@ -134,21 +136,46 @@ contract TestHelperOz5 is Test, OptionsHelper { uint8 _endpointNum, LibraryType _libraryType, address[] memory nativeTokenAddresses + ) public { + createEndpoints(_endpointNum, _libraryType, nativeTokenAddresses, new string[](_endpointNum)); + } + + function createEndpoints( + uint8 _endpointNum, + LibraryType _libraryType, + address[] memory nativeTokenAddresses, + string[] memory forkUrls ) public { endpointSetup.endpointList = new EndpointV2[](_endpointNum); endpointSetup.eidList = new uint32[](_endpointNum); endpointSetup.sendLibs = new address[](_endpointNum); endpointSetup.receiveLibs = new address[](_endpointNum); endpointSetup.readLibs = new address[](_endpointNum); + endpointSetup.priceFeed = new PriceFeed[](_endpointNum); endpointSetup.signers = new address[](1); endpointSetup.signers[0] = vm.addr(1); { + uint256 forkId = 0; + // create fork ids + for (uint8 i = 0; i < _endpointNum; i++) { + if (bytes(forkUrls[i]).length > 0) { + forkId = vm.createFork(forkUrls[i]); + } + + uint32 eid = i + 1; + eidForkMap[eid] = forkId; + } + // deploy endpoints for (uint8 i = 0; i < _endpointNum; i++) { uint32 eid = i + 1; - address nativeToken = nativeTokenAddresses[i]; + vm.selectFork(eidForkMap[eid]); + endpointSetup.eidList[i] = eid; + + address nativeToken = nativeTokenAddresses[i]; + if (nativeToken == address(0)) { endpointSetup.endpointList[i] = new EndpointV2(eid, address(this)); } else { @@ -158,10 +185,13 @@ contract TestHelperOz5 is Test, OptionsHelper { } } - // @dev oz4/5 breaking change... constructor init - endpointSetup.priceFeed = new PriceFeed(address(this)); - for (uint8 i = 0; i < _endpointNum; i++) { + uint32 eid = i + 1; + vm.selectFork(eidForkMap[eid]); + + // @dev oz4/5 breaking change... constructor init + endpointSetup.priceFeed[i] = new PriceFeed(address(this)); + if (_libraryType == LibraryType.UltraLightNode) { address endpointAddr = address(endpointSetup.endpointList[i]); @@ -198,7 +228,7 @@ contract TestHelperOz5 is Test, OptionsHelper { endpointAddr, address(0x0), messageLibs, - address(endpointSetup.priceFeed), + address(endpointSetup.priceFeed[i]), address(this), admins ); @@ -210,7 +240,7 @@ contract TestHelperOz5 is Test, OptionsHelper { endpointSetup.eidList[i], i + 1, messageLibs, - address(endpointSetup.priceFeed), + address(endpointSetup.priceFeed[i]), endpointSetup.signers, 1, admins @@ -280,14 +310,14 @@ contract TestHelperOz5 is Test, OptionsHelper { types: BitMap256.wrap(MAP_REDUCE_COMPUTE_TYPES) }); - uint128 denominator = endpointSetup.priceFeed.getPriceRatioDenominator(); + uint128 denominator = endpointSetup.priceFeed[i].getPriceRatioDenominator(); ILayerZeroPriceFeed.UpdatePrice[] memory prices = new ILayerZeroPriceFeed.UpdatePrice[](1); prices[0] = ILayerZeroPriceFeed.UpdatePrice( dstEid, ILayerZeroPriceFeed.Price(1 * denominator, 1, 1) ); - endpointSetup.priceFeed.setPrice(prices); - endpointSetup.priceFeed.setNativeTokenPriceUSD(NATIVE_TOKEN_PRICE_USD); + endpointSetup.priceFeed[i].setPrice(prices); + endpointSetup.priceFeed[i].setNativeTokenPriceUSD(NATIVE_TOKEN_PRICE_USD); } { @@ -348,6 +378,9 @@ contract TestHelperOz5 is Test, OptionsHelper { // config up for (uint8 i = 0; i < _endpointNum; i++) { + uint32 eid = i + 1; + vm.selectFork(eidForkMap[eid]); + EndpointV2 endpoint = endpointSetup.endpointList[i]; if (_libraryType == LibraryType.UltraLightNode) { endpoint.setDefaultSendLibrary(DEFAULT_CHANNEL_ID, endpointSetup.readLibs[i]); @@ -375,6 +408,8 @@ contract TestHelperOz5 is Test, OptionsHelper { ) public returns (address[] memory oapps) { oapps = new address[](_oappNum); for (uint8 eid = _startEid; eid < _startEid + _oappNum; eid++) { + vm.selectFork(eidForkMap[eid]); + address oapp = _deployOApp(_oappCreationCode, abi.encode(address(endpoints[eid]), address(this), true)); oapps[eid - _startEid] = oapp; } @@ -390,11 +425,18 @@ contract TestHelperOz5 is Test, OptionsHelper { function wireOApps(address[] memory oapps) public { uint256 size = oapps.length; for (uint256 i = 0; i < size; i++) { + vm.selectFork(i); IOAppSetPeer localOApp = IOAppSetPeer(oapps[i]); for (uint256 j = 0; j < size; j++) { if (i == j) continue; + + // find remote eid + vm.selectFork(j); IOAppSetPeer remoteOApp = IOAppSetPeer(oapps[j]); uint32 remoteEid = (remoteOApp.endpoint()).eid(); + + // set remote peer to local + vm.selectFork(i); localOApp.setPeer(remoteEid, addressToBytes32(address(remoteOApp))); } } @@ -498,6 +540,9 @@ contract TestHelperOz5 is Test, OptionsHelper { this.validatePacket(packetBytes, _resolvedPayload); bytes memory options = optionsLookup[guid]; + + vm.selectFork(eidForkMap[_dstEid]); + if (_executorOptionExists(options, ExecutorOptions.OPTION_TYPE_NATIVE_DROP)) { (uint256 amount, bytes32 receiver) = _parseExecutorNativeDropOption(options); address to = address(uint160(uint256(receiver)));