github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/L1/DataAvailabilityChallenge.t.sol (about) 1 // SPDX-License-Identifier: MIT 2 pragma solidity 0.8.15; 3 4 import { 5 DataAvailabilityChallenge, 6 ChallengeStatus, 7 Challenge, 8 CommitmentType, 9 computeCommitmentKeccak256 10 } from "src/L1/DataAvailabilityChallenge.sol"; 11 import { Proxy } from "src/universal/Proxy.sol"; 12 import { CommonTest } from "test/setup/CommonTest.sol"; 13 14 contract DataAvailabilityChallengeTest is CommonTest { 15 function setUp() public virtual override { 16 super.enablePlasma(); 17 super.setUp(); 18 } 19 20 function testDeposit() public { 21 assertEq(dataAvailabilityChallenge.balances(address(this)), 0); 22 dataAvailabilityChallenge.deposit{ value: 1000 }(); 23 assertEq(dataAvailabilityChallenge.balances(address(this)), 1000); 24 } 25 26 function testReceive() public { 27 assertEq(dataAvailabilityChallenge.balances(address(this)), 0); 28 (bool success,) = payable(address(dataAvailabilityChallenge)).call{ value: 1000 }(""); 29 assertTrue(success); 30 assertEq(dataAvailabilityChallenge.balances(address(this)), 1000); 31 } 32 33 function testWithdraw(address sender, uint256 amount) public { 34 assumePayable(sender); 35 assumeNotPrecompile(sender); 36 vm.assume(sender != address(dataAvailabilityChallenge)); 37 vm.assume(sender.balance == 0); 38 vm.deal(sender, amount); 39 40 vm.prank(sender); 41 dataAvailabilityChallenge.deposit{ value: amount }(); 42 43 assertEq(dataAvailabilityChallenge.balances(sender), amount); 44 assertEq(sender.balance, 0); 45 46 vm.prank(sender); 47 dataAvailabilityChallenge.withdraw(); 48 49 assertEq(dataAvailabilityChallenge.balances(sender), 0); 50 assertEq(sender.balance, amount); 51 } 52 53 function testChallengeSuccess(address challenger, uint256 challengedBlockNumber, bytes calldata preImage) public { 54 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 55 56 // Assume the challenger is not the 0 address 57 vm.assume(challenger != address(0)); 58 59 // Assume the block number is not close to the max uint256 value 60 vm.assume( 61 challengedBlockNumber 62 < type(uint256).max - dataAvailabilityChallenge.challengeWindow() 63 - dataAvailabilityChallenge.resolveWindow() 64 ); 65 uint256 requiredBond = dataAvailabilityChallenge.bondSize(); 66 67 // Move to a block after the challenged block 68 vm.roll(challengedBlockNumber + 1); 69 70 // Deposit the required bond 71 vm.deal(challenger, requiredBond); 72 vm.prank(challenger); 73 dataAvailabilityChallenge.deposit{ value: requiredBond }(); 74 75 // Expect the challenge status to be uninitialized 76 assertEq( 77 uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), 78 uint8(ChallengeStatus.Uninitialized) 79 ); 80 81 // Challenge a (blockNumber,hash) tuple 82 vm.prank(challenger); 83 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 84 85 // Challenge should have been created 86 Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); 87 assertEq(challenge.challenger, challenger); 88 assertEq(challenge.startBlock, block.number); 89 assertEq(challenge.resolvedBlock, 0); 90 assertEq(challenge.lockedBond, requiredBond); 91 assertEq( 92 uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), 93 uint8(ChallengeStatus.Active) 94 ); 95 96 // Challenge should have decreased the challenger's bond size 97 assertEq(dataAvailabilityChallenge.balances(challenger), 0); 98 } 99 100 function testChallengeDeposit(address challenger, uint256 challengedBlockNumber, bytes memory preImage) public { 101 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 102 103 // Assume the challenger is not the 0 address 104 vm.assume(challenger != address(0)); 105 106 // Assume the block number is not close to the max uint256 value 107 vm.assume( 108 challengedBlockNumber 109 < type(uint256).max - dataAvailabilityChallenge.challengeWindow() 110 - dataAvailabilityChallenge.resolveWindow() 111 ); 112 uint256 requiredBond = dataAvailabilityChallenge.bondSize(); 113 114 // Move to a block after the challenged block 115 vm.roll(challengedBlockNumber + 1); 116 117 // Expect the challenge status to be uninitialized 118 assertEq( 119 uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), 120 uint8(ChallengeStatus.Uninitialized) 121 ); 122 123 // Deposit the required bond as part of the challenge transaction 124 vm.deal(challenger, requiredBond); 125 vm.prank(challenger); 126 dataAvailabilityChallenge.challenge{ value: requiredBond }(challengedBlockNumber, challengedCommitment); 127 128 // Challenge should have been created 129 Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); 130 assertEq(challenge.challenger, challenger); 131 assertEq(challenge.startBlock, block.number); 132 assertEq(challenge.resolvedBlock, 0); 133 assertEq(challenge.lockedBond, requiredBond); 134 assertEq( 135 uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), 136 uint8(ChallengeStatus.Active) 137 ); 138 139 // Challenge should have decreased the challenger's bond size 140 assertEq(dataAvailabilityChallenge.balances(challenger), 0); 141 } 142 143 function testChallengeFailBondTooLow() public { 144 uint256 requiredBond = dataAvailabilityChallenge.bondSize(); 145 uint256 actualBond = requiredBond - 1; 146 dataAvailabilityChallenge.deposit{ value: actualBond }(); 147 148 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond)); 149 dataAvailabilityChallenge.challenge(0, computeCommitmentKeccak256("some hash")); 150 } 151 152 function testChallengeFailChallengeExists() public { 153 // Move to a block after the hash to challenge 154 vm.roll(2); 155 156 // First challenge succeeds 157 bytes memory challengedCommitment = computeCommitmentKeccak256("some data"); 158 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 159 dataAvailabilityChallenge.challenge(0, challengedCommitment); 160 161 // Second challenge of the same hash/blockNumber fails 162 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 163 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeExists.selector)); 164 dataAvailabilityChallenge.challenge(0, challengedCommitment); 165 166 // Challenge succeed if the challenged block number is different 167 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 168 dataAvailabilityChallenge.challenge(1, challengedCommitment); 169 170 // Challenge succeed if the challenged hash is different 171 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 172 dataAvailabilityChallenge.challenge(0, computeCommitmentKeccak256("some other hash")); 173 } 174 175 function testChallengeFailBeforeChallengeWindow() public { 176 uint256 challengedBlockNumber = 1; 177 bytes memory challengedCommitment = computeCommitmentKeccak256("some hash"); 178 179 // Move to challenged block 180 vm.roll(challengedBlockNumber - 1); 181 182 // Challenge fails because the current block number must be after the challenged block 183 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 184 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); 185 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 186 } 187 188 function testChallengeFailAfterChallengeWindow() public { 189 uint256 challengedBlockNumber = 1; 190 bytes memory challengedCommitment = computeCommitmentKeccak256("some hash"); 191 192 // Move to block after the challenge window 193 vm.roll(challengedBlockNumber + dataAvailabilityChallenge.challengeWindow() + 1); 194 195 // Challenge fails because the block number is after the challenge window 196 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 197 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeWindowNotOpen.selector)); 198 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 199 } 200 201 function testResolveSuccess( 202 address challenger, 203 address resolver, 204 bytes memory preImage, 205 uint256 challengedBlockNumber, 206 uint256 resolverRefundPercentage, 207 uint128 txGasPrice 208 ) 209 public 210 { 211 // Assume neither the challenger nor resolver is address(0) and that they're not the same entity 212 vm.assume(challenger != address(0)); 213 vm.assume(resolver != address(0)); 214 vm.assume(challenger != resolver); 215 216 // Bound the resolver refund percentage to 100 217 resolverRefundPercentage = bound(resolverRefundPercentage, 0, 100); 218 219 // Set the gas price to a fuzzed value to test bond distribution logic 220 vm.txGasPrice(txGasPrice); 221 222 // Change the resolver refund percentage 223 vm.prank(dataAvailabilityChallenge.owner()); 224 dataAvailabilityChallenge.setResolverRefundPercentage(resolverRefundPercentage); 225 226 // Assume the block number is not close to the max uint256 value 227 vm.assume( 228 challengedBlockNumber 229 < type(uint256).max - dataAvailabilityChallenge.challengeWindow() 230 - dataAvailabilityChallenge.resolveWindow() 231 ); 232 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 233 234 // Move to block after challenged block 235 vm.roll(challengedBlockNumber + 1); 236 237 // Challenge the hash 238 uint256 bondSize = dataAvailabilityChallenge.bondSize(); 239 vm.deal(challenger, bondSize); 240 vm.prank(challenger); 241 dataAvailabilityChallenge.challenge{ value: bondSize }(challengedBlockNumber, challengedCommitment); 242 243 // Store the address(0) balance before resolving to assert the burned amount later 244 uint256 zeroAddressBalanceBeforeResolve = address(0).balance; 245 246 // Resolve the challenge 247 vm.prank(resolver); 248 dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); 249 250 // Expect the challenge to be resolved 251 Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); 252 253 assertEq(challenge.challenger, challenger); 254 assertEq(challenge.lockedBond, 0); 255 assertEq(challenge.startBlock, block.number); 256 assertEq(challenge.resolvedBlock, block.number); 257 assertEq( 258 uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), 259 uint8(ChallengeStatus.Resolved) 260 ); 261 262 // Assert challenger balance after bond distribution 263 uint256 resolutionCost = ( 264 dataAvailabilityChallenge.fixedResolutionCost() 265 + preImage.length * dataAvailabilityChallenge.variableResolutionCost() 266 / dataAvailabilityChallenge.variableResolutionCostPrecision() 267 ) * block.basefee; 268 uint256 challengerRefund = bondSize > resolutionCost ? bondSize - resolutionCost : 0; 269 assertEq(dataAvailabilityChallenge.balances(challenger), challengerRefund, "challenger refund"); 270 271 // Assert resolver balance after bond distribution 272 uint256 resolverRefund = resolutionCost * dataAvailabilityChallenge.resolverRefundPercentage() / 100; 273 resolverRefund = resolverRefund > resolutionCost ? resolutionCost : resolverRefund; 274 resolverRefund = resolverRefund > bondSize ? bondSize : resolverRefund; 275 assertEq(dataAvailabilityChallenge.balances(resolver), resolverRefund, "resolver refund"); 276 277 // Assert burned amount after bond distribution 278 uint256 burned = bondSize - challengerRefund - resolverRefund; 279 assertEq(address(0).balance - zeroAddressBalanceBeforeResolve, burned, "burned bond"); 280 } 281 282 function testResolveFailNonExistentChallenge() public { 283 bytes memory preImage = "some preimage"; 284 uint256 challengedBlockNumber = 1; 285 286 // Move to block after challenged block 287 vm.roll(challengedBlockNumber + 1); 288 289 // Resolving a non-existent challenge fails 290 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); 291 dataAvailabilityChallenge.resolve(challengedBlockNumber, computeCommitmentKeccak256(preImage), preImage); 292 } 293 294 function testResolveFailResolved() public { 295 bytes memory preImage = "some preimage"; 296 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 297 uint256 challengedBlockNumber = 1; 298 299 // Move to block after challenged block 300 vm.roll(challengedBlockNumber + 1); 301 302 // Challenge the hash 303 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 304 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 305 306 // Resolve the challenge 307 dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); 308 309 // Resolving an already resolved challenge fails 310 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); 311 dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); 312 } 313 314 function testResolveFailExpired() public { 315 bytes memory preImage = "some preimage"; 316 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 317 uint256 challengedBlockNumber = 1; 318 319 // Move to block after challenged block 320 vm.roll(challengedBlockNumber + 1); 321 322 // Challenge the hash 323 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 324 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 325 326 // Move to a block after the resolve window 327 vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); 328 329 // Resolving an expired challenge fails 330 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); 331 dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); 332 } 333 334 function testResolveFailAfterResolveWindow() public { 335 bytes memory preImage = "some preimage"; 336 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 337 uint256 challengedBlockNumber = 1; 338 339 // Move to block after challenged block 340 vm.roll(challengedBlockNumber + 1); 341 342 // Challenge the hash 343 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 344 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 345 346 // Move to block after resolve window 347 vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); 348 349 // Resolve the challenge 350 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotActive.selector)); 351 dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); 352 } 353 354 function testUnlockBondSuccess(bytes memory preImage, uint256 challengedBlockNumber) public { 355 // Assume the block number is not close to the max uint256 value 356 vm.assume( 357 challengedBlockNumber 358 < type(uint256).max - dataAvailabilityChallenge.challengeWindow() 359 - dataAvailabilityChallenge.resolveWindow() 360 ); 361 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 362 363 // Move to block after challenged block 364 vm.roll(challengedBlockNumber + 1); 365 366 // Challenge the hash 367 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 368 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 369 370 // Move to a block after the resolve window 371 vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); 372 373 uint256 balanceBeforeUnlock = dataAvailabilityChallenge.balances(address(this)); 374 375 // Unlock the bond associated with the challenge 376 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 377 378 // Expect the balance to be increased by the bond size 379 uint256 balanceAfterUnlock = dataAvailabilityChallenge.balances(address(this)); 380 assertEq(balanceAfterUnlock, balanceBeforeUnlock + dataAvailabilityChallenge.bondSize()); 381 382 // Expect the bond to be unlocked 383 Challenge memory challenge = dataAvailabilityChallenge.getChallenge(challengedBlockNumber, challengedCommitment); 384 385 assertEq(challenge.challenger, address(this)); 386 assertEq(challenge.lockedBond, 0); 387 assertEq(challenge.startBlock, challengedBlockNumber + 1); 388 assertEq(challenge.resolvedBlock, 0); 389 assertEq( 390 uint8(dataAvailabilityChallenge.getChallengeStatus(challengedBlockNumber, challengedCommitment)), 391 uint8(ChallengeStatus.Expired) 392 ); 393 394 // Unlock the bond again, expect the balance to remain the same 395 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 396 assertEq(dataAvailabilityChallenge.balances(address(this)), balanceAfterUnlock); 397 } 398 399 function testUnlockBondFailNonExistentChallenge() public { 400 bytes memory preImage = "some preimage"; 401 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 402 uint256 challengedBlockNumber = 1; 403 404 // Move to block after challenged block 405 vm.roll(challengedBlockNumber + 1); 406 407 // Unlock a bond of a non-existent challenge fails 408 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); 409 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 410 } 411 412 function testUnlockBondFailResolvedChallenge() public { 413 bytes memory preImage = "some preimage"; 414 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 415 uint256 challengedBlockNumber = 1; 416 417 // Move to block after challenged block 418 vm.roll(challengedBlockNumber + 1); 419 420 // Challenge the hash 421 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 422 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 423 424 // Resolve the challenge 425 dataAvailabilityChallenge.resolve(challengedBlockNumber, challengedCommitment, preImage); 426 427 // Attempting to unlock a bond of a resolved challenge fails 428 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); 429 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 430 } 431 432 function testUnlockBondExpiredChallengeTwice() public { 433 bytes memory preImage = "some preimage"; 434 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 435 uint256 challengedBlockNumber = 1; 436 437 // Move to block after challenged block 438 vm.roll(challengedBlockNumber + 1); 439 440 // Challenge the hash 441 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 442 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 443 444 // Move to a block after the challenge window 445 vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() + 1); 446 447 // Unlock the bond 448 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 449 450 uint256 balanceAfterUnlock = dataAvailabilityChallenge.balances(address(this)); 451 452 // Unlock the bond again doesn't change the balance 453 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 454 assertEq(dataAvailabilityChallenge.balances(address(this)), balanceAfterUnlock); 455 } 456 457 function testUnlockFailResolveWindowNotClosed() public { 458 bytes memory preImage = "some preimage"; 459 bytes memory challengedCommitment = computeCommitmentKeccak256(preImage); 460 uint256 challengedBlockNumber = 1; 461 462 // Move to block after challenged block 463 vm.roll(challengedBlockNumber + 1); 464 465 // Challenge the hash 466 dataAvailabilityChallenge.deposit{ value: dataAvailabilityChallenge.bondSize() }(); 467 dataAvailabilityChallenge.challenge(challengedBlockNumber, challengedCommitment); 468 469 vm.roll(block.number + dataAvailabilityChallenge.resolveWindow() - 1); 470 471 // Expiring the challenge before the resolve window closes fails 472 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.ChallengeNotExpired.selector)); 473 dataAvailabilityChallenge.unlockBond(challengedBlockNumber, challengedCommitment); 474 } 475 476 function testSetBondSize() public { 477 uint256 requiredBond = dataAvailabilityChallenge.bondSize(); 478 uint256 actualBond = requiredBond - 1; 479 dataAvailabilityChallenge.deposit{ value: actualBond }(); 480 481 // Expect the challenge to fail because the bond is too low 482 bytes memory challengedCommitment = computeCommitmentKeccak256("some hash"); 483 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.BondTooLow.selector, actualBond, requiredBond)); 484 dataAvailabilityChallenge.challenge(0, challengedCommitment); 485 486 // Reduce the required bond 487 vm.prank(dataAvailabilityChallenge.owner()); 488 dataAvailabilityChallenge.setBondSize(actualBond); 489 490 // Expect the challenge to succeed 491 dataAvailabilityChallenge.challenge(0, challengedCommitment); 492 } 493 494 function testSetResolverRefundPercentage(uint256 resolverRefundPercentage) public { 495 resolverRefundPercentage = bound(resolverRefundPercentage, 0, 100); 496 vm.prank(dataAvailabilityChallenge.owner()); 497 dataAvailabilityChallenge.setResolverRefundPercentage(resolverRefundPercentage); 498 assertEq(dataAvailabilityChallenge.resolverRefundPercentage(), resolverRefundPercentage); 499 } 500 501 function testSetResolverRefundPercentageFail() public { 502 address owner = dataAvailabilityChallenge.owner(); 503 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.InvalidResolverRefundPercentage.selector, 101)); 504 vm.prank(owner); 505 dataAvailabilityChallenge.setResolverRefundPercentage(101); 506 } 507 508 function testSetBondSizeFailOnlyOwner(address notOwner, uint256 newBondSize) public { 509 vm.assume(notOwner != dataAvailabilityChallenge.owner()); 510 511 // Expect setting the bond size to fail because the sender is not the owner 512 vm.prank(notOwner); 513 vm.expectRevert("Ownable: caller is not the owner"); 514 dataAvailabilityChallenge.setBondSize(newBondSize); 515 } 516 517 function testValidateCommitment() public { 518 // Should not revert given a valid commitment 519 bytes memory validCommitment = abi.encodePacked(CommitmentType.Keccak256, keccak256("test")); 520 dataAvailabilityChallenge.validateCommitment(validCommitment); 521 522 // Should revert if the commitment type is unknown 523 vm.expectRevert(abi.encodeWithSelector(DataAvailabilityChallenge.UnknownCommitmentType.selector, uint8(1))); 524 bytes memory unknownType = abi.encodePacked(uint8(1), keccak256("test")); 525 dataAvailabilityChallenge.validateCommitment(unknownType); 526 527 // Should revert if the commitment length does not match 528 vm.expectRevert( 529 abi.encodeWithSelector(DataAvailabilityChallenge.InvalidCommitmentLength.selector, uint8(0), 33, 34) 530 ); 531 bytes memory invalidLength = abi.encodePacked(CommitmentType.Keccak256, keccak256("test"), "x"); 532 dataAvailabilityChallenge.validateCommitment(invalidLength); 533 } 534 }