Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: update interface and remove ignition module for custom deploy task #73

Merged
merged 4 commits into from
Dec 10, 2024
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
7 changes: 2 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,8 @@ jobs:
- name: "Install the dependencies 📦"
run: "bun install"

- name: "Lint TypeScript 🧹"
run: "bun run lint:ts"

- name: "Lint Solidity 🧹"
run: "bun run lint:sol"
- name: "Lint TypeScript & Solidity 🧹"
run: "bun run check"

- name: "Compile the contracts 🛠️"
run: "bun run compile"
Expand Down
5 changes: 2 additions & 3 deletions contracts/core/abstract/ResultHandlerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ abstract contract ResultHandlerBase is IResultHandler, Initializable {
return _resultHandlerStorage().results[requestId];
}

/// @notice Returns the address of the Seda prover contract
/// @return The address of the Seda prover contract
function getSedaProver() public view returns (address) {
/// @inheritdoc IResultHandler
function getSedaProver() public view override(IResultHandler) returns (address) {
return address(_resultHandlerStorage().sedaProver);
}

Expand Down
8 changes: 6 additions & 2 deletions contracts/interfaces/IResultHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ interface IResultHandler {
function getResult(bytes32 requestId) external view returns (SedaDataTypes.Result memory);

/// @notice Posts a new result with a proof
/// @param inputs The result data to be posted
/// @param result The result data to be posted
/// @param batchHeight The height of the batch the result belongs to
/// @param proof The proof associated with the result
/// @return resultId The unique identifier of the posted result
function postResult(
SedaDataTypes.Result calldata inputs,
SedaDataTypes.Result calldata result,
uint64 batchHeight,
bytes32[] memory proof
) external returns (bytes32);

/// @notice Returns the address of the Seda prover contract
/// @return The address of the Seda prover contract
function getSedaProver() external view returns (address);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";

import {IResultHandler} from "../interfaces/IResultHandler.sol";
import {RequestHandlerBase} from "./abstract/RequestHandlerBase.sol";
import {RequestHandlerBase} from "../core/abstract/RequestHandlerBase.sol";
import {SedaDataTypes} from "../libraries/SedaDataTypes.sol";

/// @title SedaCorePermissioned
/// @notice Core contract for the Seda protocol with permissioned access, managing requests and results
/// @dev Implements RequestHandlerBase, IResultHandler, AccessControl, and Pausable functionalities
contract SedaCorePermissioned is RequestHandlerBase, IResultHandler, AccessControl, Pausable {
/// @dev WARNING: This is a permissioned version of the SEDA core contract, primarily intended for testing
/// and controlled environments. It should not be used in production without careful consideration
/// of the centralization risks introduced by the permissioning system.
contract SedaPermissioned is RequestHandlerBase, IResultHandler, AccessControl, Pausable {
using EnumerableSet for EnumerableSet.Bytes32Set;

// ============ Constants ============
Expand Down Expand Up @@ -81,6 +84,13 @@ contract SedaCorePermissioned is RequestHandlerBase, IResultHandler, AccessContr
return results[requestId];
}

/// @inheritdoc IResultHandler
/// @dev This mock implementation does not use a prover contract, so it returns address(0)
/// @return The zero address (address(0))
function getSedaProver() external pure override(IResultHandler) returns (address) {
return address(0);
}

// ============ Public Functions ============

/// @notice Posts a new request
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Secp256k1ProverV1} from "../provers/Secp256k1ProverV1.sol";
import {Secp256k1ProverV1} from "../../provers/Secp256k1ProverV1.sol";

/// @title MockSecp256k1ProverV2
/// @notice Mock version of Secp256k1Prover for testing purposes
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {SedaCoreV1} from "../core/SedaCoreV1.sol";
import {SedaCoreV1} from "../../core/SedaCoreV1.sol";

/// @title MockSedaCoreV2
/// @notice Mock version of SedaCore for testing purposes
Expand Down
3 changes: 3 additions & 0 deletions deployments/parameters.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@
"resultsRoot": "0x56c4f39b7564ea6a32877fc98743652998753c4cd8a4b455c26dcb3b92774b73",
"provingMetadata": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
},
"SedaPermissioned": {
"maxReplicationFactor": 1
}
}
14 changes: 0 additions & 14 deletions ignition/modules/SedaCorePermissioned.ts

This file was deleted.

5 changes: 0 additions & 5 deletions ignition/modules/parameters.json

This file was deleted.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"check": "bun run lint && bun run format:sol",
"clean": "rimraf artifacts cache typechain-types",
"compile": "hardhat compile",
"deploy:core:permissioned": "hardhat ignition deploy ignition/modules/SedaCorePermissioned.ts --parameters ignition/modules/parameters.json",
"format:sol": "prettier --check \"**/*.sol\"",
"format:sol:fix": "prettier --write \"**/*.sol\"",
"gen:testvectors": "bun scripts/generateTestVectors.ts",
Expand Down
3 changes: 3 additions & 0 deletions tasks/common/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const ParamsSchema = v.object({
provingMetadata: HexString,
}),
}),
SedaPermissioned: v.object({
maxReplicationFactor: v.number(),
}),
});

