Adds formal verification DSL, multi-sig contract, and Hardhat plugin: synor-verifier crate: - Verification DSL for contract invariants and properties - SMT solver integration (Z3 backend optional) - Symbolic execution engine for path exploration - Automatic vulnerability detection (reentrancy, overflow, etc.) - 29 tests passing contracts/multi-sig: - M-of-N multi-signature wallet contract - Transaction proposals with timelock - Owner management (add/remove) - Emergency pause functionality - Native token and contract call support apps/hardhat-plugin (@synor/hardhat-plugin): - Network configuration for mainnet/testnet/devnet - Contract deployment with gas estimation - Contract verification on explorer - WASM compilation support - TypeScript type generation - Testing utilities (fork, impersonate, time manipulation) - Synor-specific RPC methods (quantum status, shard info, DAG)
188 lines
6.1 KiB
TypeScript
188 lines
6.1 KiB
TypeScript
/**
|
|
* @synor/hardhat-plugin
|
|
*
|
|
* Hardhat plugin for Synor blockchain development.
|
|
* Provides seamless integration between Hardhat and Synor network.
|
|
*/
|
|
|
|
import { extendConfig, extendEnvironment, task } from "hardhat/config";
|
|
import { HardhatConfig, HardhatUserConfig, HardhatRuntimeEnvironment } from "hardhat/types";
|
|
import { SynorProvider } from "./provider";
|
|
import { SynorDeployer } from "./deployer";
|
|
import { SynorNetwork } from "./network";
|
|
import "./type-extensions";
|
|
|
|
// Default Synor network configurations
|
|
const SYNOR_NETWORKS = {
|
|
mainnet: {
|
|
url: "https://rpc.synor.cc",
|
|
chainId: 1337,
|
|
accounts: [],
|
|
},
|
|
testnet: {
|
|
url: "https://testnet-rpc.synor.cc",
|
|
chainId: 1338,
|
|
accounts: [],
|
|
},
|
|
devnet: {
|
|
url: "http://localhost:8545",
|
|
chainId: 1339,
|
|
accounts: [],
|
|
},
|
|
};
|
|
|
|
// Extend Hardhat config with Synor options
|
|
extendConfig((config: HardhatConfig, userConfig: Readonly<HardhatUserConfig>) => {
|
|
// Add Synor-specific configuration
|
|
config.synor = {
|
|
defaultNetwork: userConfig.synor?.defaultNetwork ?? "devnet",
|
|
gasPrice: userConfig.synor?.gasPrice ?? "auto",
|
|
gasLimit: userConfig.synor?.gasLimit ?? 3000000,
|
|
confirmations: userConfig.synor?.confirmations ?? 1,
|
|
timeout: userConfig.synor?.timeout ?? 60000,
|
|
verifyContracts: userConfig.synor?.verifyContracts ?? true,
|
|
quantumSafe: userConfig.synor?.quantumSafe ?? true,
|
|
};
|
|
|
|
// Add Synor networks if not already defined
|
|
for (const [name, network] of Object.entries(SYNOR_NETWORKS)) {
|
|
const networkName = `synor-${name}`;
|
|
if (!config.networks[networkName]) {
|
|
config.networks[networkName] = {
|
|
...network,
|
|
...(userConfig.networks?.[networkName] ?? {}),
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
// Extend Hardhat runtime environment
|
|
extendEnvironment((hre: HardhatRuntimeEnvironment) => {
|
|
// Add Synor provider
|
|
hre.synor = {
|
|
provider: new SynorProvider(hre),
|
|
deployer: new SynorDeployer(hre),
|
|
network: new SynorNetwork(hre),
|
|
getBalance: async (address: string) => {
|
|
return hre.synor.provider.getBalance(address);
|
|
},
|
|
getBlockNumber: async () => {
|
|
return hre.synor.provider.getBlockNumber();
|
|
},
|
|
sendTransaction: async (tx: any) => {
|
|
return hre.synor.provider.sendTransaction(tx);
|
|
},
|
|
};
|
|
});
|
|
|
|
// Task: Deploy contract to Synor
|
|
task("synor:deploy", "Deploy a contract to Synor network")
|
|
.addParam("contract", "Contract name to deploy")
|
|
.addOptionalVariadicPositionalParam("args", "Constructor arguments")
|
|
.setAction(async (taskArgs, hre) => {
|
|
const { contract, args = [] } = taskArgs;
|
|
|
|
console.log(`Deploying ${contract} to Synor ${hre.network.name}...`);
|
|
|
|
const deployed = await hre.synor.deployer.deploy(contract, args);
|
|
|
|
console.log(`Contract deployed at: ${deployed.address}`);
|
|
console.log(`Transaction hash: ${deployed.deployTransaction.hash}`);
|
|
|
|
if (hre.config.synor.verifyContracts) {
|
|
console.log("Verifying contract...");
|
|
await hre.synor.network.verifyContract(deployed.address, args);
|
|
console.log("Contract verified!");
|
|
}
|
|
|
|
return deployed;
|
|
});
|
|
|
|
// Task: Verify contract on Synor explorer
|
|
task("synor:verify", "Verify a contract on Synor explorer")
|
|
.addParam("address", "Contract address")
|
|
.addParam("contract", "Contract name")
|
|
.addOptionalVariadicPositionalParam("args", "Constructor arguments")
|
|
.setAction(async (taskArgs, hre) => {
|
|
const { address, contract, args = [] } = taskArgs;
|
|
|
|
console.log(`Verifying ${contract} at ${address}...`);
|
|
await hre.synor.network.verifyContract(address, args, contract);
|
|
console.log("Contract verified!");
|
|
});
|
|
|
|
// Task: Get network info
|
|
task("synor:info", "Get Synor network information")
|
|
.setAction(async (_, hre) => {
|
|
const info = await hre.synor.network.getNetworkInfo();
|
|
|
|
console.log("\nSynor Network Information:");
|
|
console.log("==========================");
|
|
console.log(`Network: ${info.name}`);
|
|
console.log(`Chain ID: ${info.chainId}`);
|
|
console.log(`Block Height: ${info.blockHeight}`);
|
|
console.log(`Latest Block Hash: ${info.latestBlockHash}`);
|
|
console.log(`Gas Price: ${info.gasPrice} gwei`);
|
|
console.log(`Protocol Version: ${info.protocolVersion}`);
|
|
console.log(`Consensus: ${info.consensus}`);
|
|
console.log(`Quantum Safe: ${info.quantumSafe}`);
|
|
});
|
|
|
|
// Task: Fund account from faucet (testnet/devnet only)
|
|
task("synor:faucet", "Request tokens from Synor faucet")
|
|
.addParam("address", "Address to fund")
|
|
.addOptionalParam("amount", "Amount to request (in SYN)", "10")
|
|
.setAction(async (taskArgs, hre) => {
|
|
const { address, amount } = taskArgs;
|
|
|
|
if (hre.network.name.includes("mainnet")) {
|
|
throw new Error("Faucet not available on mainnet");
|
|
}
|
|
|
|
console.log(`Requesting ${amount} SYN for ${address}...`);
|
|
const txHash = await hre.synor.network.requestFaucet(address, amount);
|
|
console.log(`Faucet transaction: ${txHash}`);
|
|
});
|
|
|
|
// Task: Compile contracts for Synor (WASM target)
|
|
task("synor:compile", "Compile contracts for Synor WASM runtime")
|
|
.setAction(async (_, hre) => {
|
|
console.log("Compiling contracts for Synor...");
|
|
|
|
// First run standard compilation
|
|
await hre.run("compile");
|
|
|
|
// Then generate WASM artifacts
|
|
await hre.synor.deployer.compileToWasm();
|
|
|
|
console.log("Compilation complete!");
|
|
});
|
|
|
|
// Task: Run tests on Synor fork
|
|
task("synor:test", "Run tests against Synor network fork")
|
|
.addOptionalParam("fork", "Block number to fork from", "latest")
|
|
.setAction(async (taskArgs, hre) => {
|
|
const { fork } = taskArgs;
|
|
|
|
console.log(`Forking Synor at block ${fork}...`);
|
|
|
|
// Set up fork
|
|
await hre.synor.network.fork(fork);
|
|
|
|
// Run tests
|
|
await hre.run("test");
|
|
});
|
|
|
|
// Task: Generate TypeScript types for contracts
|
|
task("synor:typechain", "Generate TypeScript types for Synor contracts")
|
|
.setAction(async (_, hre) => {
|
|
console.log("Generating TypeScript types...");
|
|
await hre.synor.deployer.generateTypes();
|
|
console.log("Types generated in typechain-types/");
|
|
});
|
|
|
|
// Export types and utilities
|
|
export { SynorProvider } from "./provider";
|
|
export { SynorDeployer } from "./deployer";
|
|
export { SynorNetwork } from "./network";
|
|
export * from "./types";
|