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

feat: add initialize func to SubnerRegistrator #107

Merged
merged 6 commits into from
Sep 12, 2023
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
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)
}
})
Loading