export async function readParams(filePath: string): Promise<v.InferOutput<typeof ParamsSchema>> {
Expand Down
25 changes: 11 additions & 14 deletions tasks/common/reports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,40 @@ import { path, ensureDirectoryExists, pathExists, readFile, writeFile } from './
const DEPLOYMENTS_FOLDER = CONFIG.DEPLOYMENTS.FOLDER;
const ADDRESSES_FILE = CONFIG.DEPLOYMENTS.FILES.ADDRESSES;

type ProxyAddress = {
proxy: string;
implementation: string;
};

// Define the type for the addresses object
type Addresses = {
type DeploymentAddress = {
[networkName: string]: {
[contractName: string]: {
proxy: string;
implementation: string;
address: ProxyAddress | string;
gitCommitHash: string;
};
};
};

export async function updateAddressesFile(
hre: HardhatRuntimeEnvironment,
contractName: string,
proxyAddress: string,
implAddress: string,
) {
export async function updateAddressesFile(networkName: string, contractName: string, address: ProxyAddress | string) {
const addressesPath = path.join(DEPLOYMENTS_FOLDER, ADDRESSES_FILE);
let addresses: Addresses = {};
let addresses: DeploymentAddress = {};

if (await pathExists(addressesPath)) {
const content = await readFile(addressesPath);
if (content.trim()) {
addresses = JSON.parse(content) as Addresses;
addresses = JSON.parse(content) as DeploymentAddress;
}
}

const networkName = `${hre.network.name}-${(await hre.ethers.provider.getNetwork()).chainId.toString()}`;
if (!addresses[networkName]) {
addresses[networkName] = {};
}

const gitCommitHash = require('node:child_process').execSync('git rev-parse HEAD').toString().trim();

addresses[networkName][contractName] = {
proxy: proxyAddress,
implementation: implAddress,
address,
gitCommitHash,
};

Expand Down
2 changes: 1 addition & 1 deletion tasks/deployCore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export async function deploySedaCore(
// Update deployment files
logger.section('Updating Deployment Files', 'files');
await updateDeployment(hre, contractName);
await updateAddressesFile(hre, contractName, contractAddress, contractImplAddress);
await updateAddressesFile(networkKey, contractName, { proxy: contractAddress, implementation: contractImplAddress });

if (verify) {
logger.section('Verifying Contracts', 'verify');
Expand Down
84 changes: 84 additions & 0 deletions tasks/deployPermissioned.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { HardhatRuntimeEnvironment } from 'hardhat/types';
import { CONFIG } from './common/config';
import { pathExists } from './common/io';
import { prompt } from './common/io';
import { logger } from './common/logger';
import { readParams } from './common/params';
import { updateAddressesFile, updateDeployment } from './common/reports';

export async function deployMock(
hre: HardhatRuntimeEnvironment,
options: {
params?: string;
maxReplicationFactor?: number;
reset?: boolean;
verify?: boolean;
},
): Promise<{ contractAddress: string }> {
const contractName = 'SedaPermissioned';

// Contract Parameter: Replication Factor (1 by default)
logger.section('Contract Parameters', 'params');
let maxReplicationFactor = 1;

if (options.params) {
logger.info(`Using parameters file: ${options.params}`);
const params = await readParams(options.params);
maxReplicationFactor = params.SedaPermissioned.maxReplicationFactor;
} else if (options.maxReplicationFactor) {
maxReplicationFactor = options.maxReplicationFactor;
}
logger.info(`Max Replication Factor: ${maxReplicationFactor}`);

// Configuration
logger.section('Deployment Configuration', 'config');
logger.info(`Contract: ${contractName}`);
logger.info(`Network: ${hre.network.name}`);
logger.info(`Chain ID: ${hre.network.config.chainId}`);
const [owner] = await hre.ethers.getSigners();
const balance = hre.ethers.formatEther(await owner.provider.getBalance(owner.address));
logger.info(`Deployer: ${owner.address} (${balance} ETH)`);

// Deploy
logger.section('Deploying Contracts', 'deploy');
const networkKey = `${hre.network.name}-${hre.network.config.chainId}`;
if (!options.reset && (await pathExists(`${CONFIG.DEPLOYMENTS.FOLDER}/${networkKey}`))) {
const confirmation = await prompt('Deployments folder already exists. Type "yes" to continue: ');
if (confirmation !== 'yes') {
logger.error('Deployment aborted.');
throw new Error('Deployment aborted: User cancelled the operation');
}
}

const factory = await hre.ethers.getContractFactory(contractName);
const contract = await factory.deploy([owner.address], maxReplicationFactor);
await contract.waitForDeployment();

const contractAddress = await contract.getAddress();
logger.success(`Contract address: ${contractAddress}`);

// Update deployment files
logger.section('Updating Deployment Files', 'files');
await updateDeployment(hre, contractName);
await updateAddressesFile(networkKey, contractName, contractAddress);

if (options.verify) {
logger.section('Verifying Contracts', 'verify');
try {
await hre.run('verify:verify', {
address: contractAddress,
});
logger.success('Contract verified successfully');
} catch (error) {
// Check if the error is "Already Verified"
const errorMessage = error instanceof Error ? error.message : String(error);
if (errorMessage.includes('Already Verified')) {
logger.info('Contract is already verified on block explorer');
} else {
logger.warn(`Verification failed: ${error}`);
}
}
}

return { contractAddress };
}
2 changes: 1 addition & 1 deletion tasks/deployProver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export async function deploySecp256k1Prover(
// Update deployment files
logger.section('Updating Deployment Files', 'files');
await updateDeployment(hre, contractName);
await updateAddressesFile(hre, contractName, contractAddress, contractImplAddress);
await updateAddressesFile(networkKey, contractName, { proxy: contractAddress, implementation: contractImplAddress });

if (verify) {
logger.section('Verifying Contracts', 'verify');
Expand Down
17 changes: 14 additions & 3 deletions tasks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,43 @@ import './postRequest';

import { deployAll } from './deployAll';
import { deploySedaCore } from './deployCore';
import { deployMock } from './deployPermissioned';
import { deploySecp256k1Prover } from './deployProver';

sedaScope
.task('deploy:core', 'Deploy the SedaCoreV1 contract')
.addOptionalParam('params', 'The parameters file to use', undefined, types.string)
.addOptionalParam('proverAddress', 'Direct SedaProver contract address', undefined, types.string)
.addFlag('verify', 'Verify the contract on etherscan')
.addFlag('reset', 'Replace existing deployment files')
.addFlag('verify', 'Verify the contract on etherscan')
.setAction(async (taskArgs, hre) => {
await deploySedaCore(hre, taskArgs);
});

sedaScope
.task('deploy:prover', 'Deploy the Secp256k1ProverV1 contract')
.addParam('params', 'The parameters file to use', undefined, types.string)
.addFlag('verify', 'Verify the contract on etherscan')
.addFlag('reset', 'Replace existing deployment files')
.addFlag('verify', 'Verify the contract on etherscan')
.setAction(async (taskArgs, hre) => {
await deploySecp256k1Prover(hre, taskArgs);
});

sedaScope
.task('deploy:all', 'Deploy the Secp256k1ProverV1 and SedaCoreV1 contracts')
.addParam('params', 'The parameters file to use', undefined, types.string)
.addFlag('verify', 'Verify the contract on etherscan')
.addFlag('reset', 'Replace existing deployment files')
.addFlag('verify', 'Verify the contract on etherscan')
.setAction(async (taskArgs, hre) => {
await deployAll(hre, taskArgs);
});

sedaScope
.task('deploy:permissioned', 'Deploy the Permissioned Seda contract (only for testing)')
.addOptionalParam('maxReplicationFactor', 'The maximum replication factor', undefined, types.int)
.addOptionalParam('params', 'The parameters file to use', undefined, types.string)
.addFlag('reset', 'Replace existing deployment files')
.addFlag('verify', 'Verify the contract on etherscan')
.setAction(async (taskArgs, hre) => {
await deployMock(hre, taskArgs);
});
2 changes: 1 addition & 1 deletion tasks/postRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { sedaScope } from '.';
import { logger } from './common/logger';

sedaScope
.task('post-request', 'Posts a data request to the SedaProver contract')
.task('post-request', 'Posts a data request to the SedaCore contract')
.addParam('core', 'The address of the SedaCore contract')
.setAction(async (taskArgs, hre) => {
logger.section('Post Data Request', 'deploy');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ethers } from 'hardhat';
import { compareRequests, compareResults, convertToRequestInputs } from '../helpers';
import { deriveDataResultId, deriveRequestId, generateDataFixtures } from '../utils';

describe('SedaCorePermissioned', () => {
describe('SedaPermissioned', () => {
const MAX_REPLICATION_FACTOR = 1;

async function deployFixture() {
Expand All @@ -15,7 +15,7 @@ describe('SedaCorePermissioned', () => {
anyone,
};

const PermissionedFactory = await ethers.getContractFactory('SedaCorePermissioned');
const PermissionedFactory = await ethers.getContractFactory('SedaPermissioned');
const core = await PermissionedFactory.deploy([relayer.address], MAX_REPLICATION_FACTOR);

return { core, signers };
Expand Down
Loading