ci: clean up CI workflows and fix package dependencies
Some checks failed
Integration Tests / test-service-integration (push) Successful in 2m16s
Package Tests / Python package - aitbc-agent-sdk (push) Successful in 25s
Package Tests / Python package - aitbc-core (push) Successful in 22s
Package Tests / Python package - aitbc-crypto (push) Successful in 14s
Package Tests / Python package - aitbc-sdk (push) Successful in 18s
Package Tests / JavaScript package - aitbc-sdk-js (push) Successful in 6s
Package Tests / JavaScript package - aitbc-token (push) Successful in 21s
Production Tests / Production Integration Tests (push) Failing after 10s
Python Tests / test-python (push) Failing after 2m41s
Security Scanning / security-scan (push) Failing after 46s
Smart Contract Tests / test-solidity (map[name:aitbc-token path:packages/solidity/aitbc-token]) (push) Successful in 16s
Smart Contract Tests / lint-solidity (push) Successful in 12s

- Simplified npm install commands in CI workflows by removing fallback logic
- Added aitbc-crypto local dependency installation for aitbc-sdk in package-tests.yml
- Removed aitbc-token specific Hardhat dependency workarounds from package-tests.yml
- Fixed bare except clause in agent_daemon.py to catch specific json.JSONDecodeError
- Moved aitbc-crypto from poetry.dependencies to standard dependencies in aitbc-sdk
- Fixed MyPy type errors in receip
This commit is contained in:
aitbc
2026-04-19 19:24:09 +02:00
parent 0fc735b802
commit 625c1b7812
29 changed files with 3386 additions and 3377 deletions

View File

@@ -12,12 +12,10 @@ dependencies = [
"requests>=2.31.0",
"pydantic>=2.5.0",
"httpx>=0.25.0",
"pynacl>=1.5.0"
"pynacl>=1.5.0",
"aitbc-crypto>=0.1.0"
]
[tool.poetry.dependencies]
aitbc-crypto = { path = "../aitbc-crypto", develop = true }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

View File

@@ -2,7 +2,7 @@ from __future__ import annotations
import time
from dataclasses import dataclass, field
from typing import Any, Dict, Iterable, Iterator, List, Optional
from typing import Any, Dict, Iterable, Iterator, List, Optional, cast
import httpx
import base64
@@ -94,7 +94,10 @@ class CoordinatorReceiptClient:
resp = self._request("GET", f"/v1/jobs/{job_id}/receipt", allow_404=True)
if resp is None:
return None
return resp.json() # type: ignore[return-value]
payload = resp.json()
if not isinstance(payload, dict):
raise ValueError("Expected receipt payload to be a JSON object")
return cast(Dict[str, Any], payload)
def fetch_history(self, job_id: str) -> List[Dict[str, Any]]:
return list(self.iter_receipts(job_id=job_id))

View File

