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  }