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
26 changes: 26 additions & 0 deletions contracts/GeyserRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.24;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";

/// @title GeyserRegistry
contract GeyserRegistry is Ownable {
mapping(address => bool) public geysers;

event InstanceAdded(address instance);
event InstanceRemoved(address instance);

constructor() Ownable(msg.sender) {}

function register(address instance) external onlyOwner {
require(!geysers[instance], "GeyserRegistry: Geyser already registered");
geysers[instance] = true;
emit InstanceAdded(instance);
}

function deregister(address instance) external onlyOwner {
require(geysers[instance], "GeyserRegistry: Geyser not registered");
delete geysers[instance];
emit InstanceRemoved(instance);
}
}
112 changes: 112 additions & 0 deletions test/registry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { ethers } from "hardhat";
import { expect } from "chai";
import { Contract } from "ethers";

// Generated by chat-gpt
describe("GeyserRegistry Contract", () => {
let GeyserRegistry: Contract;
let deployer: any;
let nonOwner: any;
let geyserAddress: string;
let unregisteredAddress: string;

beforeEach(async () => {
[deployer, nonOwner] = await ethers.getSigners();
geyserAddress = ethers.Wallet.createRandom().address; // Mock address
unregisteredAddress = ethers.Wallet.createRandom().address; // Mock address

const GeyserRegistryFactory = await ethers.getContractFactory(
"GeyserRegistry",
deployer,
);
GeyserRegistry = await GeyserRegistryFactory.deploy();
});

describe("Deployment", () => {
it("should deploy with the correct owner", async () => {
const owner = await GeyserRegistry.owner();
expect(owner).to.equal(deployer.address);
});

it("should have no geysers initially", async () => {
const isGeyser = await GeyserRegistry.geysers(geyserAddress);
expect(isGeyser).to.equal(false);
});
});

describe("Registering a Geyser", () => {
it("should allow the owner to register a geyser", async () => {
const tx = await GeyserRegistry.register(geyserAddress);
await tx.wait();

const isGeyser = await GeyserRegistry.geysers(geyserAddress);
expect(isGeyser).to.equal(true);
});

it("should emit InstanceAdded when a geyser is registered", async () => {
await expect(GeyserRegistry.register(geyserAddress))
.to.emit(GeyserRegistry, "InstanceAdded")
.withArgs(geyserAddress);
});

it("should revert if a non-owner tries to register", async () => {
await expect(
GeyserRegistry.connect(nonOwner).register(geyserAddress),
).to.be.revertedWithCustomError(GeyserRegistry, "OwnableUnauthorizedAccount");
});

it("should revert if the geyser is already registered", async () => {
await GeyserRegistry.register(geyserAddress);
await expect(GeyserRegistry.register(geyserAddress)).to.be.revertedWith(
"GeyserRegistry: Geyser already registered",
);
});
});

describe("Deregistering a Geyser", () => {
beforeEach(async function () {
await GeyserRegistry.register(geyserAddress);
});

it("should allow the owner to deregister a geyser", async () => {
const tx = await GeyserRegistry.deregister(geyserAddress);
await tx.wait();

const isGeyser = await GeyserRegistry.geysers(geyserAddress);
expect(isGeyser).to.equal(false);
});

it("should emit InstanceRemoved when a geyser is deregistered", async () => {
await expect(GeyserRegistry.deregister(geyserAddress))
.to.emit(GeyserRegistry, "InstanceRemoved")
.withArgs(geyserAddress);
});

it("should revert if a non-owner tries to deregister", async () => {
await expect(
GeyserRegistry.connect(nonOwner).deregister(geyserAddress),
).to.be.revertedWithCustomError(GeyserRegistry, "OwnableUnauthorizedAccount");
});

it("should revert if the geyser is not registered", async () => {
await expect(GeyserRegistry.deregister(unregisteredAddress)).to.be.revertedWith(
"GeyserRegistry: Geyser not registered",
);
});
});

describe("Edge Cases", () => {
it("should not allow re-registering the same geyser address", async () => {
await GeyserRegistry.register(geyserAddress);
await expect(GeyserRegistry.register(geyserAddress)).to.be.revertedWith(
"GeyserRegistry: Geyser already registered",
);
});

it("should revert when deregistering an unregistered address", async () => {
await expect(GeyserRegistry.deregister(unregisteredAddress)).to.be.revertedWith(
"GeyserRegistry: Geyser not registered",
);
});
});
});
Loading