github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/test/dispute/DelayedWETH.t.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity ^0.8.15;
     3  
     4  import "src/libraries/DisputeTypes.sol";
     5  import "src/libraries/DisputeErrors.sol";
     6  
     7  import { Test } from "forge-std/Test.sol";
     8  import { DisputeGameFactory, IDisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
     9  import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
    10  import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol";
    11  import { Proxy } from "src/universal/Proxy.sol";
    12  import { CommonTest } from "test/setup/CommonTest.sol";
    13  
    14  contract DelayedWETH_Init is CommonTest {
    15      event Approval(address indexed src, address indexed guy, uint256 wad);
    16      event Transfer(address indexed src, address indexed dst, uint256 wad);
    17      event Deposit(address indexed dst, uint256 wad);
    18      event Withdrawal(address indexed src, uint256 wad);
    19      event Unwrap(address indexed src, uint256 wad);
    20  
    21      function setUp() public virtual override {
    22          super.enableFaultProofs();
    23          super.setUp();
    24  
    25          // Transfer ownership of delayed WETH to the test contract.
    26          vm.prank(deploy.mustGetAddress("SystemOwnerSafe"));
    27          delayedWeth.transferOwnership(address(this));
    28      }
    29  }
    30  
    31  contract DelayedWETH_Initialize_Test is DelayedWETH_Init {
    32      /// @dev Tests that initialization is successful.
    33      function test_initialize_succeeds() public {
    34          assertEq(delayedWeth.owner(), address(this));
    35          assertEq(address(delayedWeth.config()), address(superchainConfig));
    36      }
    37  }
    38  
    39  contract DelayedWETH_Unlock_Test is DelayedWETH_Init {
    40      /// @dev Tests that unlocking once is successful.
    41      function test_unlock_once_succeeds() public {
    42          delayedWeth.unlock(alice, 1 ether);
    43          (uint256 amount, uint256 timestamp) = delayedWeth.withdrawals(address(this), alice);
    44          assertEq(amount, 1 ether);
    45          assertEq(timestamp, block.timestamp);
    46      }
    47  
    48      /// @dev TEsts that unlocking twice is successful and timestamp/amount is updated.
    49      function test_unlock_twice_succeeds() public {
    50          // Unlock once.
    51          uint256 ts = block.timestamp;
    52          delayedWeth.unlock(alice, 1 ether);
    53          (uint256 amount1, uint256 timestamp1) = delayedWeth.withdrawals(address(this), alice);
    54          assertEq(amount1, 1 ether);
    55          assertEq(timestamp1, ts);
    56  
    57          // Go forward in time.
    58          vm.warp(ts + 1);
    59  
    60          // Unlock again works.
    61          delayedWeth.unlock(alice, 1 ether);
    62          (uint256 amount2, uint256 timestamp2) = delayedWeth.withdrawals(address(this), alice);
    63          assertEq(amount2, 2 ether);
    64          assertEq(timestamp2, ts + 1);
    65      }
    66  }
    67  
    68  contract DelayedWETH_Withdraw_Test is DelayedWETH_Init {
    69      /// @dev Tests that withdrawing while unlocked and delay has passed is successful.
    70      function test_withdraw_whileUnlocked_succeeds() public {
    71          // Deposit some WETH.
    72          vm.prank(alice);
    73          delayedWeth.deposit{ value: 1 ether }();
    74          uint256 balance = address(alice).balance;
    75  
    76          // Unlock the withdrawal.
    77          vm.prank(alice);
    78          delayedWeth.unlock(alice, 1 ether);
    79  
    80          // Wait for the delay.
    81          vm.warp(block.timestamp + delayedWeth.delay() + 1);
    82  
    83          // Withdraw the WETH.
    84          vm.expectEmit(true, true, false, false);
    85          emit Withdrawal(address(alice), 1 ether);
    86          vm.prank(alice);
    87          delayedWeth.withdraw(alice, 1 ether);
    88          assertEq(address(alice).balance, balance + 1 ether);
    89      }
    90  
    91      /// @dev Tests that withdrawing when unlock was not called fails.
    92      function test_withdraw_whileLocked_fails() public {
    93          // Deposit some WETH.
    94          vm.prank(alice);
    95          delayedWeth.deposit{ value: 1 ether }();
    96          uint256 balance = address(alice).balance;
    97  
    98          // Withdraw fails when unlock not called.
    99          vm.expectRevert("DelayedWETH: withdrawal not unlocked");
   100          vm.prank(alice);
   101          delayedWeth.withdraw(alice, 0 ether);
   102          assertEq(address(alice).balance, balance);
   103      }
   104  
   105      /// @dev Tests that withdrawing while locked and delay has not passed fails.
   106      function test_withdraw_whileLockedNotLongEnough_fails() public {
   107          // Deposit some WETH.
   108          vm.prank(alice);
   109          delayedWeth.deposit{ value: 1 ether }();
   110          uint256 balance = address(alice).balance;
   111  
   112          // Call unlock.
   113          vm.prank(alice);
   114          delayedWeth.unlock(alice, 1 ether);
   115  
   116          // Wait for the delay, but not long enough.
   117          vm.warp(block.timestamp + delayedWeth.delay() - 1);
   118  
   119          // Withdraw fails when delay not met.
   120          vm.expectRevert("DelayedWETH: withdrawal delay not met");
   121          vm.prank(alice);
   122          delayedWeth.withdraw(alice, 1 ether);
   123          assertEq(address(alice).balance, balance);
   124      }
   125  
   126      /// @dev Tests that withdrawing more than unlocked amount fails.
   127      function test_withdraw_tooMuch_fails() public {
   128          // Deposit some WETH.
   129          vm.prank(alice);
   130          delayedWeth.deposit{ value: 1 ether }();
   131          uint256 balance = address(alice).balance;
   132  
   133          // Unlock the withdrawal.
   134          vm.prank(alice);
   135          delayedWeth.unlock(alice, 1 ether);
   136  
   137          // Wait for the delay.
   138          vm.warp(block.timestamp + delayedWeth.delay() + 1);
   139  
   140          // Withdraw too much fails.
   141          vm.expectRevert("DelayedWETH: insufficient unlocked withdrawal");
   142          vm.prank(alice);
   143          delayedWeth.withdraw(alice, 2 ether);
   144          assertEq(address(alice).balance, balance);
   145      }
   146  
   147      /// @dev Tests that withdrawing while paused fails.
   148      function test_withdraw_whenPaused_fails() public {
   149          // Deposit some WETH.
   150          vm.prank(alice);
   151          delayedWeth.deposit{ value: 1 ether }();
   152  
   153          // Unlock the withdrawal.
   154          vm.prank(alice);
   155          delayedWeth.unlock(alice, 1 ether);
   156  
   157          // Wait for the delay.
   158          vm.warp(block.timestamp + delayedWeth.delay() + 1);
   159  
   160          // Pause the contract.
   161          address guardian = optimismPortal.GUARDIAN();
   162          vm.prank(guardian);
   163          superchainConfig.pause("identifier");
   164  
   165          // Withdraw fails.
   166          vm.expectRevert("DelayedWETH: contract is paused");
   167          vm.prank(alice);
   168          delayedWeth.withdraw(alice, 1 ether);
   169      }
   170  }
   171  
   172  contract DelayedWETH_Recover_Test is DelayedWETH_Init {
   173      /// @dev Tests that recovering WETH succeeds.
   174      function test_recover_succeeds() public {
   175          // Transfer ownership to alice.
   176          delayedWeth.transferOwnership(alice);
   177  
   178          // Give the contract some WETH to recover.
   179          vm.deal(address(delayedWeth), 1 ether);
   180  
   181          // Record the initial balance.
   182          uint256 initialBalance = address(alice).balance;
   183  
   184          // Recover the WETH.
   185          vm.prank(alice);
   186          delayedWeth.recover(1 ether);
   187  
   188          // Verify the WETH was recovered.
   189          assertEq(address(delayedWeth).balance, 0);
   190          assertEq(address(alice).balance, initialBalance + 1 ether);
   191      }
   192  
   193      /// @dev Tests that recovering WETH by non-owner fails.
   194      function test_recover_byNonOwner_fails() public {
   195          // Pretend to be a non-owner.
   196          vm.prank(alice);
   197  
   198          // Recover fails.
   199          vm.expectRevert("DelayedWETH: not owner");
   200          delayedWeth.recover(1 ether);
   201      }
   202  
   203      /// @dev Tests that recovering more than the balance recovers what it can.
   204      function test_recover_moreThanBalance_succeeds() public {
   205          // Transfer ownership to alice.
   206          delayedWeth.transferOwnership(alice);
   207  
   208          // Give the contract some WETH to recover.
   209          vm.deal(address(delayedWeth), 0.5 ether);
   210  
   211          // Record the initial balance.
   212          uint256 initialBalance = address(alice).balance;
   213  
   214          // Recover the WETH.
   215          vm.prank(alice);
   216          delayedWeth.recover(1 ether);
   217  
   218          // Verify the WETH was recovered.
   219          assertEq(address(delayedWeth).balance, 0);
   220          assertEq(address(alice).balance, initialBalance + 0.5 ether);
   221      }
   222  }
   223  
   224  contract DelayedWETH_Hold_Test is DelayedWETH_Init {
   225      /// @dev Tests that holding WETH succeeds.
   226      function test_hold_succeeds() public {
   227          uint256 amount = 1 ether;
   228  
   229          // Pretend to be alice and deposit some WETH.
   230          vm.prank(alice);
   231          delayedWeth.deposit{ value: amount }();
   232  
   233          // Hold some WETH.
   234          vm.expectEmit(true, true, true, false);
   235          emit Approval(alice, address(this), amount);
   236          delayedWeth.hold(alice, amount);
   237  
   238          // Verify the allowance.
   239          assertEq(delayedWeth.allowance(alice, address(this)), amount);
   240  
   241          // We can transfer.
   242          delayedWeth.transferFrom(alice, address(this), amount);
   243  
   244          // Verify the transfer.
   245          assertEq(delayedWeth.balanceOf(address(this)), amount);
   246      }
   247  
   248      /// @dev Tests that holding WETH by non-owner fails.
   249      function test_hold_byNonOwner_fails() public {
   250          // Pretend to be a non-owner.
   251          vm.prank(alice);
   252  
   253          // Hold fails.
   254          vm.expectRevert("DelayedWETH: not owner");
   255          delayedWeth.hold(bob, 1 ether);
   256      }
   257  }