|
| 1 | +// SPDX-License-Identifier: Apache-2.0 |
| 2 | +pragma solidity ^0.8.25; |
| 3 | + |
| 4 | +import {TransparentUpgradeableProxy} from |
| 5 | + "lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; |
| 6 | +import {Ownable} from "lib/openzeppelin-contracts/contracts/access/Ownable.sol"; |
| 7 | +import {IAvailAttestation, AvailAttestation} from "src/AvailAttestation.sol"; |
| 8 | +import {VectorxMock, IVectorx} from "src/mocks/VectorxMock.sol"; |
| 9 | +import {MurkyBase} from "lib/murky/src/common/MurkyBase.sol"; |
| 10 | +import {Vm, Test, console} from "forge-std/Test.sol"; |
| 11 | + |
| 12 | +contract AvailAttestationTest is Test, MurkyBase { |
| 13 | + AvailAttestation public bridge; |
| 14 | + VectorxMock public vectorx; |
| 15 | + Sha2Merkle public sha2merkle; |
| 16 | + address public owner; |
| 17 | + bytes public constant revertCode = "5F5FFD"; |
| 18 | + |
| 19 | + function setUp() external { |
| 20 | + vectorx = new VectorxMock(); |
| 21 | + sha2merkle = new Sha2Merkle(); |
| 22 | + address impl = address(new AvailAttestation()); |
| 23 | + bridge = AvailAttestation(address(new TransparentUpgradeableProxy(impl, msg.sender, ""))); |
| 24 | + bridge.initialize(msg.sender, IVectorx(vectorx)); |
| 25 | + owner = msg.sender; |
| 26 | + } |
| 27 | + |
| 28 | + function test_owner() external view { |
| 29 | + assertNotEq(bridge.owner(), address(0)); |
| 30 | + assertEq(bridge.owner(), owner); |
| 31 | + } |
| 32 | + |
| 33 | + function testRevertOwnableUnauthorizedAccount_updateVectorx(IVectorx newVectorx) external { |
| 34 | + address rand = makeAddr("rand"); |
| 35 | + vm.assume(rand != owner); |
| 36 | + vm.expectRevert(abi.encodeWithSelector((Ownable.OwnableUnauthorizedAccount.selector), rand, 0x0)); |
| 37 | + vm.prank(rand); |
| 38 | + bridge.updateVectorx(newVectorx); |
| 39 | + } |
| 40 | + |
| 41 | + function test_updateVectorx(IVectorx newVectorx) external { |
| 42 | + vm.prank(owner); |
| 43 | + bridge.updateVectorx(newVectorx); |
| 44 | + assertEq(address(bridge.vectorx()), address(newVectorx)); |
| 45 | + } |
| 46 | + |
| 47 | + function testRevertBlobRootEmpty_verifyBlobLeaf(IAvailAttestation.MerkleProofInput memory input) external { |
| 48 | + input.blobRoot = 0x0; |
| 49 | + vm.expectRevert(IAvailAttestation.BlobRootEmpty.selector); |
| 50 | + bridge.verifyBlobLeaf(input); |
| 51 | + } |
| 52 | + |
| 53 | + function test_verifyBlobLeaf( |
| 54 | + bytes32[16] calldata preimages, |
| 55 | + bytes32[16] calldata c_dataRoots, |
| 56 | + bytes32 rangeHash, |
| 57 | + uint256 rand, |
| 58 | + bytes32 bridgeRoot |
| 59 | + ) external { |
| 60 | + // we use a fixed size array because the fuzzer rejects too many inputs with arbitrary lengths |
| 61 | + bytes32[] memory dataRoots = new bytes32[](c_dataRoots.length); |
| 62 | + bytes32[] memory leaves = new bytes32[](preimages.length); |
| 63 | + for (uint256 i = 0; i < preimages.length;) { |
| 64 | + dataRoots[i] = c_dataRoots[i]; |
| 65 | + leaves[i] = keccak256(abi.encode(preimages[i])); |
| 66 | + unchecked { |
| 67 | + ++i; |
| 68 | + } |
| 69 | + } |
| 70 | + bytes32 blobRoot = getRoot(leaves); |
| 71 | + bytes32 dataRoot = hashLeafPairs(blobRoot, bridgeRoot); |
| 72 | + // set dataRoot at this point in the array |
| 73 | + dataRoots[rand % dataRoots.length] = dataRoot; |
| 74 | + bytes32 dataRootCommitment = sha2merkle.getRoot(dataRoots); |
| 75 | + bytes32[] memory dataRootProof = sha2merkle.getProof(dataRoots, rand % dataRoots.length); |
| 76 | + vectorx.set(rangeHash, dataRootCommitment); |
| 77 | + for (uint256 i = 0; i < leaves.length;) { |
| 78 | + bytes32[] memory leafProof = getProof(leaves, i); |
| 79 | + IAvailAttestation.MerkleProofInput memory input = IAvailAttestation.MerkleProofInput( |
| 80 | + dataRootProof, leafProof, rangeHash, rand % dataRoots.length, blobRoot, bridgeRoot, preimages[i], i |
| 81 | + ); |
| 82 | + assertTrue(bridge.verifyBlobLeaf(input)); |
| 83 | + unchecked { |
| 84 | + ++i; |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + |
| 89 | + function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32) { |
| 90 | + return keccak256(abi.encode(left, right)); |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +contract Sha2Merkle is MurkyBase { |
| 95 | + function hashLeafPairs(bytes32 left, bytes32 right) public pure override returns (bytes32) { |
| 96 | + return sha256(abi.encode(left, right)); |
| 97 | + } |
| 98 | +} |
0 commit comments