Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/contracts-bedrock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,8 @@ Test contracts should be named one of the following according to their use:
- `TargetContract_Init` for contracts that perform basic setup to be reused in other test contracts.
- `TargetContract_Function_Test` for contracts containing happy path tests for a given function.
- `TargetContract_Function_TestFail` for contracts containing sad path tests for a given function.

## Withdrawaing From Fee Vaults

See the file `scripts/FeeVaultWithdrawal.s.sol` to withdraw from the L2 fee vaults. It includes
instructions on how to run it. `foundry` is required.
87 changes: 87 additions & 0 deletions packages/contracts-bedrock/scripts/FeeVaultWithdrawal.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

import { console } from "forge-std/console.sol";
import { Script } from "forge-std/Script.sol";
import { Predeploys } from "../contracts/libraries/Predeploys.sol";
import { FeeVault } from "../contracts/universal/FeeVault.sol";
import { IMulticall3 } from "forge-std/interfaces/IMulticall3.sol";

/**
* @title FeeVaultWithdrawal
* @notice A script to make it very simple to withdraw from the fee vaults.
* The usage is as follows:
* $ forge script scripts/FeeVaultWithdrawal.s.sol \
* --rpc-url $ETH_RPC_URL --broadcast \
* --private-key $PRIVATE_KEY
*/
contract FeeVaultWithdrawal is Script {
IMulticall3 private constant multicall = IMulticall3(MULTICALL3_ADDRESS);
IMulticall3.Call3[] internal calls;

/**
* @notice The entrypoint function. Determines which FeeVaults can be withdrawn from and then
* will send the transaction via Multicall3 to withdraw all FeeVaults.
*/
function run() external {
require(address(multicall).code.length > 0);

address[] memory vaults = new address[](3);
vaults[0] = Predeploys.SEQUENCER_FEE_WALLET;
vaults[1] = Predeploys.BASE_FEE_VAULT;
vaults[2] = Predeploys.L1_FEE_VAULT;

for (uint256 i; i < vaults.length; i++) {
address vault = vaults[i];
bool shouldCall = canWithdrawal(vault);
if (shouldCall) {
calls.push(IMulticall3.Call3({
target: vault,
allowFailure: false,
callData: abi.encodeWithSelector(FeeVault.withdraw.selector)
}));

address recipient = FeeVault(payable(vault)).RECIPIENT();
uint256 balance = vault.balance;
log(balance, recipient, vault);
} else {
string memory logline = string.concat(
vm.toString(vault),
" does not have a large enough balance to withdraw."
);
console.log(logline);
}
}

if (calls.length > 0) {
vm.broadcast();
multicall.aggregate3(calls);
console.log("Success.");
}
}

/**
* @notice Checks whether or not a FeeVault can be withdrawn. The balance of the account must
* be larger than the `MIN_WITHDRAWAL_AMOUNT`.
*/
function canWithdrawal(address _vault) internal view returns (bool) {
uint256 minWithdrawalAmount = FeeVault(payable(_vault)).MIN_WITHDRAWAL_AMOUNT();
uint256 balance = _vault.balance;
return balance >= minWithdrawalAmount;
}

/**
* @notice Logs the information relevant to the user.
*/
function log(uint256 _balance, address _recipient, address _vault) internal view {
string memory logline = string.concat(
"Withdrawing ",
vm.toString(_balance),
" to ",
vm.toString(_recipient),
" from ",
vm.toString(_vault)
);
console.log(logline);
}
}