Skip to content
This repository has been archived by the owner on Oct 31, 2024. It is now read-only.

Commit

Permalink
feat: add initialize func to SubnerRegistrator (#107)
Browse files Browse the repository at this point in the history
Signed-off-by: Jawad Tariq <[email protected]>
  • Loading branch information
JDawg287 authored Sep 12, 2023
1 parent bc43ded commit 3cb4662
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 71 deletions.
10 changes: 9 additions & 1 deletion contracts/topos-core/SubnetRegistrator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ pragma solidity ^0.8.9;

import "./Bytes32Sets.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";

type SubnetId is bytes32;

contract SubnetRegistrator is Ownable {
contract SubnetRegistrator is Initializable, Ownable {
using Bytes32SetsLib for Bytes32SetsLib.Set;

struct Subnet {
Expand Down Expand Up @@ -47,6 +48,13 @@ contract SubnetRegistrator is Ownable {
return SubnetId.wrap(subnetSet.keyAtIndex(index));
}

/// @notice Contract initializer
/// @dev Can only be called once
/// @param admin address of the admin
function initialize(address admin) public initializer {
_transferOwnership(admin);
}

/// @notice Register a new subnet
/// @param endpoint JSON RPC endpoint of a subnet
/// @param logoURL URL for the logo of a subnet
Expand Down
60 changes: 60 additions & 0 deletions scripts/deploy-subnet-registrator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { ContractFactory, providers, utils, Wallet } from 'ethers'
import subnetRegistratorJSON from '../artifacts/contracts/topos-core/SubnetRegistrator.sol/SubnetRegistrator.json'
import { Arg, deployContractConstant } from './const-addr-deployer'

const main = async function (..._args: Arg[]) {
const [providerEndpoint, sequencerPrivateKey, salt, gasLimit, ...args] = _args
const provider = new providers.JsonRpcProvider(<string>providerEndpoint)

// Fetch the sequencer wallet
const sequencerPrivateKeyHex = sanitizeHexString(
<string>sequencerPrivateKey || ''
)
if (!utils.isHexString(sequencerPrivateKeyHex, 32)) {
console.error('ERROR: Please provide a valid private key!')
return
}
const sequencerWallet = new Wallet(sequencerPrivateKeyHex || '', provider)

// Fetch the deployer wallet
const privateKey = process.env.PRIVATE_KEY
if (!privateKey || !utils.isHexString(privateKey, 32)) {
console.error('ERROR: Please provide a valid private key! (PRIVATE_KEY)')
return
}
const deployerWallet = new Wallet(process.env.PRIVATE_KEY || '', provider)

// Deploy SubnetRegistrator contract with constant address
let address
try {
address = (
await deployContractConstant(
deployerWallet,
subnetRegistratorJSON,
<string>salt,
[...args],
<number>gasLimit
)
).address
} catch (error) {
console.error(error)
return
}
console.log(address)

// Initialize SubnetRegistrator contract
const SubnetRegistratorFactory = new ContractFactory(
subnetRegistratorJSON.abi,
subnetRegistratorJSON.bytecode,
deployerWallet
)
const subnetRegistrator = SubnetRegistratorFactory.attach(<string>address)
subnetRegistrator.initialize(sequencerWallet.address)
}

const sanitizeHexString = function (hexString: string) {
return hexString.startsWith('0x') ? hexString : `0x${hexString}`
}

const args = process.argv.slice(2)
main(...args)
54 changes: 13 additions & 41 deletions scripts/deploy.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* eslint-disable no-case-declarations */
import { ContractFactory, providers, utils, Wallet } from 'ethers'
import { providers, utils, Wallet } from 'ethers'
import fs from 'fs'

import {
Expand All @@ -9,14 +8,7 @@ import {
} from './const-addr-deployer'

const main = async function (..._args: Arg[]) {
const [
providerEndpoint,
contractJsonPath,
salt,
gasLimit,
deployConstant,
...args
] = _args
const [providerEndpoint, contractJsonPath, salt, gasLimit, ...args] = _args
const provider = new providers.JsonRpcProvider(<string>providerEndpoint)
const privateKey = process.env.PRIVATE_KEY

Expand Down Expand Up @@ -47,37 +39,17 @@ const main = async function (..._args: Arg[]) {
return
}

switch (deployConstant) {
case 'true':
const address = await deployContractConstant(
wallet,
contractJson,
<string>salt,
args,
<number>gasLimit
)
.then(({ address }) => address)
.catch(console.error)

console.log(address)
break
case 'false':
const contractFactory = new ContractFactory(
contractJson.abi,
contractJson.bytecode,
wallet
)
const contract = await contractFactory.deploy(...args, {
gasLimit: BigInt(gasLimit),
})
await contract.deployed()
console.log(contract.address)
break
default:
console.error(
`ERROR: Please provide a valid deployConstant flag! (true|false)`
)
}
const address = await deployContractConstant(
wallet,
contractJson,
<string>salt,
args,
<number>gasLimit
)
.then(({ address }) => address)
.catch(console.error)

console.log(address)
}

const args = process.argv.slice(2)
Expand Down
2 changes: 1 addition & 1 deletion scripts/register-subnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const main = async function (...args: string[]) {
process.exit(1)
}

const wallet = new Wallet(toposDeployerPrivateKey, provider)
const wallet = new Wallet(sequencerPrivateKey, provider)

const contract = new Contract(
subnetRegistratorAddress,
Expand Down
106 changes: 78 additions & 28 deletions test/topos-core/SubnetRegistrator.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Contract } from 'ethers'
import { Contract, Wallet } from 'ethers'
import { ethers } from 'hardhat'
import { expect } from 'chai'

Expand All @@ -12,16 +12,26 @@ describe('SubnetRegistrator', () => {
const subnetCurrencySymbol = 'SUB'
const chainId = 1

beforeEach(async () => {
async function deploySubnetRegistratorFixture() {
const [admin, nonAdmin, toposDeployer] = await ethers.getSigners()
const SubnetRegistrator = await ethers.getContractFactory(
'SubnetRegistrator'
)
subnetRegistrator = await SubnetRegistrator.deploy()
})
subnetRegistrator = await SubnetRegistrator.connect(toposDeployer).deploy()
await subnetRegistrator.deployed()
await subnetRegistrator.initialize(admin.address)
return {
admin,
nonAdmin,
subnetRegistrator,
toposDeployer,
}
}

describe('registerSubnet', () => {
it('reverts if non-admin tries to register a subnet', async () => {
const [, nonAdmin] = await ethers.getSigners()
const { nonAdmin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await expect(
subnetRegistrator
.connect(nonAdmin)
Expand All @@ -37,13 +47,17 @@ describe('SubnetRegistrator', () => {
})

it('reverts if the subnet is already registered', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
await expect(
registerSubnet(
Expand All @@ -52,19 +66,25 @@ describe('SubnetRegistrator', () => {
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
).to.be.revertedWith('Bytes32Set: key already exists in the set.')
})

it('registers a subnet', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
const subnet = await subnetRegistrator.subnets(subnetId)
expect(subnet.name).to.equal(subnetName)
Expand All @@ -75,53 +95,69 @@ describe('SubnetRegistrator', () => {
})

it('gets the subnet count', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
const count = await subnetRegistrator.getSubnetCount()
expect(count).to.equal(1)
})

it('gets the subnet at a given index', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
const id = await subnetRegistrator.getSubnetIdAtIndex(0)
expect(id).to.equal(subnetId)
})

it('checks if a subnet exists', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
const exists = await subnetRegistrator.subnetExists(subnetId)
expect(exists).to.be.true
})

it('emits a new subnet registered event', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await expect(
registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
)
.to.emit(subnetRegistrator, 'NewSubnetRegistered')
Expand All @@ -138,21 +174,27 @@ describe('SubnetRegistrator', () => {
})

it('reverts when removing a non-existent subnet', async () => {
await expect(removeSubnet(subnetId)).to.be.revertedWith(
'Bytes32Set: key does not exist in the set.'
)
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await expect(
removeSubnet(subnetId, subnetRegistrator, admin)
).to.be.revertedWith('Bytes32Set: key does not exist in the set.')
})

it('emit a subnet removed event', async () => {
const { admin, subnetRegistrator } =
await deploySubnetRegistratorFixture()
await registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
chainId,
subnetRegistrator,
admin
)
await expect(removeSubnet(subnetId))
await expect(removeSubnet(subnetId, subnetRegistrator, admin))
.to.emit(subnetRegistrator, 'SubnetRemoved')
.withArgs(subnetId)
})
Expand All @@ -164,19 +206,27 @@ describe('SubnetRegistrator', () => {
subnetName: string,
subnetId: string,
subnetCurrencySymbol: string,
chainId: number
chainId: number,
subnetRegistrator: Contract,
admin: Wallet
) {
return await subnetRegistrator.registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
)
return await subnetRegistrator
.connect(admin)
.registerSubnet(
endpoint,
logoURL,
subnetName,
subnetId,
subnetCurrencySymbol,
chainId
)
}

async function removeSubnet(subnetId: string) {
return await subnetRegistrator.removeSubnet(subnetId)
async function removeSubnet(
subnetId: string,
subnetRegistrator: Contract,
admin: Wallet
) {
return await subnetRegistrator.connect(admin).removeSubnet(subnetId)
}
})

0 comments on commit 3cb4662

Please sign in to comment.