Skip to content

Commit c21b3c8

Browse files
committed
test: add leaf verification tests
1 parent ba9939e commit c21b3c8

File tree

2 files changed

+84
-17
lines changed

2 files changed

+84
-17
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,6 @@ Cargo.lock
1515
cache/
1616
out/
1717
broadcast/
18+
coverage/
19+
lcov.info
20+
.DS_Store

test/AvailBridgeTest.t.sol

+81-17
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ import {VectorxMock, IVectorx} from "src/mocks/VectorxMock.sol";
1010
import {ERC20Mock} from "src/mocks/ERC20Mock.sol";
1111
import {MessageReceiverMock} from "src/mocks/MessageReceiverMock.sol";
1212
import {Vm, Test} from "forge-std/Test.sol";
13+
import {MurkyBase} from "lib/murky/src/common/MurkyBase.sol";
1314

14-
contract AvailBridgeTest is Test {
15+
contract AvailBridgeTest is Test, MurkyBase {
1516
AvailBridge public bridge;
1617
WrappedAvail public avail;
1718
VectorxMock public vectorx;
@@ -52,8 +53,9 @@ contract AvailBridgeTest is Test {
5253
bridge.receiveMessage(message, input);
5354
}
5455

55-
function test_receiveAVL(bytes32 rangeHash, bytes32 from, address to, uint256 amount, uint64 messageId) external {
56-
vm.assume(to != address(0) && amount != 0);
56+
function test_receiveAVL(bytes32 rangeHash, bytes32 from, uint256 amount, uint64 messageId) external {
57+
vm.assume(amount != 0);
58+
address to = makeAddr("to");
5759
AvailBridge.Message memory message =
5860
AvailBridge.Message(0x02, from, bytes32(bytes20(to)), 1, 2, abi.encode(bytes32(0), amount), messageId);
5961
bytes32 messageHash = keccak256(abi.encode(message));
@@ -70,10 +72,9 @@ contract AvailBridgeTest is Test {
7072
assertEq(avail.totalSupply(), amount);
7173
}
7274

73-
function test_receiveETH(bytes32 rangeHash, bytes32 from, address to, uint256 amount, uint64 messageId) external {
74-
// while technically contracts can receive ETH, foundry fuzzes with a lot of random contracts and precompiles
75-
// that cannot receive ETH
76-
vm.assume(amount != 0 && to.code.length == 0 && uint256(uint160(to)) > 9);
75+
function test_receiveETH(bytes32 rangeHash, bytes32 from, uint256 amount, uint64 messageId) external {
76+
vm.assume(amount != 0);
77+
address to = makeAddr("to");
7778
vm.deal(address(bridge), amount);
7879
AvailBridge.Message memory message = AvailBridge.Message(
7980
0x02,
@@ -102,11 +103,11 @@ contract AvailBridgeTest is Test {
102103
bytes32 rangeHash,
103104
bytes32 assetId,
104105
bytes32 from,
105-
address to,
106106
uint256 amount,
107107
uint64 messageId
108108
) external {
109-
vm.assume(amount != 0 && to != address(0) && to != address(bridge));
109+
vm.assume(amount != 0);
110+
address to = makeAddr("to");
110111
ERC20Mock token = new ERC20Mock();
111112
token.mint(address(bridge), amount);
112113
bytes32[] memory assetIdArr = new bytes32[](1);
@@ -132,8 +133,9 @@ contract AvailBridgeTest is Test {
132133
assertEq(newBalance, balance + amount);
133134
}
134135

135-
function test_sendAVL(address from, bytes32 to, uint256 amount) external {
136-
vm.assume(from != address(0) && to != bytes32(0) && amount != 0 && from != address(admin));
136+
function test_sendAVL(bytes32 to, uint256 amount) external {
137+
vm.assume(to != bytes32(0) && amount != 0);
138+
address from = makeAddr("from");
137139
vm.prank(address(bridge));
138140
avail.mint(from, amount);
139141
AvailBridge.Message memory message =
@@ -146,10 +148,9 @@ contract AvailBridgeTest is Test {
146148
assertEq(avail.totalSupply(), 0);
147149
}
148150

149-
function test_sendETH(address from, bytes32 to, uint256 amount) external {
150-
vm.assume(
151-
from != address(0) && to != bytes32(0) && amount != 0 && from != address(admin) && from != address(bridge)
152-
);
151+
function test_sendETH(bytes32 to, uint256 amount) external {
152+
vm.assume(to != bytes32(0) && amount != 0);
153+
address from = makeAddr("from");
153154
vm.deal(from, amount);
154155
AvailBridge.Message memory message = AvailBridge.Message(
155156
0x02,
@@ -168,8 +169,9 @@ contract AvailBridgeTest is Test {
168169
assertEq(from.balance, balance - amount);
169170
}
170171

171-
function test_sendERC20(bytes32 assetId, address from, bytes32 to, uint256 amount) external {
172-
vm.assume(from != address(0) && to != bytes32(0) && amount != 0 && from != address(admin));
172+
function test_sendERC20(bytes32 assetId, bytes32 to, uint256 amount) external {
173+
vm.assume(to != bytes32(0) && amount != 0);
174+
address from = makeAddr("from");
173175
ERC20Mock token = new ERC20Mock();
174176
token.mint(from, amount);
175177
bytes32[] memory assetIdArr = new bytes32[](1);
@@ -188,4 +190,66 @@ contract AvailBridgeTest is Test {
188190
assertEq(token.balanceOf(from), 0);
189191
assertEq(token.balanceOf(address(bridge)), amount);
190192
}
193+
194+
function test_verifyBlobLeaf(bytes32[16] calldata preimages, bytes32[16] calldata c_dataRoots, bytes32 rangeHash, uint256 rand, bytes32 bridgeRoot) external {
195+
// we use a fixed size array because the fuzzer rejects too many inputs with arbitrary lengths
196+
bytes32[] memory dataRoots = new bytes32[](c_dataRoots.length);
197+
bytes32[] memory leaves = new bytes32[](preimages.length);
198+
for (uint256 i = 0; i < preimages.length; ) {
199+
dataRoots[i] = c_dataRoots[i];
200+
leaves[i] = keccak256(abi.encode(preimages[i]));
201+
unchecked {
202+
++i;
203+
}
204+
}
205+
bytes32 blobRoot = getRoot(leaves);
206+
bytes32 dataRoot = hashLeafPairs(blobRoot, bridgeRoot);
207+
// set dataRoot at this point in the array
208+
dataRoots[rand % dataRoots.length] = dataRoot;
209+
bytes32 dataRootCommitment = getRoot(dataRoots);
210+
bytes32[] memory dataRootProof = getProof(dataRoots, rand % dataRoots.length);
211+
vectorx.set(rangeHash, dataRootCommitment);
212+
for (uint256 i = 0; i < leaves.length; ) {
213+
bytes32[] memory leafProof = getProof(leaves, i);
214+
AvailBridge.MerkleProofInput memory input =
215+
AvailBridge.MerkleProofInput(dataRootProof, leafProof, rangeHash, rand % dataRoots.length, blobRoot, bridgeRoot, preimages[i], i);
216+
assertTrue(bridge.verifyBlobLeaf(input));
217+
unchecked {
218+
++i;
219+
}
220+
}
221+
}
222+
223+
function test_verifyBridgeLeaf(bytes32[16] calldata c_leaves, bytes32[16] calldata c_dataRoots, bytes32 rangeHash, uint256 rand, bytes32 blobRoot) external {
224+
// we use a fixed size array because the fuzzer rejects too many inputs with arbitrary lengths
225+
bytes32[] memory dataRoots = new bytes32[](c_dataRoots.length);
226+
bytes32[] memory leaves = new bytes32[](c_leaves.length);
227+
for (uint256 i = 0; i < c_leaves.length; ) {
228+
dataRoots[i] = c_dataRoots[i];
229+
leaves[i] = c_leaves[i];
230+
unchecked {
231+
++i;
232+
}
233+
}
234+
bytes32 bridgeRoot = getRoot(leaves);
235+
bytes32 dataRoot = hashLeafPairs(blobRoot, bridgeRoot);
236+
// set dataRoot at this point in the array
237+
dataRoots[rand % dataRoots.length] = dataRoot;
238+
bytes32 dataRootCommitment = getRoot(dataRoots);
239+
bytes32[] memory dataRootProof = getProof(dataRoots, rand % dataRoots.length);
240+
vectorx.set(rangeHash, dataRootCommitment);
241+
for (uint256 i = 0; i < leaves.length; ) {
242+
bytes32[] memory leafProof = getProof(leaves, i);
243+
AvailBridge.MerkleProofInput memory input =
244+
AvailBridge.MerkleProofInput(dataRootProof, leafProof, rangeHash, rand % dataRoots.length, blobRoot, bridgeRoot, leaves[i], i);
245+
assertTrue(bridge.verifyBridgeLeaf(input));
246+
unchecked {
247+
++i;
248+
}
249+
}
250+
}
251+
252+
function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32) {
253+
return keccak256(abi.encode(left, right));
254+
}
191255
}

0 commit comments

Comments
 (0)