Skip to content

Commit 68467f1

Browse files
authored
chore: Migrate chain specific hardhat tests (#1296)
* chore: Migrate chain specific hardhat tests Signed-off-by: Faisal Usmani <faisal.of.usmani@gmail.com> * delete old tests Signed-off-by: Faisal Usmani <faisal.of.usmani@gmail.com> * mocks Signed-off-by: Faisal Usmani <faisal.of.usmani@gmail.com> --------- Signed-off-by: Faisal Usmani <faisal.of.usmani@gmail.com>
1 parent 9ed0c23 commit 68467f1

21 files changed

+3371
-2051
lines changed

contracts/test/LineaMocks.sol

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
import { IMessageService, ITokenBridge } from "../external/interfaces/LineaInterfaces.sol";
5+
6+
/**
7+
* @notice Mock implementation of Linea's L2 Message Service.
8+
* @dev Used for testing Linea_SpokePool functionality.
9+
*/
10+
contract MockL2MessageService is IMessageService {
11+
address private _sender;
12+
uint256 private _minimumFeeInWei;
13+
14+
// Track sendMessage calls
15+
uint256 public sendMessageCallCount;
16+
17+
event SendMessageCalled(address indexed to, uint256 fee, bytes calldata_);
18+
19+
struct SendMessageCall {
20+
address to;
21+
uint256 fee;
22+
bytes calldata_;
23+
uint256 value;
24+
}
25+
SendMessageCall public lastSendMessageCall;
26+
27+
function setSender(address sender_) external {
28+
_sender = sender_;
29+
}
30+
31+
function setMinimumFeeInWei(uint256 fee) external {
32+
_minimumFeeInWei = fee;
33+
}
34+
35+
function sendMessage(address _to, uint256 _fee, bytes calldata _calldata) external payable override {
36+
sendMessageCallCount++;
37+
lastSendMessageCall = SendMessageCall({ to: _to, fee: _fee, calldata_: _calldata, value: msg.value });
38+
emit SendMessageCalled(_to, _fee, _calldata);
39+
}
40+
41+
function sender() external view override returns (address) {
42+
return _sender;
43+
}
44+
45+
function minimumFeeInWei() external view override returns (uint256) {
46+
return _minimumFeeInWei;
47+
}
48+
49+
// Allow receiving ETH
50+
receive() external payable {}
51+
}
52+
53+
/**
54+
* @notice Mock implementation of Linea's L2 Token Bridge.
55+
* @dev Used for testing Linea_SpokePool functionality.
56+
*/
57+
contract MockL2TokenBridge is ITokenBridge {
58+
uint256 public bridgeTokenCallCount;
59+
60+
event BridgeTokenCalled(address indexed token, uint256 amount, address indexed recipient, uint256 value);
61+
62+
struct BridgeTokenCall {
63+
address token;
64+
uint256 amount;
65+
address recipient;
66+
uint256 value;
67+
}
68+
BridgeTokenCall public lastBridgeTokenCall;
69+
70+
function bridgeToken(address _token, uint256 _amount, address _recipient) external payable override {
71+
bridgeTokenCallCount++;
72+
lastBridgeTokenCall = BridgeTokenCall({
73+
token: _token,
74+
amount: _amount,
75+
recipient: _recipient,
76+
value: msg.value
77+
});
78+
emit BridgeTokenCalled(_token, _amount, _recipient, msg.value);
79+
}
80+
81+
// Allow receiving ETH
82+
receive() external payable {}
83+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
import { IPolygonZkEVMBridge } from "../external/interfaces/IPolygonZkEVMBridge.sol";
5+
6+
/**
7+
* @notice Mock implementation of Polygon zkEVM's Bridge.
8+
* @dev Used for testing PolygonZkEVM_SpokePool functionality.
9+
*/
10+
contract MockPolygonZkEVMBridge is IPolygonZkEVMBridge {
11+
uint256 public bridgeAssetCallCount;
12+
13+
event BridgeAssetCalled(
14+
uint32 indexed destinationNetwork,
15+
address indexed destinationAddress,
16+
uint256 amount,
17+
address token,
18+
bool forceUpdateGlobalExitRoot,
19+
bytes permitData
20+
);
21+
22+
struct BridgeAssetCall {
23+
uint32 destinationNetwork;
24+
address destinationAddress;
25+
uint256 amount;
26+
address token;
27+
bool forceUpdateGlobalExitRoot;
28+
bytes permitData;
29+
uint256 value;
30+
}
31+
BridgeAssetCall public lastBridgeAssetCall;
32+
33+
function bridgeAsset(
34+
uint32 destinationNetwork,
35+
address destinationAddress,
36+
uint256 amount,
37+
address token,
38+
bool forceUpdateGlobalExitRoot,
39+
bytes calldata permitData
40+
) external payable override {
41+
bridgeAssetCallCount++;
42+
lastBridgeAssetCall = BridgeAssetCall({
43+
destinationNetwork: destinationNetwork,
44+
destinationAddress: destinationAddress,
45+
amount: amount,
46+
token: token,
47+
forceUpdateGlobalExitRoot: forceUpdateGlobalExitRoot,
48+
permitData: permitData,
49+
value: msg.value
50+
});
51+
emit BridgeAssetCalled(
52+
destinationNetwork,
53+
destinationAddress,
54+
amount,
55+
token,
56+
forceUpdateGlobalExitRoot,
57+
permitData
58+
);
59+
}
60+
61+
function bridgeMessage(
62+
uint32 destinationNetwork,
63+
address destinationAddress,
64+
bool forceUpdateGlobalExitRoot,
65+
bytes calldata metadata
66+
) external payable override {
67+
// Not needed for SpokePool tests
68+
}
69+
70+
// Allow receiving ETH
71+
receive() external payable {}
72+
}

contracts/test/ScrollMocks.sol

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
import "@scroll-tech/contracts/libraries/IScrollMessenger.sol";
5+
6+
/**
7+
* @title MockScrollMessenger
8+
* @notice Mock implementation of IScrollMessenger for testing Scroll_SpokePool
9+
*/
10+
contract MockScrollMessenger is IScrollMessenger {
11+
address private _xDomainMessageSender;
12+
13+
/**
14+
* @notice Sets the xDomainMessageSender that will be returned by subsequent calls
15+
* @param sender The address to set as the cross-domain sender
16+
*/
17+
function setXDomainMessageSender(address sender) external {
18+
_xDomainMessageSender = sender;
19+
}
20+
21+
/**
22+
* @notice Returns the sender of a cross domain message
23+
*/
24+
function xDomainMessageSender() external view override returns (address) {
25+
return _xDomainMessageSender;
26+
}
27+
28+
/**
29+
* @notice Impersonates a cross-domain call by setting the xDomainMessageSender
30+
* and calling the target with the provided data
31+
* @param target The target contract to call
32+
* @param data The calldata to pass to the target
33+
*/
34+
function impersonateCall(address target, bytes memory data) external {
35+
_xDomainMessageSender = msg.sender;
36+
(bool success, bytes memory returnData) = target.call(data);
37+
if (!success) {
38+
// Forward the revert reason
39+
assembly {
40+
revert(add(returnData, 32), mload(returnData))
41+
}
42+
}
43+
_xDomainMessageSender = address(0);
44+
}
45+
46+
/**
47+
* @notice Mock implementation - does nothing
48+
*/
49+
function sendMessage(address, uint256, bytes calldata, uint256) external payable override {}
50+
51+
/**
52+
* @notice Mock implementation - does nothing
53+
*/
54+
function sendMessage(address, uint256, bytes calldata, uint256, address) external payable override {}
55+
}
56+
57+
/**
58+
* @title MockScrollL2GatewayRouter
59+
* @notice Mock implementation of IL2GatewayRouterExtended for testing Scroll_SpokePool
60+
*/
61+
contract MockScrollL2GatewayRouter {
62+
address public defaultERC20Gateway;
63+
mapping(address => address) public erc20Gateways;
64+
65+
// Track last withdrawERC20 call for verification
66+
address public lastWithdrawToken;
67+
address public lastWithdrawTo;
68+
uint256 public lastWithdrawAmount;
69+
uint256 public lastWithdrawGasLimit;
70+
71+
event WithdrawERC20Called(address indexed token, address indexed to, uint256 amount, uint256 gasLimit);
72+
73+
constructor() {
74+
defaultERC20Gateway = address(this);
75+
}
76+
77+
/**
78+
* @notice Sets the default ERC20 gateway address
79+
*/
80+
function setDefaultERC20Gateway(address gateway) external {
81+
defaultERC20Gateway = gateway;
82+
}
83+
84+
/**
85+
* @notice Sets a custom gateway for a specific token
86+
*/
87+
function setERC20Gateway(address token, address gateway) external {
88+
erc20Gateways[token] = gateway;
89+
}
90+
91+
/**
92+
* @notice Returns the gateway for a specific token, or the default gateway if not set
93+
*/
94+
function getERC20Gateway(address token) external view returns (address) {
95+
address gateway = erc20Gateways[token];
96+
return gateway != address(0) ? gateway : defaultERC20Gateway;
97+
}
98+
99+
/**
100+
* @notice Mock withdrawERC20 - records the call parameters
101+
*/
102+
function withdrawERC20(address token, address to, uint256 amount, uint256 gasLimit) external payable {
103+
lastWithdrawToken = token;
104+
lastWithdrawTo = to;
105+
lastWithdrawAmount = amount;
106+
lastWithdrawGasLimit = gasLimit;
107+
emit WithdrawERC20Called(token, to, amount, gasLimit);
108+
}
109+
}

contracts/test/ZkSyncMocks.sol

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.0;
3+
4+
/**
5+
* @notice Mock ZkSync ERC20 bridge for testing.
6+
* @dev Mimics the ZkBridgeLike interface used by ZkSync_SpokePool.
7+
*/
8+
contract MockZkBridge {
9+
// Call tracking for test assertions (smock-like behavior)
10+
uint256 public withdrawCallCount;
11+
12+
event Withdrawal(address indexed l1Receiver, address indexed l2Token, uint256 amount);
13+
14+
struct WithdrawCall {
15+
address l1Receiver;
16+
address l2Token;
17+
uint256 amount;
18+
}
19+
WithdrawCall public lastWithdrawCall;
20+
21+
// Store all calls for multi-call verification
22+
WithdrawCall[] public withdrawCalls;
23+
24+
function withdraw(address _l1Receiver, address _l2Token, uint256 _amount) external {
25+
withdrawCallCount++;
26+
lastWithdrawCall = WithdrawCall(_l1Receiver, _l2Token, _amount);
27+
withdrawCalls.push(lastWithdrawCall);
28+
emit Withdrawal(_l1Receiver, _l2Token, _amount);
29+
}
30+
31+
/**
32+
* @notice Get a specific withdraw call by index.
33+
*/
34+
function getWithdrawCall(
35+
uint256 index
36+
) external view returns (address l1Receiver, address l2Token, uint256 amount) {
37+
WithdrawCall memory call = withdrawCalls[index];
38+
return (call.l1Receiver, call.l2Token, call.amount);
39+
}
40+
}
41+
42+
/**
43+
* @notice Mock ZkSync L2 ETH contract for testing.
44+
* @dev Mimics the IL2ETH interface - ETH on ZkSync implements ERC-20 subset with L1 bridge support.
45+
*/
46+
contract MockL2Eth {
47+
// Call tracking for test assertions (smock-like behavior)
48+
uint256 public withdrawCallCount;
49+
50+
event EthWithdrawal(address indexed l1Receiver, uint256 amount);
51+
52+
struct WithdrawCall {
53+
address l1Receiver;
54+
uint256 amount;
55+
}
56+
WithdrawCall public lastWithdrawCall;
57+
58+
// Store all calls for multi-call verification
59+
WithdrawCall[] public withdrawCalls;
60+
61+
function withdraw(address _l1Receiver) external payable {
62+
withdrawCallCount++;
63+
lastWithdrawCall = WithdrawCall(_l1Receiver, msg.value);
64+
withdrawCalls.push(lastWithdrawCall);
65+
emit EthWithdrawal(_l1Receiver, msg.value);
66+
}
67+
68+
/**
69+
* @notice Get a specific withdraw call by index.
70+
*/
71+
function getWithdrawCall(uint256 index) external view returns (address l1Receiver, uint256 amount) {
72+
WithdrawCall memory call = withdrawCalls[index];
73+
return (call.l1Receiver, call.amount);
74+
}
75+
76+
// Allow receiving ETH
77+
receive() external payable {}
78+
}

0 commit comments

Comments
 (0)