diff --git a/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts b/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts
index 31699ed3228f981b54df847978e9482c4dd88052..c5696e98af11b9c5f62c34beb2e8dc734db7f4cc 100644
--- a/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts
+++ b/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts
@@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
 
 /* Imports: Internal */
 import {
-  deployAndRegister,
+  deployAndPostDeploy,
   getDeployedContract,
+  getLibAddressManager,
 } from '../src/hardhat-deploy-ethers'
 
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'ChainStorageContainer-CTC-batches',
     contract: 'ChainStorageContainer',
diff --git a/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts b/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts
index 13b8a7adcbf759415fc270bea4994b3d73968615..226ccfabad97b67d8cd3523662f12a3c71ce3f17 100644
--- a/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts
+++ b/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts
@@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
 
 /* Imports: Internal */
 import {
-  deployAndRegister,
+  deployAndPostDeploy,
   getDeployedContract,
+  getLibAddressManager,
 } from '../src/hardhat-deploy-ethers'
 
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'ChainStorageContainer-SCC-batches',
     contract: 'ChainStorageContainer',
diff --git a/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts b/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts
index 9891ce358e7cd62f2572e4f80f8afc1343dfd96d..2023bb42420b095b1e1529a9970ca37e3df80f99 100644
--- a/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts
+++ b/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts
@@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
 
 /* Imports: Internal */
 import {
-  deployAndRegister,
+  deployAndPostDeploy,
   getDeployedContract,
+  getLibAddressManager,
 } from '../src/hardhat-deploy-ethers'
 
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'CanonicalTransactionChain',
     args: [
diff --git a/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts b/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts
index 8b0f0b63a14cff0611af5701147a2869c4b50439..55f8c59c06c17f02a1a3ec4246e3df391f8671a8 100644
--- a/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts
+++ b/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts
@@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
 
 /* Imports: Internal */
 import {
-  deployAndRegister,
+  deployAndPostDeploy,
   getDeployedContract,
+  getLibAddressManager,
 } from '../src/hardhat-deploy-ethers'
 
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'StateCommitmentChain',
     args: [
diff --git a/packages/contracts/deploy/005-OVM_BondManager.deploy.ts b/packages/contracts/deploy/005-OVM_BondManager.deploy.ts
index 010d2ba0177ae359632772a5e74a68661d854a46..d535cbf5b0a414b9f9d2af6c118b739623d0e572 100644
--- a/packages/contracts/deploy/005-OVM_BondManager.deploy.ts
+++ b/packages/contracts/deploy/005-OVM_BondManager.deploy.ts
@@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
 
 /* Imports: Internal */
 import {
-  deployAndRegister,
+  deployAndPostDeploy,
   getDeployedContract,
+  getLibAddressManager,
 } from '../src/hardhat-deploy-ethers'
 
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'BondManager',
     args: [Lib_AddressManager.address],
diff --git a/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts b/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts
index 80988265637e9a8651ffde87a705f718a42c8ff5..4402b159ed656481f9fcbacbe9046ac14d870d95 100644
--- a/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts
+++ b/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts
@@ -4,19 +4,16 @@ import { hexStringEquals } from '@eth-optimism/core-utils'
 
 /* Imports: Internal */
 import {
-  getDeployedContract,
-  deployAndRegister,
+  deployAndPostDeploy,
+  getLibAddressManager,
   waitUntilTrue,
 } from '../src/hardhat-deploy-ethers'
 
 // todo: this implementation needs to also have a chugsplash proxy in front of it.
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'OVM_L1CrossDomainMessenger',
     contract: 'L1CrossDomainMessenger',
diff --git a/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts b/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts
index cc4332b0de0e0dae29fc99547e57206b20f437e7..46f9ff6936f91cb79c7dd961e5954d9b323b682a 100644
--- a/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts
+++ b/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts
@@ -4,19 +4,16 @@ import { hexStringEquals } from '@eth-optimism/core-utils'
 
 /* Imports: Internal */
 import {
-  getDeployedContract,
-  deployAndRegister,
+  deployAndPostDeploy,
+  getLibAddressManager,
   waitUntilTrue,
 } from '../src/hardhat-deploy-ethers'
 
 // We need to skip this step, because we're keeping the existing proxy.
 const deployFn: DeployFunction = async (hre) => {
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'Proxy__OVM_L1CrossDomainMessenger',
     contract: 'Lib_ResolvedDelegateProxy',
diff --git a/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts b/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts
index 0fd6a5961831fb74009aa02c313ab19bd0a235ec..58451eb1085897c49e5975071be816878a32b6f1 100644
--- a/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts
+++ b/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts
@@ -2,12 +2,12 @@
 import { DeployFunction } from 'hardhat-deploy/dist/types'
 
 /* Imports: Internal */
-import { deployAndRegister } from '../src/hardhat-deploy-ethers'
+import { deployAndPostDeploy } from '../src/hardhat-deploy-ethers'
 
 const deployFn: DeployFunction = async (hre) => {
   const { deployer } = await hre.getNamedAccounts()
 
-  await deployAndRegister({
+  await deployAndPostDeploy({
     hre,
     name: 'Proxy__OVM_L1StandardBridge',
     contract: 'L1ChugSplashProxy',
diff --git a/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts b/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts
index b2d5d68766db34f81e0b8693614df9baac1593c4..4fbe6fd118c8fdcb3b5077396debea0a141271f3 100644
--- a/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts
+++ b/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts
@@ -11,6 +11,7 @@ import {
 } from '../src/contract-defs'
 import {
   getDeployedContract,
+  getLibAddressManager,
   waitUntilTrue,
   getAdvancedContract,
   deployAndRegister,
@@ -18,10 +19,7 @@ import {
 
 const deployFn: DeployFunction = async (hre) => {
   const { deployer } = await hre.getNamedAccounts()
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager'
-  )
+  const Lib_AddressManager = await getLibAddressManager(hre)
 
   // Set up a reference to the proxy as if it were the L1StandardBridge contract.
   const contract = await getDeployedContract(
diff --git a/packages/contracts/deploy/010-AddressSetter.deploy.ts b/packages/contracts/deploy/010-AddressSetter.deploy.ts
new file mode 100644
index 0000000000000000000000000000000000000000..56c8abc3f02dd70985c8757e95d008f49273c3cd
--- /dev/null
+++ b/packages/contracts/deploy/010-AddressSetter.deploy.ts
@@ -0,0 +1,46 @@
+/* Imports: External */
+import { DeployFunction, DeploymentsExtension } from 'hardhat-deploy/dist/types'
+
+/* Imports: Internal */
+import {
+  deployAndPostDeploy,
+  getDeployedContract,
+  getLibAddressManager,
+} from '../src/hardhat-deploy-ethers'
+
+const deployFn: DeployFunction = async (hre) => {
+  const Lib_AddressManager = await getLibAddressManager(hre)
+
+  const names = [
+    'ChainStorageContainer-CTC-batches',
+    'ChainStorageContainer-SCC-batches',
+    'CanonicalTransactionChain',
+    'StateCommitmentChain',
+    'BondManager',
+    'OVM_L1CrossDomainMessenger',
+    'Proxy__L1CrossDomainMessenger',
+    'Proxy__L1StandardBridge',
+    'OVM_Proposer',
+  ]
+
+  const addresses = await Promise.all(
+    names.map(async (n) => {
+      return (await getDeployedContract(hre, n)).address
+    })
+  )
+
+  await deployAndPostDeploy({
+    hre,
+    name: 'AddressSetter',
+    args: [
+      Lib_AddressManager.address,
+      (hre as any).deployConfig.ovmAddressManagerOwner,
+      names,
+      addresses,
+    ],
+  })
+}
+
+deployFn.tags = ['AddressSetter', 'upgrade']
+
+export default deployFn
diff --git a/packages/contracts/deploy/010-set-addresses.ts b/packages/contracts/deploy/011-set-addresses.ts
similarity index 100%
rename from packages/contracts/deploy/010-set-addresses.ts
rename to packages/contracts/deploy/011-set-addresses.ts
diff --git a/packages/contracts/deploy/014-fund-accounts.ts b/packages/contracts/deploy/014-fund-accounts.ts
new file mode 100644
index 0000000000000000000000000000000000000000..81093b9394b956c09eee1c5774c1f8c0927b88e3
--- /dev/null
+++ b/packages/contracts/deploy/014-fund-accounts.ts
@@ -0,0 +1,63 @@
+/* Imports: External */
+import { sleep } from '@eth-optimism/core-utils'
+import { DeployFunction } from 'hardhat-deploy/dist/types'
+import {
+  defaultHardhatNetworkHdAccountsConfigParams,
+  defaultHardhatNetworkParams,
+} from 'hardhat/internal/core/config/default-config'
+import { normalizeHardhatNetworkAccountsConfig } from 'hardhat/internal/core/providers/util'
+
+/* Imports: Internal */
+import { getDeployedContract } from '../src/hardhat-deploy-ethers'
+
+// This is a TEMPORARY way to fund the default hardhat accounts on L2. The better way to do this is
+// to make a modification to hardhat-ovm. However, I don't have the time right now to figure the
+// details of how to make that work cleanly. This is fine in the meantime.
+const deployFn: DeployFunction = async (hre) => {
+  // Only execute this step if we're on the hardhat chain ID.
+  const { chainId } = await hre.ethers.provider.getNetwork()
+  if (chainId === defaultHardhatNetworkParams.chainId) {
+    const L1StandardBridge = await getDeployedContract(
+      hre,
+      'Proxy__L1StandardBridge',
+      {
+        iface: 'L1StandardBridge',
+      }
+    )
+
+    // Default has 20 accounts but we restrict to 20 accounts manually as well just to prevent
+    // future problems if the number of default accounts increases for whatever reason.
+    const accounts = normalizeHardhatNetworkAccountsConfig(
+      defaultHardhatNetworkHdAccountsConfigParams
+    ).slice(0, 20)
+
+    // Fund the accounts in parallel to speed things up.
+    await Promise.all(
+      accounts.map(async (account, index) => {
+        // Add a sleep here to avoid any potential issues with spamming hardhat. Not sure if this
+        // is strictly necessary but it can't hurt.
+        await sleep(200 * index)
+
+        const wallet = new hre.ethers.Wallet(
+          account.privateKey,
+          hre.ethers.provider
+        )
+        const balance = await wallet.getBalance()
+        const depositAmount = balance.div(2) // Deposit half of the wallet's balance into L2.
+        await L1StandardBridge.connect(wallet).depositETH(8_000_000, '0x', {
+          value: depositAmount,
+          gasLimit: 2_000_000, // Idk, gas estimation was broken and this fixes it.
+        })
+        console.log(
+          `✓ Funded ${wallet.address} on L2 with ${hre.ethers.utils.formatEther(
+            depositAmount
+          )} ETH`
+        )
+      })
+    )
+  }
+}
+
+deployFn.tags = ['fund-accounts']
+
+export default deployFn
diff --git a/packages/contracts/src/hardhat-deploy-ethers.ts b/packages/contracts/src/hardhat-deploy-ethers.ts
index 54241a542d395c608c67f2a225cdcaf91d98e778..92c608acac8a39c4bdf8432b35d19f8265e2bf9c 100644
--- a/packages/contracts/src/hardhat-deploy-ethers.ts
+++ b/packages/contracts/src/hardhat-deploy-ethers.ts
@@ -25,41 +25,7 @@ export const waitUntilTrue = async (
   }
 }
 
-export const registerAddress = async ({
-  hre,
-  name,
-  address,
-}): Promise<void> => {
-  // TODO: Cache these 2 across calls?
-  const { deployer } = await hre.getNamedAccounts()
-  const Lib_AddressManager = await getDeployedContract(
-    hre,
-    'Lib_AddressManager',
-    {
-      signerOrProvider: deployer,
-    }
-  )
-
-  const currentAddress = await Lib_AddressManager.getAddress(name)
-  if (address === currentAddress) {
-    console.log(
-      `✓ Not registering address for ${name} because it's already been correctly registered`
-    )
-    return
-  }
-
-  console.log(`Registering address for ${name} to ${address}...`)
-  await Lib_AddressManager.setAddress(name, address)
-
-  console.log(`Waiting for registration to reflect on-chain...`)
-  await waitUntilTrue(async () => {
-    return hexStringEquals(await Lib_AddressManager.getAddress(name), address)
-  })
-
-  console.log(`✓ Registered address for ${name}`)
-}
-
-export const deployAndRegister = async ({
+export const deployAndPostDeploy = async ({
   hre,
   name,
   args,
@@ -102,12 +68,6 @@ export const deployAndRegister = async ({
         })
       )
     }
-
-    await registerAddress({
-      hre,
-      name,
-      address: result.address,
-    })
   }
 }
 
@@ -288,3 +248,15 @@ export const getContractFromArtifact = async (
 
 // Large balance to fund accounts with.
 export const BIG_BALANCE = ethers.BigNumber.from(`0xFFFFFFFFFFFFFFFFFFFF`)
+export const getLibAddressManager = async (hre: any): Promise<Contract> => {
+  const factory = await hre.ethers.getContractFactory('Lib_AddressManager')
+  const iface = factory.interface
+  // try to get the address from the config options
+  const addr = (hre as any).deployConfig.libAddressManager
+  if (hre.ethers.utils.isAddress(addr)) {
+    return new Contract(addr, iface)
+  } else {
+    // if an address was not provided, a new manager must have been deployed
+    return getDeployedContract(hre, 'Lib_AddressManager')
+  }
+}
diff --git a/packages/contracts/tasks/deploy.ts b/packages/contracts/tasks/deploy.ts
index 476d560db09cf6e2dcac2e6c8528734083ed527d..f8056d32c7ef82a586952e3d9907d1c1a1e0ec21 100644
--- a/packages/contracts/tasks/deploy.ts
+++ b/packages/contracts/tasks/deploy.ts
@@ -60,6 +60,12 @@ task('deploy')
     undefined,
     types.string
   )
+  .addOptionalParam(
+    'libAddressManager',
+    'Address of the Lib_AddressManager, for use in a deployment which is keeping the existing contract.',
+    undefined,
+    types.string
+  )
   .addOptionalParam(
     'ovmAddressManagerOwner',
     'Address that will own the Lib_AddressManager. Must be provided or this deployment will fail.',
@@ -97,6 +103,24 @@ task('deploy')
     validateAddressArg('ovmProposerAddress')
     validateAddressArg('ovmAddressManagerOwner')
 
+    const hasAddressManagerTag = args.tags
+      .split(',')
+      .includes('Lib_AddressManager')
+    try {
+      validateAddressArg('libAddressManager')
+      if (hasAddressManagerTag) {
+        throw new Error(
+          'cannot deploy a new Lib_AddressManager if the address of an existing one is provided'
+        )
+      }
+    } catch (error) {
+      if (!hasAddressManagerTag) {
+        throw new Error(
+          'must either deploy a new Lib_AddressManager, or provide the address for an existing one'
+        )
+      }
+    }
+
     hre.deployConfig = args
     return runSuper(args)
   })