-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ai): introduce AIServiceRegistry contract
This commit introduces the `AIServiceRegistry` contract. This contract serves as a registry for AI subnet orchestrators, enabling them to register and make their services discoverable within the AI subnet.
- Loading branch information
Showing
4 changed files
with
140 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.9; | ||
|
||
import "./ServiceRegistry.sol"; | ||
|
||
/** | ||
* @title AIServiceRegistry | ||
* @notice Maintains a registry of service metadata associated with AI subnet service provider addresses (workers/orchestrators) | ||
*/ | ||
contract AIServiceRegistry is ServiceRegistry { | ||
constructor(address _controller) ServiceRegistry(_controller) {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import {HardhatRuntimeEnvironment} from "hardhat/types" | ||
import {DeployFunction} from "hardhat-deploy/types" | ||
|
||
import {Controller} from "../typechain" | ||
|
||
import ContractDeployer from "../utils/deployer" | ||
|
||
const func: DeployFunction = async function(hre: HardhatRuntimeEnvironment) { | ||
const {deployments, getNamedAccounts} = hre // Get the deployments and getNamedAccounts which are provided by hardhat-deploy | ||
|
||
const {deployer} = await getNamedAccounts() // Fetch named accounts from hardhat.config.ts | ||
|
||
const contractDeployer = new ContractDeployer(deployer, deployments) | ||
const Controller: Controller = await contractDeployer.deployController() | ||
|
||
await contractDeployer.deployAndRegister({ | ||
contract: "AIServiceRegistry", | ||
name: "AIServiceRegistry", | ||
proxy: true, | ||
args: [Controller.address] | ||
}) | ||
} | ||
|
||
func.tags = ["AI_SERVICE_REGISTRY"] | ||
export default func |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import Fixture from "./helpers/Fixture" | ||
import {web3, ethers} from "hardhat" | ||
|
||
import chai, {expect, assert} from "chai" | ||
import {solidity} from "ethereum-waffle" | ||
chai.use(solidity) | ||
|
||
describe("AIServiceRegistry", () => { | ||
let fixture | ||
let registry | ||
let signers | ||
let controller | ||
before(async () => { | ||
signers = await ethers.getSigners() | ||
fixture = new Fixture(web3) | ||
// Use dummy Controller in these unit tests | ||
// We are testing the logic of AIServiceRegistry directly so we do not | ||
// interact with the contract via a proxy | ||
// Thus, we do not need an actual Controller for the tests | ||
controller = signers[0].address | ||
|
||
registry = await ( | ||
await ethers.getContractFactory("AIServiceRegistry") | ||
).deploy(controller) | ||
}) | ||
|
||
beforeEach(async () => { | ||
await fixture.setUp() | ||
}) | ||
|
||
afterEach(async () => { | ||
await fixture.tearDown() | ||
}) | ||
|
||
describe("constructor", () => { | ||
it("invokes base Manager contract constructor", async () => { | ||
assert.equal( | ||
await registry.controller(), | ||
controller, | ||
"wrong Controller address" | ||
) | ||
}) | ||
}) | ||
|
||
describe("setServiceURI", () => { | ||
it("stores service URI endpoint for caller", async () => { | ||
await registry.setServiceURI("foo") | ||
await registry.connect(signers[1]).setServiceURI("bar") | ||
|
||
assert.equal( | ||
await registry.getServiceURI(signers[0].address), | ||
"foo", | ||
"wrong service URI stored for caller 1" | ||
) | ||
assert.equal( | ||
await registry.getServiceURI(signers[1].address), | ||
"bar", | ||
"wrong service URI stored for caller 2" | ||
) | ||
}) | ||
|
||
it("fires ServiceURIUpdate event", async () => { | ||
const tx = registry.setServiceURI("foo") | ||
await expect(tx) | ||
.to.emit(registry, "ServiceURIUpdate") | ||
.withArgs(signers[0].address, "foo") | ||
}) | ||
}) | ||
|
||
describe("getServiceURI", () => { | ||
it("returns service URI endpoint for provided address", async () => { | ||
await registry.setServiceURI("foo") | ||
await registry.connect(signers[1]).setServiceURI("bar") | ||
|
||
assert.equal( | ||
await registry.getServiceURI(signers[0].address), | ||
"foo", | ||
"wrong service URI stored for caller 1" | ||
) | ||
assert.equal( | ||
await registry.getServiceURI(signers[1].address), | ||
"bar", | ||
"wrong service URI stored for caller 2" | ||
) | ||
}) | ||
|
||
it("returns empty string for address without stored service URI endpoint", async () => { | ||
assert.equal( | ||
await registry.getServiceURI(signers[5].address), | ||
"", | ||
"should return empty string for address without service URI" | ||
) | ||
}) | ||
}) | ||
}) |