@@ -1,16 +1,15 @@
{
"plugins": ["@prettier/plugin-solidity"],
"plugins": ["prettier-plugin-solidity"],
"overrides": [
{
"files": "*.sol",
"options": {
"parser": "solidity-parse",
"parser": "slang",
"printWidth": 80,
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": true,
"explicitTypes": "always"
"bracketSpacing": true
}
}
]

View File

@@ -1,61 +1,76 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";
/// @title AIToken
/// @notice ERC20 token that mints units for providers based on attested compute receipts
contract AIToken is ERC20, AccessControl {
using ECDSA for bytes32;
using MessageHashUtils for bytes32;
using ECDSA for bytes32;
using MessageHashUtils for bytes32;
bytes32 public constant COORDINATOR_ROLE = keccak256("COORDINATOR_ROLE");
bytes32 public constant ATTESTOR_ROLE = keccak256("ATTESTOR_ROLE");
bytes32 public constant COORDINATOR_ROLE = keccak256("COORDINATOR_ROLE");
bytes32 public constant ATTESTOR_ROLE = keccak256("ATTESTOR_ROLE");
/// @notice Tracks consumed receipt hashes to prevent replay
mapping(bytes32 => bool) public consumedReceipts;
/// @notice Tracks consumed receipt hashes to prevent replay
mapping(bytes32 => bool) public consumedReceipts;
event ReceiptConsumed(bytes32 indexed receiptHash, address indexed provider, uint256 units, address indexed attestor);
event ReceiptConsumed(
bytes32 indexed receiptHash,
address indexed provider,
uint256 units,
address indexed attestor
);
constructor(address admin) ERC20("AIToken", "AIT") {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
constructor(address admin) ERC20("AIToken", "AIT") {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
/// @notice Mint tokens for a provider when coordinator submits a valid attested receipt
/// @param provider Address of the compute provider receiving minted tokens
/// @param units Amount of tokens to mint
/// @param receiptHash Unique hash representing the off-chain receipt
/// @param signature Coordinator-attested signature authorizing the mint
function mintWithReceipt(
address provider,
uint256 units,
bytes32 receiptHash,
bytes calldata signature
) external onlyRole(COORDINATOR_ROLE) {
require(provider != address(0), "invalid provider");
require(units > 0, "invalid units");
require(!consumedReceipts[receiptHash], "receipt already consumed");
/// @notice Mint tokens for a provider when coordinator submits a valid attested receipt
/// @param provider Address of the compute provider receiving minted tokens
/// @param units Amount of tokens to mint
/// @param receiptHash Unique hash representing the off-chain receipt
/// @param signature Coordinator-attested signature authorizing the mint
function mintWithReceipt(
address provider,
uint256 units,
bytes32 receiptHash,
bytes calldata signature
) external onlyRole(COORDINATOR_ROLE) {
require(provider != address(0), "invalid provider");
require(units > 0, "invalid units");
require(!consumedReceipts[receiptHash], "receipt already consumed");
bytes32 digest = _mintDigest(provider, units, receiptHash);
address attestor = digest.recover(signature);
require(hasRole(ATTESTOR_ROLE, attestor), "invalid attestor signature");
bytes32 digest = _mintDigest(provider, units, receiptHash);
address attestor = digest.recover(signature);
require(hasRole(ATTESTOR_ROLE, attestor), "invalid attestor signature");
consumedReceipts[receiptHash] = true;
_mint(provider, units);
consumedReceipts[receiptHash] = true;
_mint(provider, units);
emit ReceiptConsumed(receiptHash, provider, units, attestor);
}
emit ReceiptConsumed(receiptHash, provider, units, attestor);
}
/// @notice Helper to compute the signed digest required for minting
function mintDigest(address provider, uint256 units, bytes32 receiptHash) external view returns (bytes32) {
return _mintDigest(provider, units, receiptHash);
}
/// @notice Helper to compute the signed digest required for minting
function mintDigest(
address provider,
uint256 units,
bytes32 receiptHash
) external view returns (bytes32) {
return _mintDigest(provider, units, receiptHash);
}
function _mintDigest(address provider, uint256 units, bytes32 receiptHash) internal view returns (bytes32) {
bytes32 structHash = keccak256(abi.encode(block.chainid, address(this), provider, units, receiptHash));
return structHash.toEthSignedMessageHash();
}
function _mintDigest(
address provider,
uint256 units,
bytes32 receiptHash
) internal view returns (bytes32) {
bytes32 structHash = keccak256(
abi.encode(block.chainid, address(this), provider, units, receiptHash)
);
return structHash.toEthSignedMessageHash();
}
}

View File

@@ -1,46 +1,61 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
/// @title AITokenRegistry
/// @notice Tracks permitted providers and staking requirements for AIToken minting
contract AITokenRegistry is AccessControl {
bytes32 public constant COORDINATOR_ROLE = keccak256("COORDINATOR_ROLE");
bytes32 public constant COORDINATOR_ROLE = keccak256("COORDINATOR_ROLE");
struct ProviderInfo {
bool active;
uint256 collateral;
}
struct ProviderInfo {
bool active;
uint256 collateral;
}
mapping(address => ProviderInfo) public providers;
mapping(address => ProviderInfo) public providers;
event ProviderRegistered(address indexed provider, uint256 collateral);
event ProviderUpdated(address indexed provider, bool active, uint256 collateral);
event ProviderRegistered(address indexed provider, uint256 collateral);
event ProviderUpdated(
address indexed provider,
bool active,
uint256 collateral
);
constructor(address admin) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
constructor(address admin) {
_grantRole(DEFAULT_ADMIN_ROLE, admin);
}
function registerProvider(address provider, uint256 collateral) external onlyRole(COORDINATOR_ROLE) {
require(provider != address(0), "invalid provider");
require(!providers[provider].active, "already registered");
providers[provider] = ProviderInfo({active: true, collateral: collateral});
emit ProviderRegistered(provider, collateral);
}
function registerProvider(
address provider,
uint256 collateral
) external onlyRole(COORDINATOR_ROLE) {
require(provider != address(0), "invalid provider");
require(!providers[provider].active, "already registered");
providers[provider] = ProviderInfo({
active: true,
collateral: collateral
});
emit ProviderRegistered(provider, collateral);
}
function updateProvider(
address provider,
bool active,
uint256 collateral
) external onlyRole(COORDINATOR_ROLE) {
require(provider != address(0), "invalid provider");
require(providers[provider].active || active, "provider not registered");
providers[provider] = ProviderInfo({active: active, collateral: collateral});
emit ProviderUpdated(provider, active, collateral);
}
function updateProvider(
address provider,
bool active,
uint256 collateral
) external onlyRole(COORDINATOR_ROLE) {
require(provider != address(0), "invalid provider");
require(providers[provider].active || active, "provider not registered");
providers[provider] = ProviderInfo({
active: active,
collateral: collateral
});
emit ProviderUpdated(provider, active, collateral);
}
function providerInfo(address provider) external view returns (ProviderInfo memory) {
return providers[provider];
}
function providerInfo(
address provider
) external view returns (ProviderInfo memory) {
return providers[provider];
}
}

View File

@@ -0,0 +1,7 @@
declare module "@nomicfoundation/hardhat-toolbox-mocha-ethers" {
import type { HardhatPlugin } from "hardhat/types/plugins";
const hardhatToolboxMochaEthersPlugin: HardhatPlugin;
export default hardhatToolboxMochaEthersPlugin;
}

View File

@@ -1,7 +1,8 @@
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
import { defineConfig } from "hardhat/config";
import hardhatToolboxMochaEthersPlugin from "@nomicfoundation/hardhat-toolbox-mocha-ethers";
const config: HardhatUserConfig = {
export default defineConfig({
plugins: [hardhatToolboxMochaEthersPlugin],
solidity: {
version: "0.8.25",
settings: {
@@ -19,11 +20,10 @@ const config: HardhatUserConfig = {
artifacts: "artifacts"
},
networks: {
hardhat: {},
localhost: {
type: "http",
chainType: "l1",
url: "http://127.0.0.1:8545"
}
}
};
export default config;
});

File diff suppressed because it is too large Load Diff

View File

@@ -12,23 +12,26 @@
"deploy": "hardhat run scripts/deploy.ts --network localhost"
},
"devDependencies": {
"@nomicfoundation/hardhat-chai-matchers": "^3.0.0",
"@nomicfoundation/hardhat-ethers": "^4.0.7",
"@nomicfoundation/hardhat-ignition-ethers": "^3.1.1",
"@nomicfoundation/hardhat-network-helpers": "^3.0.4",
"@nomicfoundation/hardhat-toolbox": "7.0.0-hh2",
"@nomicfoundation/hardhat-verify": "^3.0.13",
"@typechain/ethers-v6": "^0.5.1",
"@types/chai": "^4.3.11",
"@nomicfoundation/hardhat-ethers": "^4.0.0",
"@nomicfoundation/hardhat-ethers-chai-matchers": "^3.0.0",
"@nomicfoundation/hardhat-ignition": "^3.0.7",
"@nomicfoundation/hardhat-ignition-ethers": "^3.0.7",
"@nomicfoundation/hardhat-keystore": "^3.0.0",
"@nomicfoundation/hardhat-mocha": "^3.0.0",
"@nomicfoundation/hardhat-network-helpers": "^3.0.0",
"@nomicfoundation/hardhat-toolbox-mocha-ethers": "^3.0.2",
"@nomicfoundation/hardhat-typechain": "^3.0.0",
"@nomicfoundation/hardhat-verify": "^3.0.0",
"@nomicfoundation/ignition-core": "^3.0.7",
"@types/chai": "^5.2.3",
"@types/mocha": "^10.0.10",
"@types/node": "^20.11.30",
"chai": "^4.4.1",
"chai": "^5.1.2",
"ethers": "^6.16.0",
"hardhat": "^3.3.0",
"hardhat-gas-reporter": "^1.0.10",
"@prettier/plugin-solidity": "^1.3.1",
"mocha": "^11.0.0",
"prettier": "^3.2.5",
"solidity-coverage": "^0.8.4",
"prettier-plugin-solidity": "^2.3.1",
"ts-node": "^10.9.2",
"typescript": "^5.9.2"
},

View File

@@ -1,5 +1,10 @@
import { ethers } from "hardhat";
import { AIToken__factory } from "../typechain-types";
import type { HardhatEthers } from "@nomicfoundation/hardhat-ethers/types";
import { network } from "hardhat";
import type { NetworkConnection } from "hardhat/types/network";
type HardhatConnection = NetworkConnection & {
ethers: HardhatEthers;
};
function envOrDefault(name: string, fallback?: string): string | undefined {
const value = process.env[name]?.trim();
@@ -7,11 +12,12 @@ function envOrDefault(name: string, fallback?: string): string | undefined {
}
async function main() {
const { ethers } = (await network.connect()) as HardhatConnection;
const [deployer, coordinatorCandidate] = await ethers.getSigners();
console.log("Deploying AIToken using admin:", deployer.address);
const contractFactory: AIToken__factory = await ethers.getContractFactory("AIToken");
const contractFactory = await ethers.getContractFactory("AIToken");
const token = await contractFactory.deploy(deployer.address);
await token.waitForDeployment();
@@ -21,10 +27,13 @@ async function main() {
const coordinatorRole = await token.COORDINATOR_ROLE();
const attestorRole = await token.ATTESTOR_ROLE();
const coordinatorAddress = envOrDefault("COORDINATOR_ADDRESS", coordinatorCandidate.address);
const coordinatorAddress = envOrDefault(
"COORDINATOR_ADDRESS",
coordinatorCandidate.address,
);
if (!coordinatorAddress) {
throw new Error(
"COORDINATOR_ADDRESS not provided and could not infer fallback signer address"
"COORDINATOR_ADDRESS not provided and could not infer fallback signer address",
);
}

View File

@@ -1,9 +1,15 @@
import { ethers } from "hardhat";
import type { HardhatEthers } from "@nomicfoundation/hardhat-ethers/types";
import { network } from "hardhat";
import type { NetworkConnection } from "hardhat/types/network";
import { AIToken__factory } from "../typechain-types";
type HardhatConnection = NetworkConnection & {
ethers: HardhatEthers;
};
type HexString = `0x${string}`;
type EnvValue = string & {}
type EnvValue = string & {};
function requireEnv(name: string): EnvValue {
const value = process.env[name]?.trim();
@@ -20,7 +26,9 @@ function parseUnits(value: string): bigint {
}
return BigInt(value);
} catch (error) {
throw new Error(`UNITS must be a BigInt-compatible value, received ${value}`);
throw new Error(
`UNITS must be a BigInt-compatible value, received ${value}`,
);
}
}
@@ -32,18 +40,25 @@ function assertHex(value: string, name: string): HexString {
}
async function main() {
const contractAddress = assertHex(requireEnv("AITOKEN_ADDRESS"), "AITOKEN_ADDRESS");
const { ethers } = (await network.connect()) as HardhatConnection;
const contractAddress = assertHex(
requireEnv("AITOKEN_ADDRESS"),
"AITOKEN_ADDRESS",
);
const providerAddress = requireEnv("PROVIDER_ADDRESS");
const units = parseUnits(requireEnv("UNITS"));
const receiptHash = assertHex(requireEnv("RECEIPT_HASH"), "RECEIPT_HASH");
const signature = assertHex(requireEnv("ATTESTOR_SIGNATURE"), "ATTESTOR_SIGNATURE");
const signature = assertHex(
requireEnv("ATTESTOR_SIGNATURE"),
"ATTESTOR_SIGNATURE",
);
const coordinatorIndex = Number(process.env.COORDINATOR_SIGNER_INDEX ?? "1");
const signers = await ethers.getSigners();
const coordinator = signers[coordinatorIndex];
if (!coordinator) {
throw new Error(
`COORDINATOR_SIGNER_INDEX=${coordinatorIndex} does not correspond to an available signer`
`COORDINATOR_SIGNER_INDEX=${coordinatorIndex} does not correspond to an available signer`,
);
}
@@ -52,7 +67,12 @@ async function main() {
console.log("Units:", units.toString());
const token = AIToken__factory.connect(contractAddress, coordinator);
const tx = await token.mintWithReceipt(providerAddress, units, receiptHash, signature);
const tx = await token.mintWithReceipt(
providerAddress,
units,
receiptHash,
signature,
);
const receipt = await tx.wait();
console.log("Mint transaction hash:", receipt?.hash ?? tx.hash);

View File

@@ -1,12 +1,70 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
import type { Signer } from "ethers";
import type { HardhatEthers } from "@nomicfoundation/hardhat-ethers/types";
import type { NetworkHelpers } from "@nomicfoundation/hardhat-network-helpers/types";
import type { BaseContract, ContractTransactionResponse, Signer } from "ethers";
import { network } from "hardhat";
import type { NetworkConnection } from "hardhat/types/network";
import type { AIToken } from "../typechain-types";
import { AIToken__factory } from "../typechain-types";
type HardhatConnection = NetworkConnection & {
ethers: HardhatEthers;
networkHelpers: NetworkHelpers;
};
const { ethers, networkHelpers } =
(await network.connect()) as HardhatConnection;
async function expectRevert(
operation: Promise<unknown>,
expectedMessage?: string,
) {
let caughtError: unknown;
try {
await operation;
} catch (error) {
caughtError = error;
}
expect(caughtError).to.not.equal(undefined);
if (expectedMessage !== undefined) {
const message =
caughtError instanceof Error ? caughtError.message : String(caughtError);
expect(message).to.contain(expectedMessage);
}
}
async function expectEvent(
contract: BaseContract,
operation: Promise<ContractTransactionResponse>,
eventName: string,
expectedArgs: readonly unknown[],
) {
const tx = await operation;
const receipt = await tx.wait();
expect(receipt).to.not.equal(null);
const parsedLog = receipt!.logs
.map((log) => {
try {
return contract.interface.parseLog(log);
} catch {
return null;
}
})
.find((entry) => entry?.name === eventName);
expect(parsedLog).to.not.equal(undefined);
expect(parsedLog).to.not.equal(null);
expect(Array.from(parsedLog!.args)).to.deep.equal([...expectedArgs]);
}
async function deployAITokenFixture() {
const [admin, coordinator, attestor, provider, outsider] = await ethers.getSigners();
const [admin, coordinator, attestor, provider, outsider] =
await ethers.getSigners();
const factory = new AIToken__factory(admin);
const token = await factory.deploy(admin.address);
@@ -26,7 +84,7 @@ async function buildSignature(
attestor: Signer,
provider: string,
units: bigint,
receiptHash: string
receiptHash: string,
) {
const chainId = (await ethers.provider.getNetwork()).chainId;
const contractAddress = await token.getAddress();
@@ -34,7 +92,7 @@ async function buildSignature(
const encoded = abiCoder.encode(
["uint256", "address", "address", "uint256", "bytes32"],
[chainId, contractAddress, provider, units, receiptHash]
[chainId, contractAddress, provider, units, receiptHash],
);
const structHash = ethers.keccak256(encoded);
@@ -43,46 +101,61 @@ async function buildSignature(
describe("AIToken", function () {
it("mints tokens when presented a valid attestor signature", async function () {
const { token, coordinator, attestor, provider } = await loadFixture(deployAITokenFixture);
const { token, coordinator, attestor, provider } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 100n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-1"));
const signature = await buildSignature(token, attestor, provider.address, units, receiptHash);
const signature = await buildSignature(
token,
attestor,
provider.address,
units,
receiptHash,
);
await expect(
await expectEvent(
token,
token
.connect(coordinator)
.mintWithReceipt(provider.address, units, receiptHash, signature)
)
.to.emit(token, "ReceiptConsumed")
.withArgs(receiptHash, provider.address, units, attestor.address);
.mintWithReceipt(provider.address, units, receiptHash, signature),
"ReceiptConsumed",
[receiptHash, provider.address, units, attestor.address],
);
expect(await token.balanceOf(provider.address)).to.equal(units);
expect(await token.consumedReceipts(receiptHash)).to.equal(true);
});
it("rejects reuse of a consumed receipt hash", async function () {
const { token, coordinator, attestor, provider } = await loadFixture(deployAITokenFixture);
const { token, coordinator, attestor, provider } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 50n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-2"));
const signature = await buildSignature(token, attestor, provider.address, units, receiptHash);
const signature = await buildSignature(
token,
attestor,
provider.address,
units,
receiptHash,
);
await token
.connect(coordinator)
.mintWithReceipt(provider.address, units, receiptHash, signature);
await expect(
await expectRevert(
token
.connect(coordinator)
.mintWithReceipt(provider.address, units, receiptHash, signature)
).to.be.revertedWith("receipt already consumed");
.mintWithReceipt(provider.address, units, receiptHash, signature),
"receipt already consumed",
);
});
it("rejects signatures from non-attestors", async function () {
const { token, coordinator, attestor, provider, outsider } = await loadFixture(
deployAITokenFixture
);
const { token, coordinator, attestor, provider, outsider } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 25n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-3"));
@@ -91,60 +164,85 @@ describe("AIToken", function () {
outsider,
provider.address,
units,
receiptHash
receiptHash,
);
await expect(
await expectRevert(
token
.connect(coordinator)
.mintWithReceipt(provider.address, units, receiptHash, signature)
).to.be.revertedWith("invalid attestor signature");
.mintWithReceipt(provider.address, units, receiptHash, signature),
"invalid attestor signature",
);
});
it("rejects minting to zero address", async function () {
const { token, coordinator, attestor } = await loadFixture(deployAITokenFixture);
const { token, coordinator, attestor } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 100n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-4"));
const signature = await buildSignature(token, attestor, ethers.ZeroAddress, units, receiptHash);
const signature = await buildSignature(
token,
attestor,
ethers.ZeroAddress,
units,
receiptHash,
);
await expect(
await expectRevert(
token
.connect(coordinator)
.mintWithReceipt(ethers.ZeroAddress, units, receiptHash, signature)
).to.be.revertedWith("invalid provider");
.mintWithReceipt(ethers.ZeroAddress, units, receiptHash, signature),
"invalid provider",
);
});
it("rejects minting zero units", async function () {
const { token, coordinator, attestor, provider } = await loadFixture(deployAITokenFixture);
const { token, coordinator, attestor, provider } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 0n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-5"));
const signature = await buildSignature(token, attestor, provider.address, units, receiptHash);
const signature = await buildSignature(
token,
attestor,
provider.address,
units,
receiptHash,
);
await expect(
await expectRevert(
token
.connect(coordinator)
.mintWithReceipt(provider.address, units, receiptHash, signature)
).to.be.revertedWith("invalid units");
.mintWithReceipt(provider.address, units, receiptHash, signature),
"invalid units",
);
});
it("rejects minting from non-coordinator", async function () {
const { token, attestor, provider, outsider } = await loadFixture(deployAITokenFixture);
const { token, attestor, provider, outsider } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 100n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-6"));
const signature = await buildSignature(token, attestor, provider.address, units, receiptHash);
const signature = await buildSignature(
token,
attestor,
provider.address,
units,
receiptHash,
);
await expect(
await expectRevert(
token
.connect(outsider)
.mintWithReceipt(provider.address, units, receiptHash, signature)
).to.be.reverted;
.mintWithReceipt(provider.address, units, receiptHash, signature),
);
});
it("returns correct mint digest", async function () {
const { token, provider } = await loadFixture(deployAITokenFixture);
const { token, provider } =
await networkHelpers.loadFixture(deployAITokenFixture);
const units = 100n;
const receiptHash = ethers.keccak256(ethers.toUtf8Bytes("receipt-7"));
@@ -155,7 +253,7 @@ describe("AIToken", function () {
});
it("has correct token name and symbol", async function () {
const { token } = await loadFixture(deployAITokenFixture);
const { token } = await networkHelpers.loadFixture(deployAITokenFixture);
expect(await token.name()).to.equal("AIToken");
expect(await token.symbol()).to.equal("AIT");

View File

@@ -1,10 +1,69 @@
import { expect } from "chai";
import { ethers } from "hardhat";
import { loadFixture } from "@nomicfoundation/hardhat-toolbox/network-helpers";
import type { HardhatEthers } from "@nomicfoundation/hardhat-ethers/types";
import type { NetworkHelpers } from "@nomicfoundation/hardhat-network-helpers/types";
import type { BaseContract, ContractTransactionResponse } from "ethers";
import { network } from "hardhat";
import type { NetworkConnection } from "hardhat/types/network";
import { AITokenRegistry__factory } from "../typechain-types";
type HardhatConnection = NetworkConnection & {
ethers: HardhatEthers;
networkHelpers: NetworkHelpers;
};
const { ethers, networkHelpers } =
(await network.connect()) as HardhatConnection;
async function expectRevert(
operation: Promise<unknown>,
expectedMessage?: string,
) {
let caughtError: unknown;
try {
await operation;
} catch (error) {
caughtError = error;
}
expect(caughtError).to.not.equal(undefined);
if (expectedMessage !== undefined) {
const message =
caughtError instanceof Error ? caughtError.message : String(caughtError);
expect(message).to.contain(expectedMessage);
}
}
async function expectEvent(
contract: BaseContract,
operation: Promise<ContractTransactionResponse>,
eventName: string,
expectedArgs: readonly unknown[],
) {
const tx = await operation;
const receipt = await tx.wait();
expect(receipt).to.not.equal(null);
const parsedLog = receipt!.logs
.map((log) => {
try {
return contract.interface.parseLog(log);
} catch {
return null;
}
})
.find((entry) => entry?.name === eventName);
expect(parsedLog).to.not.equal(undefined);
expect(parsedLog).to.not.equal(null);
expect(Array.from(parsedLog!.args)).to.deep.equal([...expectedArgs]);
}
async function deployRegistryFixture() {
const [admin, coordinator, provider1, provider2, outsider] = await ethers.getSigners();
const [admin, coordinator, provider1, provider2, outsider] =
await ethers.getSigners();
const factory = new AITokenRegistry__factory(admin);
const registry = await factory.deploy(admin.address);
@@ -19,15 +78,19 @@ async function deployRegistryFixture() {
describe("AITokenRegistry", function () {
describe("Provider Registration", function () {
it("allows coordinator to register a provider", async function () {
const { registry, coordinator, provider1 } = await loadFixture(deployRegistryFixture);
const { registry, coordinator, provider1 } =
await networkHelpers.loadFixture(deployRegistryFixture);
const collateral = ethers.parseEther("100");
await expect(
registry.connect(coordinator).registerProvider(provider1.address, collateral)
)
.to.emit(registry, "ProviderRegistered")
.withArgs(provider1.address, collateral);
await expectEvent(
registry,
registry
.connect(coordinator)
.registerProvider(provider1.address, collateral),
"ProviderRegistered",
[provider1.address, collateral],
);
const info = await registry.providerInfo(provider1.address);
expect(info.active).to.equal(true);
@@ -35,43 +98,57 @@ describe("AITokenRegistry", function () {
});
it("rejects registration of zero address", async function () {
const { registry, coordinator } = await loadFixture(deployRegistryFixture);
const { registry, coordinator } = await networkHelpers.loadFixture(
deployRegistryFixture,
);
await expect(
registry.connect(coordinator).registerProvider(ethers.ZeroAddress, 0)
).to.be.revertedWith("invalid provider");
await expectRevert(
registry.connect(coordinator).registerProvider(ethers.ZeroAddress, 0),
"invalid provider",
);
});
it("rejects duplicate registration", async function () {
const { registry, coordinator, provider1 } = await loadFixture(deployRegistryFixture);
const { registry, coordinator, provider1 } =
await networkHelpers.loadFixture(deployRegistryFixture);
await registry.connect(coordinator).registerProvider(provider1.address, 100);
await registry
.connect(coordinator)
.registerProvider(provider1.address, 100);
await expect(
registry.connect(coordinator).registerProvider(provider1.address, 200)
).to.be.revertedWith("already registered");
await expectRevert(
registry.connect(coordinator).registerProvider(provider1.address, 200),
"already registered",
);
});
it("rejects registration from non-coordinator", async function () {
const { registry, provider1, outsider } = await loadFixture(deployRegistryFixture);
const { registry, provider1, outsider } =
await networkHelpers.loadFixture(deployRegistryFixture);
await expect(
registry.connect(outsider).registerProvider(provider1.address, 100)
).to.be.reverted;
await expectRevert(
registry.connect(outsider).registerProvider(provider1.address, 100),
);
});
});
describe("Provider Updates", function () {
it("allows coordinator to update provider status", async function () {
const { registry, coordinator, provider1 } = await loadFixture(deployRegistryFixture);
const { registry, coordinator, provider1 } =
await networkHelpers.loadFixture(deployRegistryFixture);
await registry.connect(coordinator).registerProvider(provider1.address, 100);
await registry
.connect(coordinator)
.registerProvider(provider1.address, 100);
await expect(
registry.connect(coordinator).updateProvider(provider1.address, false, 50)
)
.to.emit(registry, "ProviderUpdated")
.withArgs(provider1.address, false, 50);
await expectEvent(
registry,
registry
.connect(coordinator)
.updateProvider(provider1.address, false, 50),
"ProviderUpdated",
[provider1.address, false, 50n],
);
const info = await registry.providerInfo(provider1.address);
expect(info.active).to.equal(false);
@@ -79,11 +156,18 @@ describe("AITokenRegistry", function () {
});
it("allows reactivating a deactivated provider", async function () {
const { registry, coordinator, provider1 } = await loadFixture(deployRegistryFixture);
const { registry, coordinator, provider1 } =
await networkHelpers.loadFixture(deployRegistryFixture);
await registry.connect(coordinator).registerProvider(provider1.address, 100);
await registry.connect(coordinator).updateProvider(provider1.address, false, 100);
await registry.connect(coordinator).updateProvider(provider1.address, true, 200);
await registry
.connect(coordinator)
.registerProvider(provider1.address, 100);
await registry
.connect(coordinator)
.updateProvider(provider1.address, false, 100);
await registry
.connect(coordinator)
.updateProvider(provider1.address, true, 200);
const info = await registry.providerInfo(provider1.address);
expect(info.active).to.equal(true);
@@ -91,32 +175,45 @@ describe("AITokenRegistry", function () {
});
it("rejects update of unregistered provider", async function () {
const { registry, coordinator, provider1 } = await loadFixture(deployRegistryFixture);
const { registry, coordinator, provider1 } =
await networkHelpers.loadFixture(deployRegistryFixture);
await expect(
registry.connect(coordinator).updateProvider(provider1.address, false, 100)
).to.be.revertedWith("provider not registered");
await expectRevert(
registry
.connect(coordinator)
.updateProvider(provider1.address, false, 100),
"provider not registered",
);
});
});
describe("Access Control", function () {
it("admin can grant coordinator role", async function () {
const { registry, admin, outsider } = await loadFixture(deployRegistryFixture);
const { registry, admin, outsider } = await networkHelpers.loadFixture(
deployRegistryFixture,
);
const coordinatorRole = await registry.COORDINATOR_ROLE();
await registry.connect(admin).grantRole(coordinatorRole, outsider.address);
await registry
.connect(admin)
.grantRole(coordinatorRole, outsider.address);
expect(await registry.hasRole(coordinatorRole, outsider.address)).to.equal(true);
expect(
await registry.hasRole(coordinatorRole, outsider.address),
).to.equal(true);
});
it("non-admin cannot grant roles", async function () {
const { registry, coordinator, outsider } = await loadFixture(deployRegistryFixture);
const { registry, coordinator, outsider } =
await networkHelpers.loadFixture(deployRegistryFixture);
const coordinatorRole = await registry.COORDINATOR_ROLE();
await expect(
registry.connect(coordinator).grantRole(coordinatorRole, outsider.address)
).to.be.reverted;
await expectRevert(
registry
.connect(coordinator)
.grantRole(coordinatorRole, outsider.address),
);
});
});
});

View File

@@ -1,14 +1,20 @@
{
"compilerOptions": {
"target": "es2020",
"module": "commonjs",
"target": "es2022",
"module": "esnext",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"outDir": "dist",
"types": ["node", "mocha", "hardhat", "@nomicfoundation/hardhat-chai-matchers"],
"resolveJsonModule": true,
"moduleResolution": "node"
"moduleResolution": "bundler"
},
"include": ["hardhat.config.ts", "scripts", "test", "typechain-types"],
"include": [
"hardhat.config.ts",
"hardhat-toolbox-mocha-ethers.d.ts",
"scripts",
"test",
"typechain-types"
],
"exclude": ["dist"]
}

View File

@@ -2,4 +2,3 @@
/* tslint:disable */
/* eslint-disable */
export type { ECDSA } from "./ECDSA";
export type { MessageHashUtils } from "./MessageHashUtils";

View File

@@ -2,4 +2,3 @@
/* tslint:disable */
/* eslint-disable */
export { ECDSA__factory } from "./ECDSA__factory";
export { MessageHashUtils__factory } from "./MessageHashUtils__factory";

View File

@@ -49,10 +49,6 @@ declare module "hardhat/types/runtime" {
name: "ECDSA",
signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<Contracts.ECDSA__factory>;
getContractFactory(
name: "MessageHashUtils",
signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<Contracts.MessageHashUtils__factory>;
getContractFactory(
name: "ERC165",
signerOrOptions?: ethers.Signer | FactoryOptions
@@ -123,11 +119,6 @@ declare module "hardhat/types/runtime" {
address: string | ethers.Addressable,
signer?: ethers.Signer
): Promise<Contracts.ECDSA>;
getContractAt(
name: "MessageHashUtils",
address: string | ethers.Addressable,
signer?: ethers.Signer
): Promise<Contracts.MessageHashUtils>;
getContractAt(
name: "ERC165",
address: string | ethers.Addressable,
@@ -195,10 +186,6 @@ declare module "hardhat/types/runtime" {
name: "ECDSA",
signerOrOptions?: ethers.Signer | DeployContractOptions
): Promise<Contracts.ECDSA>;
deployContract(
name: "MessageHashUtils",
signerOrOptions?: ethers.Signer | DeployContractOptions
): Promise<Contracts.MessageHashUtils>;
deployContract(
name: "ERC165",
signerOrOptions?: ethers.Signer | DeployContractOptions
@@ -269,11 +256,6 @@ declare module "hardhat/types/runtime" {
args: any[],
signerOrOptions?: ethers.Signer | DeployContractOptions
): Promise<Contracts.ECDSA>;
deployContract(
name: "MessageHashUtils",
args: any[],
signerOrOptions?: ethers.Signer | DeployContractOptions
): Promise<Contracts.MessageHashUtils>;
deployContract(
name: "ERC165",
args: any[],

View File

@@ -24,8 +24,6 @@ export type { IERC20 } from "./@openzeppelin/contracts/token/ERC20/IERC20";
export { IERC20__factory } from "./factories/@openzeppelin/contracts/token/ERC20/IERC20__factory";
export type { ECDSA } from "./@openzeppelin/contracts/utils/cryptography/ECDSA";
export { ECDSA__factory } from "./factories/@openzeppelin/contracts/utils/cryptography/ECDSA__factory";
export type { MessageHashUtils } from "./@openzeppelin/contracts/utils/cryptography/MessageHashUtils";
export { MessageHashUtils__factory } from "./factories/@openzeppelin/contracts/utils/cryptography/MessageHashUtils__factory";
export type { ERC165 } from "./@openzeppelin/contracts/utils/introspection/ERC165";
export { ERC165__factory } from "./factories/@openzeppelin/contracts/utils/introspection/ERC165__factory";
export type { IERC165 } from "./@openzeppelin/contracts/utils/introspection/IERC165";

View File

@@ -0,0 +1,474 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, AddressLike, ContractRunner, ContractMethod, Listener } from "ethers"
import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "./common.js"
export interface AITokenInterface extends Interface {
getFunction(nameOrSignature: "ATTESTOR_ROLE" | "COORDINATOR_ROLE" | "DEFAULT_ADMIN_ROLE" | "allowance" | "approve" | "balanceOf" | "consumedReceipts" | "decimals" | "getRoleAdmin" | "grantRole" | "hasRole" | "mintDigest" | "mintWithReceipt" | "name" | "renounceRole" | "revokeRole" | "supportsInterface" | "symbol" | "totalSupply" | "transfer" | "transferFrom"): FunctionFragment;
getEvent(nameOrSignatureOrTopic: "Approval" | "ReceiptConsumed" | "RoleAdminChanged" | "RoleGranted" | "RoleRevoked" | "Transfer"): EventFragment;
encodeFunctionData(functionFragment: 'ATTESTOR_ROLE', values?: undefined): string;
encodeFunctionData(functionFragment: 'COORDINATOR_ROLE', values?: undefined): string;
encodeFunctionData(functionFragment: 'DEFAULT_ADMIN_ROLE', values?: undefined): string;
encodeFunctionData(functionFragment: 'allowance', values: [AddressLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'approve', values: [AddressLike, BigNumberish]): string;
encodeFunctionData(functionFragment: 'balanceOf', values: [AddressLike]): string;
encodeFunctionData(functionFragment: 'consumedReceipts', values: [BytesLike]): string;
encodeFunctionData(functionFragment: 'decimals', values?: undefined): string;
encodeFunctionData(functionFragment: 'getRoleAdmin', values: [BytesLike]): string;
encodeFunctionData(functionFragment: 'grantRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'hasRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'mintDigest', values: [AddressLike, BigNumberish, BytesLike]): string;
encodeFunctionData(functionFragment: 'mintWithReceipt', values: [AddressLike, BigNumberish, BytesLike, BytesLike]): string;
encodeFunctionData(functionFragment: 'name', values?: undefined): string;
encodeFunctionData(functionFragment: 'renounceRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'revokeRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'supportsInterface', values: [BytesLike]): string;
encodeFunctionData(functionFragment: 'symbol', values?: undefined): string;
encodeFunctionData(functionFragment: 'totalSupply', values?: undefined): string;
encodeFunctionData(functionFragment: 'transfer', values: [AddressLike, BigNumberish]): string;
encodeFunctionData(functionFragment: 'transferFrom', values: [AddressLike, AddressLike, BigNumberish]): string;
decodeFunctionResult(functionFragment: 'ATTESTOR_ROLE', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'COORDINATOR_ROLE', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'DEFAULT_ADMIN_ROLE', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'allowance', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'approve', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'balanceOf', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'consumedReceipts', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'decimals', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'getRoleAdmin', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'grantRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'hasRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'mintDigest', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'mintWithReceipt', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'name', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'renounceRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'revokeRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'supportsInterface', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'symbol', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'totalSupply', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'transfer', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'transferFrom', data: BytesLike): Result;
}
export namespace ApprovalEvent {
export type InputTuple = [owner: AddressLike, spender: AddressLike, value: BigNumberish];
export type OutputTuple = [owner: string, spender: string, value: bigint];
export interface OutputObject {owner: string, spender: string, value: bigint };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace ReceiptConsumedEvent {
export type InputTuple = [receiptHash: BytesLike, provider: AddressLike, units: BigNumberish, attestor: AddressLike];
export type OutputTuple = [receiptHash: string, provider: string, units: bigint, attestor: string];
export interface OutputObject {receiptHash: string, provider: string, units: bigint, attestor: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace RoleAdminChangedEvent {
export type InputTuple = [role: BytesLike, previousAdminRole: BytesLike, newAdminRole: BytesLike];
export type OutputTuple = [role: string, previousAdminRole: string, newAdminRole: string];
export interface OutputObject {role: string, previousAdminRole: string, newAdminRole: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace RoleGrantedEvent {
export type InputTuple = [role: BytesLike, account: AddressLike, sender: AddressLike];
export type OutputTuple = [role: string, account: string, sender: string];
export interface OutputObject {role: string, account: string, sender: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace RoleRevokedEvent {
export type InputTuple = [role: BytesLike, account: AddressLike, sender: AddressLike];
export type OutputTuple = [role: string, account: string, sender: string];
export interface OutputObject {role: string, account: string, sender: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace TransferEvent {
export type InputTuple = [from: AddressLike, to: AddressLike, value: BigNumberish];
export type OutputTuple = [from: string, to: string, value: bigint];
export interface OutputObject {from: string, to: string, value: bigint };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export interface AIToken extends BaseContract {
connect(runner?: ContractRunner | null): AIToken;
waitForDeployment(): Promise<this>;
interface: AITokenInterface;
queryFilter<TCEvent extends TypedContractEvent>(
event: TCEvent,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined,
): Promise<Array<TypedEventLog<TCEvent>>>
queryFilter<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TypedEventLog<TCEvent>>>;
on<TCEvent extends TypedContractEvent>(event: TCEvent, listener: TypedListener<TCEvent>): Promise<this>
on<TCEvent extends TypedContractEvent>(filter: TypedDeferredTopicFilter<TCEvent>, listener: TypedListener<TCEvent>): Promise<this>
once<TCEvent extends TypedContractEvent>(event: TCEvent, listener: TypedListener<TCEvent>): Promise<this>
once<TCEvent extends TypedContractEvent>(filter: TypedDeferredTopicFilter<TCEvent>, listener: TypedListener<TCEvent>): Promise<this>
listeners<TCEvent extends TypedContractEvent>(
event: TCEvent
): Promise<Array<TypedListener<TCEvent>>>;
listeners(eventName?: string): Promise<Array<Listener>>
removeAllListeners<TCEvent extends TypedContractEvent>(event?: TCEvent): Promise<this>
ATTESTOR_ROLE: TypedContractMethod<
[],
[string],
'view'
>
COORDINATOR_ROLE: TypedContractMethod<
[],
[string],
'view'
>
DEFAULT_ADMIN_ROLE: TypedContractMethod<
[],
[string],
'view'
>
allowance: TypedContractMethod<
[owner: AddressLike, spender: AddressLike, ],
[bigint],
'view'
>
approve: TypedContractMethod<
[spender: AddressLike, value: BigNumberish, ],
[boolean],
'nonpayable'
>
balanceOf: TypedContractMethod<
[account: AddressLike, ],
[bigint],
'view'
>
consumedReceipts: TypedContractMethod<
[arg0: BytesLike, ],
[boolean],
'view'
>
decimals: TypedContractMethod<
[],
[bigint],
'view'
>
getRoleAdmin: TypedContractMethod<
[role: BytesLike, ],
[string],
'view'
>
grantRole: TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>
hasRole: TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[boolean],
'view'
>
mintDigest: TypedContractMethod<
[provider: AddressLike, units: BigNumberish, receiptHash: BytesLike, ],
[string],
'view'
>
mintWithReceipt: TypedContractMethod<
[provider: AddressLike, units: BigNumberish, receiptHash: BytesLike, signature: BytesLike, ],
[void],
'nonpayable'
>
name: TypedContractMethod<
[],
[string],
'view'
>
renounceRole: TypedContractMethod<
[role: BytesLike, callerConfirmation: AddressLike, ],
[void],
'nonpayable'
>
revokeRole: TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>
supportsInterface: TypedContractMethod<
[interfaceId: BytesLike, ],
[boolean],
'view'
>
symbol: TypedContractMethod<
[],
[string],
'view'
>
totalSupply: TypedContractMethod<
[],
[bigint],
'view'
>
transfer: TypedContractMethod<
[to: AddressLike, value: BigNumberish, ],
[boolean],
'nonpayable'
>
transferFrom: TypedContractMethod<
[from: AddressLike, to: AddressLike, value: BigNumberish, ],
[boolean],
'nonpayable'
>
getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T;
getFunction(nameOrSignature: 'ATTESTOR_ROLE'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'COORDINATOR_ROLE'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'DEFAULT_ADMIN_ROLE'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'allowance'): TypedContractMethod<
[owner: AddressLike, spender: AddressLike, ],
[bigint],
'view'
>;
getFunction(nameOrSignature: 'approve'): TypedContractMethod<
[spender: AddressLike, value: BigNumberish, ],
[boolean],
'nonpayable'
>;
getFunction(nameOrSignature: 'balanceOf'): TypedContractMethod<
[account: AddressLike, ],
[bigint],
'view'
>;
getFunction(nameOrSignature: 'consumedReceipts'): TypedContractMethod<
[arg0: BytesLike, ],
[boolean],
'view'
>;
getFunction(nameOrSignature: 'decimals'): TypedContractMethod<
[],
[bigint],
'view'
>;
getFunction(nameOrSignature: 'getRoleAdmin'): TypedContractMethod<
[role: BytesLike, ],
[string],
'view'
>;
getFunction(nameOrSignature: 'grantRole'): TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'hasRole'): TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[boolean],
'view'
>;
getFunction(nameOrSignature: 'mintDigest'): TypedContractMethod<
[provider: AddressLike, units: BigNumberish, receiptHash: BytesLike, ],
[string],
'view'
>;
getFunction(nameOrSignature: 'mintWithReceipt'): TypedContractMethod<
[provider: AddressLike, units: BigNumberish, receiptHash: BytesLike, signature: BytesLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'name'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'renounceRole'): TypedContractMethod<
[role: BytesLike, callerConfirmation: AddressLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'revokeRole'): TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'supportsInterface'): TypedContractMethod<
[interfaceId: BytesLike, ],
[boolean],
'view'
>;
getFunction(nameOrSignature: 'symbol'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'totalSupply'): TypedContractMethod<
[],
[bigint],
'view'
>;
getFunction(nameOrSignature: 'transfer'): TypedContractMethod<
[to: AddressLike, value: BigNumberish, ],
[boolean],
'nonpayable'
>;
getFunction(nameOrSignature: 'transferFrom'): TypedContractMethod<
[from: AddressLike, to: AddressLike, value: BigNumberish, ],
[boolean],
'nonpayable'
>;
getEvent(key: 'Approval'): TypedContractEvent<ApprovalEvent.InputTuple, ApprovalEvent.OutputTuple, ApprovalEvent.OutputObject>;
getEvent(key: 'ReceiptConsumed'): TypedContractEvent<ReceiptConsumedEvent.InputTuple, ReceiptConsumedEvent.OutputTuple, ReceiptConsumedEvent.OutputObject>;
getEvent(key: 'RoleAdminChanged'): TypedContractEvent<RoleAdminChangedEvent.InputTuple, RoleAdminChangedEvent.OutputTuple, RoleAdminChangedEvent.OutputObject>;
getEvent(key: 'RoleGranted'): TypedContractEvent<RoleGrantedEvent.InputTuple, RoleGrantedEvent.OutputTuple, RoleGrantedEvent.OutputObject>;
getEvent(key: 'RoleRevoked'): TypedContractEvent<RoleRevokedEvent.InputTuple, RoleRevokedEvent.OutputTuple, RoleRevokedEvent.OutputObject>;
getEvent(key: 'Transfer'): TypedContractEvent<TransferEvent.InputTuple, TransferEvent.OutputTuple, TransferEvent.OutputObject>;
filters: {
'Approval(address,address,uint256)': TypedContractEvent<ApprovalEvent.InputTuple, ApprovalEvent.OutputTuple, ApprovalEvent.OutputObject>;
Approval: TypedContractEvent<ApprovalEvent.InputTuple, ApprovalEvent.OutputTuple, ApprovalEvent.OutputObject>;
'ReceiptConsumed(bytes32,address,uint256,address)': TypedContractEvent<ReceiptConsumedEvent.InputTuple, ReceiptConsumedEvent.OutputTuple, ReceiptConsumedEvent.OutputObject>;
ReceiptConsumed: TypedContractEvent<ReceiptConsumedEvent.InputTuple, ReceiptConsumedEvent.OutputTuple, ReceiptConsumedEvent.OutputObject>;
'RoleAdminChanged(bytes32,bytes32,bytes32)': TypedContractEvent<RoleAdminChangedEvent.InputTuple, RoleAdminChangedEvent.OutputTuple, RoleAdminChangedEvent.OutputObject>;
RoleAdminChanged: TypedContractEvent<RoleAdminChangedEvent.InputTuple, RoleAdminChangedEvent.OutputTuple, RoleAdminChangedEvent.OutputObject>;
'RoleGranted(bytes32,address,address)': TypedContractEvent<RoleGrantedEvent.InputTuple, RoleGrantedEvent.OutputTuple, RoleGrantedEvent.OutputObject>;
RoleGranted: TypedContractEvent<RoleGrantedEvent.InputTuple, RoleGrantedEvent.OutputTuple, RoleGrantedEvent.OutputObject>;
'RoleRevoked(bytes32,address,address)': TypedContractEvent<RoleRevokedEvent.InputTuple, RoleRevokedEvent.OutputTuple, RoleRevokedEvent.OutputObject>;
RoleRevoked: TypedContractEvent<RoleRevokedEvent.InputTuple, RoleRevokedEvent.OutputTuple, RoleRevokedEvent.OutputObject>;
'Transfer(address,address,uint256)': TypedContractEvent<TransferEvent.InputTuple, TransferEvent.OutputTuple, TransferEvent.OutputObject>;
Transfer: TypedContractEvent<TransferEvent.InputTuple, TransferEvent.OutputTuple, TransferEvent.OutputObject>;
};
}

View File

@@ -0,0 +1,329 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type { BaseContract, BigNumberish, BytesLike, FunctionFragment, Result, Interface, EventFragment, AddressLike, ContractRunner, ContractMethod, Listener } from "ethers"
import type { TypedContractEvent, TypedDeferredTopicFilter, TypedEventLog, TypedLogDescription, TypedListener, TypedContractMethod } from "./common.js"
export declare namespace AITokenRegistry {
export type ProviderInfoStruct = {active: boolean, collateral: BigNumberish}
export type ProviderInfoStructOutput = [active: boolean, collateral: bigint] & {active: boolean, collateral: bigint }
}
export interface AITokenRegistryInterface extends Interface {
getFunction(nameOrSignature: "COORDINATOR_ROLE" | "DEFAULT_ADMIN_ROLE" | "getRoleAdmin" | "grantRole" | "hasRole" | "providerInfo" | "providers" | "registerProvider" | "renounceRole" | "revokeRole" | "supportsInterface" | "updateProvider"): FunctionFragment;
getEvent(nameOrSignatureOrTopic: "ProviderRegistered" | "ProviderUpdated" | "RoleAdminChanged" | "RoleGranted" | "RoleRevoked"): EventFragment;
encodeFunctionData(functionFragment: 'COORDINATOR_ROLE', values?: undefined): string;
encodeFunctionData(functionFragment: 'DEFAULT_ADMIN_ROLE', values?: undefined): string;
encodeFunctionData(functionFragment: 'getRoleAdmin', values: [BytesLike]): string;
encodeFunctionData(functionFragment: 'grantRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'hasRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'providerInfo', values: [AddressLike]): string;
encodeFunctionData(functionFragment: 'providers', values: [AddressLike]): string;
encodeFunctionData(functionFragment: 'registerProvider', values: [AddressLike, BigNumberish]): string;
encodeFunctionData(functionFragment: 'renounceRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'revokeRole', values: [BytesLike, AddressLike]): string;
encodeFunctionData(functionFragment: 'supportsInterface', values: [BytesLike]): string;
encodeFunctionData(functionFragment: 'updateProvider', values: [AddressLike, boolean, BigNumberish]): string;
decodeFunctionResult(functionFragment: 'COORDINATOR_ROLE', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'DEFAULT_ADMIN_ROLE', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'getRoleAdmin', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'grantRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'hasRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'providerInfo', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'providers', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'registerProvider', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'renounceRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'revokeRole', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'supportsInterface', data: BytesLike): Result;
decodeFunctionResult(functionFragment: 'updateProvider', data: BytesLike): Result;
}
export namespace ProviderRegisteredEvent {
export type InputTuple = [provider: AddressLike, collateral: BigNumberish];
export type OutputTuple = [provider: string, collateral: bigint];
export interface OutputObject {provider: string, collateral: bigint };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace ProviderUpdatedEvent {
export type InputTuple = [provider: AddressLike, active: boolean, collateral: BigNumberish];
export type OutputTuple = [provider: string, active: boolean, collateral: bigint];
export interface OutputObject {provider: string, active: boolean, collateral: bigint };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace RoleAdminChangedEvent {
export type InputTuple = [role: BytesLike, previousAdminRole: BytesLike, newAdminRole: BytesLike];
export type OutputTuple = [role: string, previousAdminRole: string, newAdminRole: string];
export interface OutputObject {role: string, previousAdminRole: string, newAdminRole: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace RoleGrantedEvent {
export type InputTuple = [role: BytesLike, account: AddressLike, sender: AddressLike];
export type OutputTuple = [role: string, account: string, sender: string];
export interface OutputObject {role: string, account: string, sender: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export namespace RoleRevokedEvent {
export type InputTuple = [role: BytesLike, account: AddressLike, sender: AddressLike];
export type OutputTuple = [role: string, account: string, sender: string];
export interface OutputObject {role: string, account: string, sender: string };
export type Event = TypedContractEvent<InputTuple, OutputTuple, OutputObject>
export type Filter = TypedDeferredTopicFilter<Event>
export type Log = TypedEventLog<Event>
export type LogDescription = TypedLogDescription<Event>
}
export interface AITokenRegistry extends BaseContract {
connect(runner?: ContractRunner | null): AITokenRegistry;
waitForDeployment(): Promise<this>;
interface: AITokenRegistryInterface;
queryFilter<TCEvent extends TypedContractEvent>(
event: TCEvent,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined,
): Promise<Array<TypedEventLog<TCEvent>>>
queryFilter<TCEvent extends TypedContractEvent>(
filter: TypedDeferredTopicFilter<TCEvent>,
fromBlockOrBlockhash?: string | number | undefined,
toBlock?: string | number | undefined
): Promise<Array<TypedEventLog<TCEvent>>>;
on<TCEvent extends TypedContractEvent>(event: TCEvent, listener: TypedListener<TCEvent>): Promise<this>
on<TCEvent extends TypedContractEvent>(filter: TypedDeferredTopicFilter<TCEvent>, listener: TypedListener<TCEvent>): Promise<this>
once<TCEvent extends TypedContractEvent>(event: TCEvent, listener: TypedListener<TCEvent>): Promise<this>
once<TCEvent extends TypedContractEvent>(filter: TypedDeferredTopicFilter<TCEvent>, listener: TypedListener<TCEvent>): Promise<this>
listeners<TCEvent extends TypedContractEvent>(
event: TCEvent
): Promise<Array<TypedListener<TCEvent>>>;
listeners(eventName?: string): Promise<Array<Listener>>
removeAllListeners<TCEvent extends TypedContractEvent>(event?: TCEvent): Promise<this>
COORDINATOR_ROLE: TypedContractMethod<
[],
[string],
'view'
>
DEFAULT_ADMIN_ROLE: TypedContractMethod<
[],
[string],
'view'
>
getRoleAdmin: TypedContractMethod<
[role: BytesLike, ],
[string],
'view'
>
grantRole: TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>
hasRole: TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[boolean],
'view'
>
providerInfo: TypedContractMethod<
[provider: AddressLike, ],
[AITokenRegistry.ProviderInfoStructOutput],
'view'
>
providers: TypedContractMethod<
[arg0: AddressLike, ],
[[boolean, bigint] & {active: boolean, collateral: bigint }],
'view'
>
registerProvider: TypedContractMethod<
[provider: AddressLike, collateral: BigNumberish, ],
[void],
'nonpayable'
>
renounceRole: TypedContractMethod<
[role: BytesLike, callerConfirmation: AddressLike, ],
[void],
'nonpayable'
>
revokeRole: TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>
supportsInterface: TypedContractMethod<
[interfaceId: BytesLike, ],
[boolean],
'view'
>
updateProvider: TypedContractMethod<
[provider: AddressLike, active: boolean, collateral: BigNumberish, ],
[void],
'nonpayable'
>
getFunction<T extends ContractMethod = ContractMethod>(key: string | FunctionFragment): T;
getFunction(nameOrSignature: 'COORDINATOR_ROLE'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'DEFAULT_ADMIN_ROLE'): TypedContractMethod<
[],
[string],
'view'
>;
getFunction(nameOrSignature: 'getRoleAdmin'): TypedContractMethod<
[role: BytesLike, ],
[string],
'view'
>;
getFunction(nameOrSignature: 'grantRole'): TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'hasRole'): TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[boolean],
'view'
>;
getFunction(nameOrSignature: 'providerInfo'): TypedContractMethod<
[provider: AddressLike, ],
[AITokenRegistry.ProviderInfoStructOutput],
'view'
>;
getFunction(nameOrSignature: 'providers'): TypedContractMethod<
[arg0: AddressLike, ],
[[boolean, bigint] & {active: boolean, collateral: bigint }],
'view'
>;
getFunction(nameOrSignature: 'registerProvider'): TypedContractMethod<
[provider: AddressLike, collateral: BigNumberish, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'renounceRole'): TypedContractMethod<
[role: BytesLike, callerConfirmation: AddressLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'revokeRole'): TypedContractMethod<
[role: BytesLike, account: AddressLike, ],
[void],
'nonpayable'
>;
getFunction(nameOrSignature: 'supportsInterface'): TypedContractMethod<
[interfaceId: BytesLike, ],
[boolean],
'view'
>;
getFunction(nameOrSignature: 'updateProvider'): TypedContractMethod<
[provider: AddressLike, active: boolean, collateral: BigNumberish, ],
[void],
'nonpayable'
>;
getEvent(key: 'ProviderRegistered'): TypedContractEvent<ProviderRegisteredEvent.InputTuple, ProviderRegisteredEvent.OutputTuple, ProviderRegisteredEvent.OutputObject>;
getEvent(key: 'ProviderUpdated'): TypedContractEvent<ProviderUpdatedEvent.InputTuple, ProviderUpdatedEvent.OutputTuple, ProviderUpdatedEvent.OutputObject>;
getEvent(key: 'RoleAdminChanged'): TypedContractEvent<RoleAdminChangedEvent.InputTuple, RoleAdminChangedEvent.OutputTuple, RoleAdminChangedEvent.OutputObject>;
getEvent(key: 'RoleGranted'): TypedContractEvent<RoleGrantedEvent.InputTuple, RoleGrantedEvent.OutputTuple, RoleGrantedEvent.OutputObject>;
getEvent(key: 'RoleRevoked'): TypedContractEvent<RoleRevokedEvent.InputTuple, RoleRevokedEvent.OutputTuple, RoleRevokedEvent.OutputObject>;
filters: {
'ProviderRegistered(address,uint256)': TypedContractEvent<ProviderRegisteredEvent.InputTuple, ProviderRegisteredEvent.OutputTuple, ProviderRegisteredEvent.OutputObject>;
ProviderRegistered: TypedContractEvent<ProviderRegisteredEvent.InputTuple, ProviderRegisteredEvent.OutputTuple, ProviderRegisteredEvent.OutputObject>;
'ProviderUpdated(address,bool,uint256)': TypedContractEvent<ProviderUpdatedEvent.InputTuple, ProviderUpdatedEvent.OutputTuple, ProviderUpdatedEvent.OutputObject>;
ProviderUpdated: TypedContractEvent<ProviderUpdatedEvent.InputTuple, ProviderUpdatedEvent.OutputTuple, ProviderUpdatedEvent.OutputObject>;
'RoleAdminChanged(bytes32,bytes32,bytes32)': TypedContractEvent<RoleAdminChangedEvent.InputTuple, RoleAdminChangedEvent.OutputTuple, RoleAdminChangedEvent.OutputObject>;
RoleAdminChanged: TypedContractEvent<RoleAdminChangedEvent.InputTuple, RoleAdminChangedEvent.OutputTuple, RoleAdminChangedEvent.OutputObject>;
'RoleGranted(bytes32,address,address)': TypedContractEvent<RoleGrantedEvent.InputTuple, RoleGrantedEvent.OutputTuple, RoleGrantedEvent.OutputObject>;
RoleGranted: TypedContractEvent<RoleGrantedEvent.InputTuple, RoleGrantedEvent.OutputTuple, RoleGrantedEvent.OutputObject>;
'RoleRevoked(bytes32,address,address)': TypedContractEvent<RoleRevokedEvent.InputTuple, RoleRevokedEvent.OutputTuple, RoleRevokedEvent.OutputObject>;
RoleRevoked: TypedContractEvent<RoleRevokedEvent.InputTuple, RoleRevokedEvent.OutputTuple, RoleRevokedEvent.OutputObject>;
};
}

View File

@@ -0,0 +1,92 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type {
FunctionFragment,
Typed,
EventFragment,
ContractTransaction,
ContractTransactionResponse,
DeferredTopicFilter,
EventLog,
TransactionRequest,
LogDescription,
} from 'ethers'
export interface TypedDeferredTopicFilter<_TCEvent extends TypedContractEvent> extends DeferredTopicFilter {}
export interface TypedContractEvent<
InputTuple extends Array<any> = any,
OutputTuple extends Array<any> = any,
OutputObject = any,
> {
(...args: Partial<InputTuple>): TypedDeferredTopicFilter<TypedContractEvent<InputTuple, OutputTuple, OutputObject>>
name: string
fragment: EventFragment
getFragment(...args: Partial<InputTuple>): EventFragment
}
type __TypechainAOutputTuple<T> = T extends TypedContractEvent<infer _U, infer W> ? W : never
type __TypechainOutputObject<T> = T extends TypedContractEvent<infer _U, infer _W, infer V> ? V : never
export interface TypedEventLog<TCEvent extends TypedContractEvent> extends Omit<EventLog, 'args'> {
args: __TypechainAOutputTuple<TCEvent> & __TypechainOutputObject<TCEvent>
}
export interface TypedLogDescription<TCEvent extends TypedContractEvent> extends Omit<LogDescription, 'args'> {
args: __TypechainAOutputTuple<TCEvent> & __TypechainOutputObject<TCEvent>
}
export type TypedListener<TCEvent extends TypedContractEvent> = (
...listenerArg: [...__TypechainAOutputTuple<TCEvent>, TypedEventLog<TCEvent>, ...undefined[]]
) => void
export type MinEthersFactory<C, ARGS> = {
deploy(...a: ARGS[]): Promise<C>
}
export type GetContractTypeFromFactory<F> = F extends MinEthersFactory<infer C, any> ? C : never
export type GetARGsTypeFromFactory<F> = F extends MinEthersFactory<any, any> ? Parameters<F['deploy']> : never
export type StateMutability = 'nonpayable' | 'payable' | 'view'
export type BaseOverrides = Omit<TransactionRequest, 'to' | 'data'>
export type NonPayableOverrides = Omit<BaseOverrides, 'value' | 'blockTag' | 'enableCcipRead'>
export type PayableOverrides = Omit<BaseOverrides, 'blockTag' | 'enableCcipRead'>
export type ViewOverrides = Omit<TransactionRequest, 'to' | 'data'>
export type Overrides<S extends StateMutability> = S extends 'nonpayable'
? NonPayableOverrides
: S extends 'payable'
? PayableOverrides
: ViewOverrides
export type PostfixOverrides<A extends Array<any>, S extends StateMutability> = A | [...A, Overrides<S>]
export type ContractMethodArgs<A extends Array<any>, S extends StateMutability> = PostfixOverrides<
{ [I in keyof A]-?: A[I] | Typed },
S
>
export type DefaultReturnType<R> = R extends Array<any> ? R[0] : R
// export interface ContractMethod<A extends Array<any> = Array<any>, R = any, D extends R | ContractTransactionResponse = R | ContractTransactionResponse> {
export interface TypedContractMethod<
A extends Array<any> = Array<any>,
R = any,
S extends StateMutability = 'payable',
> {
(...args: ContractMethodArgs<A, S>): S extends 'view'
? Promise<DefaultReturnType<R>>
: Promise<ContractTransactionResponse>
name: string
fragment: FunctionFragment
getFragment(...args: ContractMethodArgs<A, S>): FunctionFragment
populateTransaction(...args: ContractMethodArgs<A, S>): Promise<ContractTransaction>
staticCall(...args: ContractMethodArgs<A, 'view'>): Promise<DefaultReturnType<R>>
send(...args: ContractMethodArgs<A, S>): Promise<ContractTransactionResponse>
estimateGas(...args: ContractMethodArgs<A, S>): Promise<bigint>
staticCallResult(...args: ContractMethodArgs<A, 'view'>): Promise<R>
}

View File

@@ -0,0 +1,450 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import type { Addressable } from "ethers";
import { Contract, ContractFactory, ContractTransactionResponse, Interface } from "ethers"
import type { Signer, AddressLike, ContractDeployTransaction, ContractRunner } from "ethers"
import type { NonPayableOverrides } from "../common.js"
import type { AITokenRegistry, AITokenRegistryInterface } from "../AITokenRegistry.js";
const _abi = [
{
"inputs": [
{
"internalType": "address",
"name": "admin",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "AccessControlBadConfirmation",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "account",
"type": "address"
},
{
"internalType": "bytes32",
"name": "neededRole",
"type": "bytes32"
}
],
"name": "AccessControlUnauthorizedAccount",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "provider",
"type": "address"
},
{
"indexed": false,
"internalType": "uint256",
"name": "collateral",
"type": "uint256"
}
],
"name": "ProviderRegistered",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "provider",
"type": "address"
},
{
"indexed": false,
"internalType": "bool",
"name": "active",
"type": "bool"
},
{
"indexed": false,
"internalType": "uint256",
"name": "collateral",
"type": "uint256"
}
],
"name": "ProviderUpdated",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "previousAdminRole",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "bytes32",
"name": "newAdminRole",
"type": "bytes32"
}
],
"name": "RoleAdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleGranted",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"indexed": true,
"internalType": "address",
"name": "account",
"type": "address"
},
{
"indexed": true,
"internalType": "address",
"name": "sender",
"type": "address"
}
],
"name": "RoleRevoked",
"type": "event"
},
{
"inputs": [],
"name": "COORDINATOR_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "DEFAULT_ADMIN_ROLE",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
}
],
"name": "getRoleAdmin",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "grantRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "hasRole",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "provider",
"type": "address"
}
],
"name": "providerInfo",
"outputs": [
{
"components": [
{
"internalType": "bool",
"name": "active",
"type": "bool"
},
{
"internalType": "uint256",
"name": "collateral",
"type": "uint256"
}
],
"internalType": "struct AITokenRegistry.ProviderInfo",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "providers",
"outputs": [
{
"internalType": "bool",
"name": "active",
"type": "bool"
},
{
"internalType": "uint256",
"name": "collateral",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "provider",
"type": "address"
},
{
"internalType": "uint256",
"name": "collateral",
"type": "uint256"
}
],
"name": "registerProvider",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "callerConfirmation",
"type": "address"
}
],
"name": "renounceRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes32",
"name": "role",
"type": "bytes32"
},
{
"internalType": "address",
"name": "account",
"type": "address"
}
],
"name": "revokeRole",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "bytes4",
"name": "interfaceId",
"type": "bytes4"
}
],
"name": "supportsInterface",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "provider",
"type": "address"
},
{
"internalType": "bool",
"name": "active",
"type": "bool"
},
{
"internalType": "uint256",
"name": "collateral",
"type": "uint256"
}
],
"name": "updateProvider",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
] as const;
const _bytecode = "0x608060405234801561000f575f80fd5b506040516109a13803806109a183398101604081905261002e916100e8565b6100385f8261003f565b5050610115565b5f828152602081815260408083206001600160a01b038516845290915281205460ff166100df575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556100973390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016100e2565b505f5b92915050565b5f602082840312156100f8575f80fd5b81516001600160a01b038116811461010e575f80fd5b9392505050565b61087f806101225f395ff3fe608060405234801561000f575f80fd5b50600436106100b1575f3560e01c80633ae259161161006e5780633ae259161461018b5780636b366cb51461020057806391d1485414610227578063a217fddf1461023a578063d119056514610241578063d547741f14610254575f80fd5b806301ffc9a7146100b55780630787bc27146100dd5780631af431a714610120578063248a9ca3146101355780632f2ff15d1461016557806336568abe14610178575b5f80fd5b6100c86100c336600461073e565b610267565b60405190151581526020015b60405180910390f35b6101096100eb366004610787565b600160208190525f9182526040909120805491015460ff9091169082565b6040805192151583526020830191909152016100d4565b61013361012e3660046107a0565b61029d565b005b6101576101433660046107c8565b5f9081526020819052604090206001015490565b6040519081526020016100d4565b6101336101733660046107df565b6103e9565b6101336101863660046107df565b610413565b6101e3610199366004610787565b604080518082019091525f8082526020820152506001600160a01b03165f908152600160208181526040928390208351808501909452805460ff1615158452909101549082015290565b6040805182511515815260209283015192810192909252016100d4565b6101577f2e8b98eef02e8df3bd27d1270ded3bea3d14db99c5234c7b14001a7fff957bcc81565b6100c86102353660046107df565b61044b565b6101575f81565b61013361024f366004610809565b610473565b6101336102623660046107df565b6105d8565b5f6001600160e01b03198216637965db0b60e01b148061029757506301ffc9a760e01b6001600160e01b03198316145b92915050565b7f2e8b98eef02e8df3bd27d1270ded3bea3d14db99c5234c7b14001a7fff957bcc6102c7816105fc565b6001600160a01b0383166103155760405162461bcd60e51b815260206004820152601060248201526f34b73b30b634b210383937bb34b232b960811b60448201526064015b60405180910390fd5b6001600160a01b0383165f9081526001602052604090205460ff16156103725760405162461bcd60e51b8152602060048201526012602482015271185b1c9958591e481c9959da5cdd195c995960721b604482015260640161030c565b604080518082018252600180825260208083018681526001600160a01b0388165f8181528484528690209451855460ff19169015151785559051939092019290925591518481527f90c9734131c1e4fb36cde2d71e6feb93fb258f71be8a85411c173d25e1516e80910160405180910390a2505050565b5f82815260208190526040902060010154610403816105fc565b61040d8383610609565b50505050565b6001600160a01b038116331461043c5760405163334bd91960e11b815260040160405180910390fd5b6104468282610698565b505050565b5f918252602082815260408084206001600160a01b0393909316845291905290205460ff1690565b7f2e8b98eef02e8df3bd27d1270ded3bea3d14db99c5234c7b14001a7fff957bcc61049d816105fc565b6001600160a01b0384166104e65760405162461bcd60e51b815260206004820152601060248201526f34b73b30b634b210383937bb34b232b960811b604482015260640161030c565b6001600160a01b0384165f9081526001602052604090205460ff16806105095750825b6105555760405162461bcd60e51b815260206004820152601760248201527f70726f7669646572206e6f742072656769737465726564000000000000000000604482015260640161030c565b60408051808201825284151580825260208083018681526001600160a01b0389165f8181526001808552908790209551865460ff1916901515178655915194909101939093558351918252810185905290917fe226f4be7d881611b5a3ddc83f2e771728014b8012359a29890cd3d670c43dc8910160405180910390a250505050565b5f828152602081905260409020600101546105f2816105fc565b61040d8383610698565b6106068133610701565b50565b5f610614838361044b565b610691575f838152602081815260408083206001600160a01b03861684529091529020805460ff191660011790556106493390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610297565b505f610297565b5f6106a3838361044b565b15610691575f838152602081815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610297565b61070b828261044b565b61073a5760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440161030c565b5050565b5f6020828403121561074e575f80fd5b81356001600160e01b031981168114610765575f80fd5b9392505050565b80356001600160a01b0381168114610782575f80fd5b919050565b5f60208284031215610797575f80fd5b6107658261076c565b5f80604083850312156107b1575f80fd5b6107ba8361076c565b946020939093013593505050565b5f602082840312156107d8575f80fd5b5035919050565b5f80604083850312156107f0575f80fd5b823591506108006020840161076c565b90509250929050565b5f805f6060848603121561081b575f80fd5b6108248461076c565b925060208401358015158114610838575f80fd5b92959294505050604091909101359056fea26469706673582212201777f6e8fbdbbc1162afca135af6f0ea80738b2c91d95d3ba599ee9b7f5111c264736f6c63430008190033";
type AITokenRegistryConstructorParams = [signer?: Signer] | ConstructorParameters<typeof ContractFactory>;
const isSuperArgs = (xs: AITokenRegistryConstructorParams): xs is ConstructorParameters<typeof ContractFactory> =>
xs.length > 1
export class AITokenRegistry__factory extends ContractFactory {
constructor(...args: AITokenRegistryConstructorParams) {
if (isSuperArgs(args)) {
super(...args);
} else {
super(_abi, _bytecode, args[0]);
}
}
override getDeployTransaction(admin: AddressLike, overrides?: NonPayableOverrides & { from?: string }): Promise<ContractDeployTransaction> {
return super.getDeployTransaction(admin, overrides || {});
};
override deploy(admin: AddressLike, overrides?: NonPayableOverrides & { from?: string }) {
return super.deploy(admin, overrides || {}) as Promise<AITokenRegistry & {
deploymentTransaction(): ContractTransactionResponse;
}>;
}
override connect(runner: ContractRunner | null): AITokenRegistry__factory {
return super.connect(runner) as AITokenRegistry__factory;
}
static readonly bytecode = _bytecode;
static readonly abi = _abi;
static createInterface(): AITokenRegistryInterface {
return new Interface(_abi) as AITokenRegistryInterface;
}
override attach(address: string | Addressable): AITokenRegistry {
return super.attach(address) as AITokenRegistry;
}
static connect(address: string, runner?: ContractRunner | null): AITokenRegistry {
return new Contract(address, _abi, runner) as unknown as AITokenRegistry;
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
export { AIToken__factory } from './AIToken__factory.js';
export { AITokenRegistry__factory } from './AITokenRegistry__factory.js';

View File

@@ -0,0 +1,51 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
import { ethers } from 'ethers'
import { DeployContractOptions, FactoryOptions, HardhatEthersHelpers as HardhatEthersHelpersBase} from "@nomicfoundation/hardhat-ethers/types";
import * as Contracts from "./index.js";
declare module "@nomicfoundation/hardhat-ethers/types" {
interface HardhatEthersHelpers extends HardhatEthersHelpersBase {
getContractFactory(name: 'AIToken', signerOrOptions?: ethers.Signer | FactoryOptions): Promise<Contracts.AIToken__factory>
getContractFactory(name: 'AITokenRegistry', signerOrOptions?: ethers.Signer | FactoryOptions): Promise<Contracts.AITokenRegistry__factory>
getContractAt(name: 'AIToken', address: string | ethers.Addressable, signer?: ethers.Signer): Promise<Contracts.AIToken>
getContractAt(name: 'AITokenRegistry', address: string | ethers.Addressable, signer?: ethers.Signer): Promise<Contracts.AITokenRegistry>
deployContract(name: 'AIToken', signerOrOptions?: ethers.Signer | DeployContractOptions): Promise<Contracts.AIToken>
deployContract(name: 'AITokenRegistry', signerOrOptions?: ethers.Signer | DeployContractOptions): Promise<Contracts.AITokenRegistry>
deployContract(name: 'AIToken', args: any[], signerOrOptions?: ethers.Signer | DeployContractOptions): Promise<Contracts.AIToken>
deployContract(name: 'AITokenRegistry', args: any[], signerOrOptions?: ethers.Signer | DeployContractOptions): Promise<Contracts.AITokenRegistry>
// default types
getContractFactory(
name: string,
signerOrOptions?: ethers.Signer | FactoryOptions
): Promise<ethers.ContractFactory>;
getContractFactory(
abi: any[],
bytecode: ethers.BytesLike,
signer?: ethers.Signer
): Promise<ethers.ContractFactory>;
getContractAt(
nameOrAbi: string | any[],
address: string | ethers.Addressable,
signer?: ethers.Signer
): Promise<ethers.Contract>;
deployContract(
name: string,
signerOrOptions?: ethers.Signer | DeployContractOptions
): Promise<ethers.Contract>;
deployContract(
name: string,
args: any[],
signerOrOptions?: ethers.Signer | DeployContractOptions
): Promise<ethers.Contract>;
}
}

View File

@@ -0,0 +1,8 @@
/* Autogenerated file. Do not edit manually. */
/* tslint:disable */
/* eslint-disable */
export type { AIToken } from './AIToken.js';
export type { AITokenRegistry } from './AITokenRegistry.js';
export * as factories from './factories/index.js';
export { AIToken__factory } from './factories/AIToken__factory.js';
export { AITokenRegistry__factory } from './factories/AITokenRegistry__factory.js';