diff --git a/contracts/tasks/index.ts b/contracts/tasks/index.ts
index 37d8529c8..6f4bfc5e2 100644
--- a/contracts/tasks/index.ts
+++ b/contracts/tasks/index.ts
@@ -12,3 +12,4 @@ import './fetchRound'
import './mergeAllocations'
import './setDurations'
import './deploySponsor'
+import './loadUsers'
diff --git a/contracts/tasks/loadUsers.ts b/contracts/tasks/loadUsers.ts
new file mode 100644
index 000000000..6fb185d2f
--- /dev/null
+++ b/contracts/tasks/loadUsers.ts
@@ -0,0 +1,86 @@
+import { task } from 'hardhat/config'
+import { Contract, utils, ContractReceipt } from 'ethers'
+import fs from 'fs'
+
+/*
+ * Script to bulkload users into the simple user registry.
+ * File path can be relative or absolute path.
+ * The script can only be run by the owner of the simple user registry
+ *
+ * Sample usage:
+ *
+ * yarn hardhat load-users --file-path addresses.txt --user-registry
--network goerli
+ */
+
+/**
+ * Add a user to the Simple user registry
+ *
+ * @param registry Simple user registry contract
+ * @param address User wallet address
+ * @returns transaction receipt
+ */
+async function addUser(
+ registry: Contract,
+ address: string
+): Promise {
+ const tx = await registry.addUser(address)
+ const receipt = await tx.wait()
+ return receipt
+}
+
+/**
+ * Load users in the file into the simple user registry
+ *
+ * @param registry Simple user registry contract
+ * @param filePath The path of the file containing the addresses
+ */
+async function loadFile(registry: Contract, filePath: string) {
+ let content: string | null = null
+ try {
+ content = fs.readFileSync(filePath, 'utf8')
+ } catch (err) {
+ console.error('Failed to read file', filePath, err)
+ return
+ }
+
+ const addresses: string[] = []
+ content.split(/\r?\n/).forEach(async (address) => {
+ addresses.push(address)
+ })
+
+ for (let i = 0; i < addresses.length; i++) {
+ const address = addresses[i]
+ const isValidAddress = Boolean(address) && utils.isAddress(address)
+ if (isValidAddress) {
+ console.log('Adding address', address)
+ try {
+ const result = await addUser(registry, address)
+ if (result.status !== 1) {
+ throw new Error(
+ `Transaction ${result.transactionHash} failed with status ${result.status}`
+ )
+ }
+ } catch (err) {
+ console.error('Failed to add address', address, err)
+ break
+ }
+ } else {
+ console.warn('Skipping invalid address', address)
+ }
+ }
+}
+
+task('load-users', 'Bulkload recipients into the simple user registry')
+ .addParam('userRegistry', 'The simple user registry contract address')
+ .addParam(
+ 'filePath',
+ 'The path of the file containing addresses separated by newline'
+ )
+ .setAction(async ({ userRegistry, filePath }, { ethers }) => {
+ const registry = await ethers.getContractAt(
+ 'SimpleUserRegistry',
+ userRegistry
+ )
+
+ await loadFile(registry, filePath)
+ })