diff --git a/test/gas-report/poolsize.js b/test/gas-report/poolsize.js
index 315340f1..13132cc8 100644
--- a/test/gas-report/poolsize.js
+++ b/test/gas-report/poolsize.js
@@ -1,5 +1,5 @@
 import RPC from "../../utils/rpc"
-import {web3, ethers} from "hardhat"
+import {ethers} from "hardhat"
 import setupIntegrationTest from "../helpers/setupIntegrationTest"
 
 import chai from "chai"
@@ -40,7 +40,7 @@ describe("transcoder pool size gas report", () => {
     }
 
     before(async () => {
-        rpc = new RPC(web3)
+        rpc = new RPC(ethers.provider)
 
         const fixture = await setupIntegrationTest()
         controller = await ethers.getContractAt(
diff --git a/test/gas-report/redeemTicket.js b/test/gas-report/redeemTicket.js
index ece7a59e..a12c0e3b 100644
--- a/test/gas-report/redeemTicket.js
+++ b/test/gas-report/redeemTicket.js
@@ -34,7 +34,7 @@ describe("redeem ticket gas report", () => {
     let signers
 
     before(async () => {
-        rpc = new RPC(web3)
+        rpc = new RPC(ethers.provider)
         signers = await ethers.getSigners()
         transcoder = signers[0]
         broadcaster = signers[1]
diff --git a/test/integration/PoolUpdatesWithHints.js b/test/integration/PoolUpdatesWithHints.js
index 71df97d1..908896d6 100644
--- a/test/integration/PoolUpdatesWithHints.js
+++ b/test/integration/PoolUpdatesWithHints.js
@@ -80,7 +80,7 @@ describe("PoolUpdatesWithHints", () => {
         transcoders = signers.slice(0, 10)
         delegator = signers[11]
         newTranscoder = signers[12]
-        rpc = new RPC(web3)
+        rpc = new RPC(ethers.provider)
 
         const fixture = await setupIntegrationTest()
         controller = await ethers.getContractAt(
diff --git a/test/unit/BondingManager.js b/test/unit/BondingManager.js
index b98e44d5..bcb812cc 100644
--- a/test/unit/BondingManager.js
+++ b/test/unit/BondingManager.js
@@ -7,7 +7,7 @@ import {
 import {constants} from "../../utils/constants"
 import math from "../helpers/math"
 import {assert} from "chai"
-import {ethers, web3} from "hardhat"
+import {ethers} from "hardhat"
 const BigNumber = ethers.BigNumber
 import chai from "chai"
 import {solidity} from "ethereum-waffle"
@@ -49,7 +49,7 @@ describe("BondingManager", () => {
     let signers
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
 
         const llFac = await ethers.getContractFactory("SortedDoublyLL")
diff --git a/test/unit/Controller.js b/test/unit/Controller.js
index 7669ce70..e77a534e 100644
--- a/test/unit/Controller.js
+++ b/test/unit/Controller.js
@@ -1,6 +1,6 @@
 import Fixture from "./helpers/Fixture"
 import {contractId} from "../../utils/helpers"
-import {web3, ethers} from "hardhat"
+import {ethers} from "hardhat"
 
 import chai, {expect, assert} from "chai"
 import {solidity} from "ethereum-waffle"
@@ -14,7 +14,7 @@ describe("Controller", () => {
 
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
         controller = fixture.controller
         commitHash = fixture.commitHash
diff --git a/test/unit/Governor.js b/test/unit/Governor.js
index e04ff8f1..e0f97569 100644
--- a/test/unit/Governor.js
+++ b/test/unit/Governor.js
@@ -16,7 +16,7 @@ describe("Governor", () => {
 
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
         const govFac = await ethers.getContractFactory("Governor")
         governor = await govFac.deploy()
diff --git a/test/unit/LivepeerTokenFaucet.js b/test/unit/LivepeerTokenFaucet.js
index ce84c822..65c9b11c 100644
--- a/test/unit/LivepeerTokenFaucet.js
+++ b/test/unit/LivepeerTokenFaucet.js
@@ -15,7 +15,7 @@ describe("LivepeerTokenFaucet", () => {
     let signers
 
     before(async () => {
-        rpc = new RPC(web3)
+        rpc = new RPC(ethers.provider)
         signers = await ethers.getSigners()
         const tokenFac = await ethers.getContractFactory("LivepeerToken")
         const faucetFac = await ethers.getContractFactory("LivepeerTokenFaucet")
diff --git a/test/unit/ManagerProxy.js b/test/unit/ManagerProxy.js
index 71f2137b..2851ff5f 100644
--- a/test/unit/ManagerProxy.js
+++ b/test/unit/ManagerProxy.js
@@ -38,7 +38,7 @@ describe("ManagerProxy", () => {
 
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
         await fixture.deployAndRegister(
             await ethers.getContractFactory("ManagerProxyTargetMockV1"),
diff --git a/test/unit/MerkleSnapshot.js b/test/unit/MerkleSnapshot.js
index 3d03ce1d..9e5cf2aa 100644
--- a/test/unit/MerkleSnapshot.js
+++ b/test/unit/MerkleSnapshot.js
@@ -1,7 +1,7 @@
 import {keccak256, bufferToHex} from "ethereumjs-util"
 import MerkleTree from "../../utils/merkleTree"
 import Fixture from "./helpers/Fixture"
-import {web3, ethers} from "hardhat"
+import {ethers} from "hardhat"
 import chai, {expect, assert} from "chai"
 import {solidity} from "ethereum-waffle"
 chai.use(solidity)
@@ -13,7 +13,7 @@ describe("MerkleSnapshot", () => {
 
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
         const merkleFac = await ethers.getContractFactory("MerkleSnapshot")
         merkleSnapshot = await merkleFac.deploy(fixture.controller.address)
diff --git a/test/unit/Minter.js b/test/unit/Minter.js
index b329f21c..de6f97d6 100644
--- a/test/unit/Minter.js
+++ b/test/unit/Minter.js
@@ -98,7 +98,7 @@ describe("Minter", () => {
     })
 
     before(async () => {
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
 
         minter = await fixture.deployAndRegister(
diff --git a/test/unit/Poll.js b/test/unit/Poll.js
index 2cb97158..a91a6a8b 100644
--- a/test/unit/Poll.js
+++ b/test/unit/Poll.js
@@ -15,7 +15,7 @@ describe("Poll", () => {
 
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
     })
 
     beforeEach(async () => {
diff --git a/test/unit/PollCreator.js b/test/unit/PollCreator.js
index 4b3c0a16..5a846220 100644
--- a/test/unit/PollCreator.js
+++ b/test/unit/PollCreator.js
@@ -1,5 +1,5 @@
 import Fixture from "./helpers/Fixture"
-import {web3, ethers} from "hardhat"
+import {ethers} from "hardhat"
 
 import {expect, use} from "chai"
 import {solidity} from "ethereum-waffle"
@@ -22,7 +22,7 @@ describe("PollCreator", () => {
     before(async () => {
         ;[, mockBondingManagerEOA] = await ethers.getSigners()
 
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
 
         bondingManagerMock = await smock.fake(
             "contracts/polling/PollCreator.sol:IBondingManager",
diff --git a/test/unit/RoundsManager.js b/test/unit/RoundsManager.js
index 65597380..61bab0b4 100644
--- a/test/unit/RoundsManager.js
+++ b/test/unit/RoundsManager.js
@@ -21,7 +21,7 @@ describe("RoundsManager", () => {
 
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
 
         roundsManager = await fixture.deployAndRegister(
diff --git a/test/unit/ServiceRegistry.js b/test/unit/ServiceRegistry.js
index 30924d4e..2c0fec42 100644
--- a/test/unit/ServiceRegistry.js
+++ b/test/unit/ServiceRegistry.js
@@ -1,5 +1,5 @@
 import Fixture from "./helpers/Fixture"
-import {web3, ethers} from "hardhat"
+import {ethers} from "hardhat"
 
 import chai, {expect, assert} from "chai"
 import {solidity} from "ethereum-waffle"
@@ -12,7 +12,7 @@ describe("ServiceRegistry", () => {
     let controller
     before(async () => {
         signers = await ethers.getSigners()
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         // Use dummy Controller in these unit tests
         // We are testing the logic of ServiceRegistry directly so we do not
         // interact with the contract via a proxy
diff --git a/test/unit/TicketBroker.js b/test/unit/TicketBroker.js
index ea1f1130..29f66173 100644
--- a/test/unit/TicketBroker.js
+++ b/test/unit/TicketBroker.js
@@ -43,7 +43,7 @@ describe("TicketBroker", () => {
         sender = signers[0].address
         recipient = signers[1].address
         funder = signers[3]
-        fixture = new Fixture(web3)
+        fixture = new Fixture(ethers.provider)
         await fixture.deploy()
 
         broker = await (
diff --git a/test/unit/helpers/Fixture.js b/test/unit/helpers/Fixture.js
index e806dfdf..f8e12983 100644
--- a/test/unit/helpers/Fixture.js
+++ b/test/unit/helpers/Fixture.js
@@ -3,8 +3,8 @@ import {contractId} from "../../../utils/helpers"
 import {ethers} from "hardhat"
 
 export default class Fixture {
-    constructor(web3) {
-        this.rpc = new RPC(web3)
+    constructor(provider) {
+        this.rpc = new RPC(provider)
         this.commitHash = "0x3031323334353637383930313233343536373839"
     }
 
diff --git a/utils/rpc.js b/utils/rpc.js
deleted file mode 100644
index 970ac47e..00000000
--- a/utils/rpc.js
+++ /dev/null
@@ -1,94 +0,0 @@
-export default class RPC {
-    constructor(web3) {
-        this.web3 = web3
-    }
-
-    sendAsync(method, arg) {
-        const req = {
-            jsonrpc: "2.0",
-            method: method,
-            id: new Date().getTime()
-        }
-
-        if (arg) req.params = arg
-
-        return new Promise((resolve, reject) => {
-            return this.web3.currentProvider.send(req, (err, result) => {
-                if (err) {
-                    reject(err)
-                } else if (result && result.error) {
-                    reject(new Error("RPC Error: " + (result.error.message || result.error)))
-                } else {
-                    resolve(result)
-                }
-            })
-        })
-    }
-
-    // Change block time using TestRPC call evm_setTimestamp
-    // https://github.com/numerai/contract/blob/master/test/numeraire.js
-    increaseTime(time) {
-        return this.sendAsync("evm_increaseTime", [time])
-    }
-
-    mine() {
-        return this.sendAsync("evm_mine")
-    }
-
-    snapshot() {
-        return this.sendAsync("evm_snapshot")
-            .then(res => res.result)
-    }
-
-    revert(snapshotId) {
-        return this.sendAsync("evm_revert", [snapshotId])
-    }
-
-    async wait(blocks = 1, seconds = 20) {
-        const currentBlock = await this.getBlockNumberAsync()
-        const targetBlock = currentBlock + blocks
-        await this.waitUntilBlock(targetBlock, seconds)
-    }
-
-    async waitUntilBlock(targetBlock, seconds = 20) {
-        let currentBlock = await this.getBlockNumberAsync()
-
-        while (currentBlock < targetBlock) {
-            await this.increaseTime(seconds)
-            await this.mine()
-            currentBlock++
-        }
-    }
-
-    async waitUntilNextBlockMultiple(blockMultiple, multiples = 1, seconds = 20) {
-        const currentBlock = await this.getBlockNumberAsync()
-        const additionalBlocks = (multiples - 1) * blockMultiple
-        await this.waitUntilBlock(this.nextBlockMultiple(currentBlock, blockMultiple) + additionalBlocks)
-    }
-
-    getBlockNumberAsync() {
-        return new Promise((resolve, reject) => {
-            return this.web3.eth.getBlockNumber((err, blockNum) => {
-                if (err) {
-                    reject(err)
-                } else {
-                    resolve(blockNum)
-                }
-            })
-        })
-    }
-
-    nextBlockMultiple(currentBlockNum, blockMultiple) {
-        if (blockMultiple === 0) {
-            return currentBlockNum
-        }
-
-        const remainder = currentBlockNum % blockMultiple
-
-        if (remainder === 0) {
-            return currentBlockNum
-        }
-
-        return currentBlockNum + blockMultiple - remainder
-    }
-}
diff --git a/utils/rpc.ts b/utils/rpc.ts
new file mode 100644
index 00000000..a4f5491e
--- /dev/null
+++ b/utils/rpc.ts
@@ -0,0 +1,79 @@
+import {ethers} from "ethers"
+
+export default class RPC {
+    constructor(public provider: ethers.providers.JsonRpcProvider) {}
+
+    sendAsync(method: string, arg: any[]) {
+        try {
+            return this.provider.send(method, arg)
+        } catch (error: any) {
+            throw error
+        }
+    }
+
+    // Change block time using TestRPC call evm_setTimestamp
+    // https://github.com/numerai/contract/blob/master/test/numeraire.js
+    increaseTime(time: number) {
+        return this.sendAsync("evm_increaseTime", [time])
+    }
+
+    mine() {
+        return this.sendAsync("evm_mine", [])
+    }
+
+    async snapshot() {
+        const id = await this.sendAsync("evm_snapshot", [])
+        return id
+    }
+
+    revert(snapshotId: number) {
+        return this.sendAsync("evm_revert", [snapshotId])
+    }
+
+    async wait(blocks = 1, seconds = 20) {
+        const currentBlock = await this.provider.getBlockNumber()
+        const targetBlock = currentBlock + blocks
+        await this.waitUntilBlock(targetBlock, seconds)
+    }
+
+    async getBlockNumberAsync() {
+        return this.provider.getBlockNumber()
+    }
+
+    async waitUntilBlock(targetBlock: number, seconds = 20) {
+        let currentBlock = await this.provider.getBlockNumber()
+
+        while (currentBlock < targetBlock) {
+            await this.increaseTime(seconds)
+            await this.mine()
+            currentBlock++
+        }
+    }
+
+    async waitUntilNextBlockMultiple(
+        blockMultiple: number,
+        multiples = 1,
+        seconds = 20
+    ) {
+        const currentBlock = await this.provider.getBlockNumber()
+        const additionalBlocks = (multiples - 1) * blockMultiple
+        await this.waitUntilBlock(
+            this.nextBlockMultiple(currentBlock, blockMultiple) +
+                additionalBlocks
+        )
+    }
+
+    nextBlockMultiple(currentBlockNum: number, blockMultiple: number) {
+        if (blockMultiple === 0) {
+            return currentBlockNum
+        }
+
+        const remainder = currentBlockNum % blockMultiple
+
+        if (remainder === 0) {
+            return currentBlockNum
+        }
+
+        return currentBlockNum + blockMultiple - remainder
+    }
+}