From a8acb2370d089fe0cc9fa055c241764e4833c91f Mon Sep 17 00:00:00 2001 From: sendra Date: Tue, 10 Dec 2024 15:35:26 +0100 Subject: [PATCH] fix: added unit tests --- scripts/Adapters/DeployLineaAdapter.sol | 2 +- scripts/contract_extensions/LineaAdapter.sol | 10 +- src/contracts/adapters/linea/LineaAdapter.sol | 9 +- src/contracts/libs/Errors.sol | 1 + tests/adapters/LineaAdapter.t.sol | 275 ++++++++++++++++++ 5 files changed, 282 insertions(+), 15 deletions(-) create mode 100644 tests/adapters/LineaAdapter.t.sol diff --git a/scripts/Adapters/DeployLineaAdapter.sol b/scripts/Adapters/DeployLineaAdapter.sol index 9dfcdc63..0ba4ca90 100644 --- a/scripts/Adapters/DeployLineaAdapter.sol +++ b/scripts/Adapters/DeployLineaAdapter.sol @@ -48,7 +48,7 @@ abstract contract BaseDeployLineaAdapter is BaseAdapterScript { LineaAdapterDeploymentHelper.getAdapterCode( LineaAdapterDeploymentHelper.LineaAdapterArgs({ baseArgs: baseArgs, - inbox: LINEA_MESSAGE_SERVICE() + lineaMessageService: LINEA_MESSAGE_SERVICE() }) ); } diff --git a/scripts/contract_extensions/LineaAdapter.sol b/scripts/contract_extensions/LineaAdapter.sol index cff10195..a4a23b32 100644 --- a/scripts/contract_extensions/LineaAdapter.sol +++ b/scripts/contract_extensions/LineaAdapter.sol @@ -19,15 +19,7 @@ contract LineaAdapterTestnet is LineaAdapter { address lineaMessageService, uint256 providerGasLimit, TrustedRemotesConfig[] memory trustedRemotes - ) - LineaAdapter( - crossChainController, - lineaMessageService, - providerGasLimit, - trustedRemotes, - 'Linea native adapter' - ) - {} + ) LineaAdapter(crossChainController, lineaMessageService, providerGasLimit, trustedRemotes) {} /// @inheritdoc ILineaAdapter function isDestinationChainIdSupported(uint256 chainId) public pure override returns (bool) { diff --git a/src/contracts/adapters/linea/LineaAdapter.sol b/src/contracts/adapters/linea/LineaAdapter.sol index beaae03f..b3ef9c1d 100644 --- a/src/contracts/adapters/linea/LineaAdapter.sol +++ b/src/contracts/adapters/linea/LineaAdapter.sol @@ -32,23 +32,22 @@ contract LineaAdapter is ILineaAdapter, BaseAdapter { * @param crossChainController address of the cross chain controller that will use this bridge adapter * @param lineaMessageService Linea entry point address * @param providerGasLimit base gas limit used by the bridge adapter - * @param adapterName string indicating the adapter name * @param trustedRemotes list of remote configurations to set as trusted */ constructor( address crossChainController, address lineaMessageService, uint256 providerGasLimit, - string memory adapterName, TrustedRemotesConfig[] memory trustedRemotes - ) BaseAdapter(crossChainController, providerGasLimit, adapterName, trustedRemotes) { + ) BaseAdapter(crossChainController, providerGasLimit, 'Linea native adapter', trustedRemotes) { + require(lineaMessageService != address(0), Errors.LINEA_MESSAGE_SERVICE_CANT_BE_ADDRESS_0); LINEA_MESSAGE_SERVICE = lineaMessageService; } /// @inheritdoc IBaseAdapter function forwardMessage( address receiver, - uint256 executionGasLimit, + uint256, uint256 destinationChainId, bytes calldata message ) external virtual returns (address, uint256) { @@ -69,7 +68,7 @@ contract LineaAdapter is ILineaAdapter, BaseAdapter { } /// @inheritdoc ILineaAdapter - function ovmReceive(bytes calldata message) external onlyLineaMessageService { + function receiveMessage(bytes calldata message) external onlyLineaMessageService { uint256 originChainId = getOriginChainId(); address srcAddress = IMessageService(LINEA_MESSAGE_SERVICE).sender(); require( diff --git a/src/contracts/libs/Errors.sol b/src/contracts/libs/Errors.sol index 040f57da..a0ec2adb 100644 --- a/src/contracts/libs/Errors.sol +++ b/src/contracts/libs/Errors.sol @@ -52,4 +52,5 @@ library Errors { string public constant ZK_SYNC_BRIDGE_HUB_CANT_BE_ADDRESS_0 = '43'; // ZkSync Bridgehub can not be address 0 string public constant CL_GAS_PRICE_ORACLE_CANT_BE_ADDRESS_0 = '44'; // ChainLink gas price oracle can not be address 0 string public constant CALLER_NOT_LINEA_MESSAGE_SERVICE = '45'; // caller must be the Linea message service + string public constant LINEA_MESSAGE_SERVICE_CANT_BE_ADDRESS_0 = '46'; // Linea message service can not be address 0 } diff --git a/tests/adapters/LineaAdapter.t.sol b/tests/adapters/LineaAdapter.t.sol new file mode 100644 index 00000000..d03bc513 --- /dev/null +++ b/tests/adapters/LineaAdapter.t.sol @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity ^0.8.0; + +import {LineaAdapter, IBaseAdapter, ILineaAdapter, IMessageService} from '../../src/contracts/adapters/linea/LineaAdapter.sol'; +import {ICrossChainReceiver} from '../../src/contracts/interfaces/ICrossChainReceiver.sol'; +import {ChainIds} from 'solidity-utils/contracts/utils/ChainHelpers.sol'; +import {Errors} from '../../src/contracts/libs/Errors.sol'; +import {BaseAdapterTest} from './BaseAdapterTest.sol'; + +contract LineaAdapterTest is BaseAdapterTest { + LineaAdapter internal lineaAdapter; + event SetTrustedRemote(uint256 indexed originChainId, address indexed originForwarder); + + modifier setLineaAdapter( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + uint256 originChainId + ) { + vm.assume(crossChainController != tx.origin); // zkVM doesn't support mocking tx.origin + vm.assume(baseGasLimit < 1 ether); + _assumeSafeAddress(crossChainController); + _assumeSafeAddress(lineaMessageService); + vm.assume(originForwarder != address(0)); + vm.assume(originChainId > 0); + + IBaseAdapter.TrustedRemotesConfig memory originConfig = IBaseAdapter.TrustedRemotesConfig({ + originForwarder: originForwarder, + originChainId: originChainId + }); + IBaseAdapter.TrustedRemotesConfig[] + memory originConfigs = new IBaseAdapter.TrustedRemotesConfig[](1); + originConfigs[0] = originConfig; + + lineaAdapter = new LineaAdapter( + crossChainController, + lineaMessageService, + baseGasLimit, + originConfigs + ); + _; + } + + struct Params { + address lineaMessageService; + address receiver; + uint256 dstGasLimit; + address caller; + } + + function setUp() public {} + + function testWrongLineaMessageSender( + address crossChainController, + uint256 baseGasLimit, + address originForwarder, + uint256 originChainId + ) public { + vm.assume(crossChainController != address(0)); + vm.assume(originForwarder != address(0)); + vm.assume(originChainId > 0); + + IBaseAdapter.TrustedRemotesConfig memory originConfig = IBaseAdapter.TrustedRemotesConfig({ + originForwarder: originForwarder, + originChainId: originChainId + }); + IBaseAdapter.TrustedRemotesConfig[] + memory originConfigs = new IBaseAdapter.TrustedRemotesConfig[](1); + originConfigs[0] = originConfig; + vm.expectRevert(bytes(Errors.LINEA_MESSAGE_SERVICE_CANT_BE_ADDRESS_0)); + new LineaAdapter(crossChainController, address(0), baseGasLimit, originConfigs); + } + + function testInitialize( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + uint256 originChainId + ) + public + setLineaAdapter( + crossChainController, + lineaMessageService, + originForwarder, + baseGasLimit, + originChainId + ) + { + assertEq(lineaAdapter.getTrustedRemoteByChainId(originChainId), originForwarder); + } + + function testForwardMessage( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + uint256 originChainId + ) + public + setLineaAdapter( + crossChainController, + lineaMessageService, + originForwarder, + baseGasLimit, + originChainId + ) + { + _testForwardMessage( + Params({ + lineaMessageService: lineaMessageService, + receiver: address(135961), + dstGasLimit: 12, + caller: address(12354) + }) + ); + } + + function testForwardMessageWhenChainNotSupported( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + uint256 originChainId, + uint256 dstGasLimit, + address receiver, + bytes memory message + ) + public + setLineaAdapter( + crossChainController, + lineaMessageService, + originForwarder, + baseGasLimit, + originChainId + ) + { + vm.assume(receiver != address(0)); + + vm.expectRevert(bytes(Errors.DESTINATION_CHAIN_ID_NOT_SUPPORTED)); + lineaAdapter.forwardMessage(receiver, dstGasLimit, 11, message); + } + + function testForwardMessageWhenWrongReceiver( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + uint256 originChainId, + uint256 dstGasLimit, + bytes memory message + ) + public + setLineaAdapter( + crossChainController, + lineaMessageService, + originForwarder, + baseGasLimit, + originChainId + ) + { + vm.expectRevert(bytes(Errors.RECEIVER_NOT_SET)); + lineaAdapter.forwardMessage(address(0), dstGasLimit, ChainIds.LINEA, message); + } + + function testReceive( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + bytes memory message + ) + public + setLineaAdapter(crossChainController, lineaMessageService, originForwarder, baseGasLimit, 1) + { + hoax(lineaMessageService); + + vm.mockCall( + lineaMessageService, + abi.encodeWithSelector(IMessageService.sender.selector), + abi.encode(originForwarder) + ); + vm.mockCall( + crossChainController, + abi.encodeWithSelector(ICrossChainReceiver.receiveCrossChainMessage.selector), + abi.encode() + ); + vm.expectCall( + crossChainController, + 0, + abi.encodeWithSelector(ICrossChainReceiver.receiveCrossChainMessage.selector, message, 1) + ); + lineaAdapter.receiveMessage(message); + } + + function testReceiveWhenRemoteNotTrusted( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + bytes memory message, + address remote + ) + public + setLineaAdapter(crossChainController, lineaMessageService, originForwarder, baseGasLimit, 1) + { + vm.assume(remote != originForwarder); + hoax(lineaMessageService); + + vm.mockCall( + lineaMessageService, + abi.encodeWithSelector(IMessageService.sender.selector), + abi.encode(remote) + ); + vm.expectRevert(bytes(Errors.REMOTE_NOT_TRUSTED)); + + lineaAdapter.receiveMessage(message); + } + + function testReceiveWhenIncorrectOriginChainId( + address crossChainController, + address lineaMessageService, + address originForwarder, + uint256 baseGasLimit, + bytes memory message, + uint256 originChainId + ) + public + setLineaAdapter( + crossChainController, + lineaMessageService, + originForwarder, + baseGasLimit, + originChainId + ) + { + vm.assume(originChainId != 1); + hoax(lineaMessageService); + + vm.mockCall( + lineaMessageService, + abi.encodeWithSelector(IMessageService.sender.selector), + abi.encode(originForwarder) + ); + vm.expectRevert(bytes(Errors.REMOTE_NOT_TRUSTED)); + + lineaAdapter.receiveMessage(message); + } + + function _testForwardMessage(Params memory params) internal { + bytes memory message = abi.encode('test message'); + + hoax(params.caller, 10 ether); + + vm.mockCall( + params.lineaMessageService, + abi.encodeWithSelector(IMessageService.sendMessage.selector), + abi.encode() + ); + (bool success, bytes memory returnData) = address(lineaAdapter).delegatecall( + abi.encodeWithSelector( + IBaseAdapter.forwardMessage.selector, + params.receiver, + params.dstGasLimit, + ChainIds.LINEA, + message + ) + ); + vm.clearMockedCalls(); + + assertEq(success, true); + assertEq(returnData, abi.encode(params.lineaMessageService, 0)); + } +}