Skip to content

Commit 24eb09d

Browse files
committed
feat(tests): Add comprehensive tests for RLCOFT and related contracts
1 parent f5c1400 commit 24eb09d

File tree

5 files changed

+498
-0
lines changed

5 files changed

+498
-0
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@ verify-oft:
7373
# Combined verification target
7474
verify-all: verify-adapter verify-oft
7575

76+
test-rlcoft:
77+
@echo "Running RLC OFT tests..."
78+
forge test --match-contract RLCOFTTest -vvv
79+
7680
# Test and utility targets
7781
test:
7882
@echo "Running tests..."

test/TokenSpenderMock.sol

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.22;
3+
4+
import "../src/TokenSpender.sol";
5+
6+
contract TokenSpenderMock is TokenSpender {
7+
address public lastCaller;
8+
uint256 public lastAmount;
9+
address public lastToken;
10+
bytes public lastData;
11+
12+
function receiveApproval(
13+
address _sender,
14+
uint256 _value,
15+
address _token,
16+
bytes calldata _extraData
17+
) external override {
18+
lastCaller = _sender;
19+
lastAmount = _value;
20+
lastToken = _token;
21+
lastData = _extraData;
22+
}
23+
}

test/mocks/ERC20Mock.sol

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.22;
3+
4+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
6+
contract ERC20Mock is ERC20 {
7+
uint8 private _decimals = 9;
8+
9+
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}
10+
11+
function mint(address to, uint256 amount) external {
12+
_mint(to, amount);
13+
}
14+
15+
function decimals() public view override returns (uint8) {
16+
return _decimals;
17+
}
18+
19+
function setDecimals(uint8 newDecimals) external {
20+
_decimals = newDecimals;
21+
}
22+
}

test/mocks/LZEndpointMock.sol

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.22;
3+
4+
import {ILayerZeroEndpoint} from "@layerzerolabs/oft-evm/contracts/interfaces/ILayerZeroEndpoint.sol";
5+
import {ILayerZeroReceiver} from "@layerzerolabs/oft-evm/contracts/interfaces/ILayerZeroReceiver.sol";
6+
7+
contract LZEndpointMock is ILayerZeroEndpoint {
8+
uint16 public chainId;
9+
mapping(uint16 => address) public destinations;
10+
11+
constructor(uint16 _chainId) {
12+
chainId = _chainId;
13+
}
14+
15+
function setDestLzEndpoint(address destLzEndpoint, uint16 destChainId) external {
16+
destinations[destChainId] = destLzEndpoint;
17+
}
18+
19+
function estimateFees(
20+
uint16 _dstChainId,
21+
address _userApplication,
22+
bytes calldata _payload,
23+
bool _payInZRO,
24+
bytes calldata _adapterParam
25+
) external view override returns (uint256 nativeFee, uint256 zroFee) {
26+
nativeFee = 0.01 ether;
27+
zroFee = 0;
28+
}
29+
30+
function send(
31+
uint16 _dstChainId,
32+
bytes calldata _destination,
33+
bytes calldata _payload,
34+
address payable _refundAddress,
35+
address _zroPaymentAddress,
36+
bytes calldata _adapterParams
37+
) external payable override returns (bytes memory) {
38+
address destEndpoint = destinations[_dstChainId];
39+
require(destEndpoint != address(0), "Destination not set");
40+
41+
address dstAddress;
42+
assembly {
43+
dstAddress := mload(add(_destination, 20))
44+
}
45+
46+
LZEndpointMock(destEndpoint).receivePayload(
47+
chainId,
48+
abi.encodePacked(msg.sender),
49+
dstAddress,
50+
0, // nonce doesn't matter for testing
51+
100000, // gas limit, doesn't matter for testing
52+
_payload
53+
);
54+
55+
return "";
56+
}
57+
58+
function receivePayload(
59+
uint16 _srcChainId,
60+
bytes memory _srcAddress,
61+
address _dstAddress,
62+
uint64 _nonce,
63+
uint256 _gasLimit,
64+
bytes memory _payload
65+
) external {
66+
address srcAddress;
67+
assembly {
68+
srcAddress := mload(add(_srcAddress, 20))
69+
}
70+
71+
ILayerZeroReceiver(_dstAddress).lzReceive(
72+
_srcChainId,
73+
_srcAddress,
74+
_nonce,
75+
_payload
76+
);
77+
}
78+
79+
// Implement the remaining interfaces with minimal functionality for testing
80+
function getChainId() external view override returns (uint16) {
81+
return chainId;
82+
}
83+
84+
function getConfig(
85+
uint16, /* _version */
86+
uint16, /* _chainId */
87+
address, /* _userApplication */
88+
uint256 /* _configType */
89+
) external pure override returns (bytes memory) {
90+
return "";
91+
}
92+
93+
function getInboundNonce(uint16, bytes calldata) external pure override returns (uint64) {
94+
return 0;
95+
}
96+
97+
function getOutboundNonce(uint16, address) external pure override returns (uint64) {
98+
return 0;
99+
}
100+
101+
function hasStoredPayload(uint16, bytes calldata) external pure override returns (bool) {
102+
return false;
103+
}
104+
105+
function isReceivingPayload() external pure override returns (bool) {
106+
return false;
107+
}
108+
109+
function isSendingPayload() external pure override returns (bool) {
110+
return false;
111+
}
112+
113+
function receivePayloadAndRetryAffected(
114+
uint16, bytes calldata, address, uint64, uint256, bytes calldata, bytes calldata
115+
) external pure override {}
116+
117+
function retryPayload(
118+
uint16, bytes calldata, bytes calldata
119+
) external pure override {}
120+
121+
function setConfig(
122+
uint16, uint16, address, uint256, bytes calldata
123+
) external pure override {}
124+
125+
function setSendVersion(uint16) external pure override {}
126+
127+
function setReceiveVersion(uint16) external pure override {}
128+
}

0 commit comments

Comments
 (0)