Initial commit with 🏗️ create-eth @ 2.0.4
This commit is contained in:
121
packages/hardhat/deploy/00_deploy_whitelist.ts
Normal file
121
packages/hardhat/deploy/00_deploy_whitelist.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { DeployFunction } from "hardhat-deploy/types";
|
||||
import { decodeEventLog } from "viem";
|
||||
import { fetchPriceFromUniswap } from "../scripts/fetchPriceFromUniswap";
|
||||
|
||||
/**
|
||||
* Deploys a WhitelistOracle contract and creates SimpleOracle instances through it
|
||||
*
|
||||
* @param hre HardhatRuntimeEnvironment object.
|
||||
*/
|
||||
const deployWhitelistOracleContracts: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const { deployer } = await hre.getNamedAccounts();
|
||||
const { deploy } = hre.deployments;
|
||||
const { viem } = hre;
|
||||
|
||||
const publicClient = await viem.getPublicClient();
|
||||
|
||||
console.log("Deploying WhitelistOracle contract...");
|
||||
const whitelistOracleDeployment = await deploy("WhitelistOracle", {
|
||||
from: deployer,
|
||||
args: [],
|
||||
log: true,
|
||||
autoMine: false,
|
||||
});
|
||||
const whitelistOracleAddress = whitelistOracleDeployment.address as `0x${string}`;
|
||||
const whitelistOracleAbi = whitelistOracleDeployment.abi;
|
||||
|
||||
// Skip the rest of the setup if we are on a live network
|
||||
if (hre.network.name === "localhost") {
|
||||
// Get 10 wallet clients (accounts) to be oracle owners
|
||||
const accounts = await viem.getWalletClients();
|
||||
const nodeAccounts = accounts.slice(0, 10);
|
||||
|
||||
console.log("Creating SimpleOracle instances through WhitelistOracle...");
|
||||
const deployerAccount = accounts.find(a => a.account.address.toLowerCase() === deployer.toLowerCase());
|
||||
if (!deployerAccount) throw new Error("Deployer account not found in wallet clients");
|
||||
|
||||
// Create SimpleOracle instances through WhitelistOracle.addOracle() sequentially
|
||||
// (parallel nonce assignment doesn't work reliably with automining)
|
||||
const addOracleReceipts = [];
|
||||
for (let i = 0; i < nodeAccounts.length; i++) {
|
||||
const ownerAddress = nodeAccounts[i].account.address;
|
||||
console.log(`Creating SimpleOracle ${i + 1}/10 with owner: ${ownerAddress}`);
|
||||
const txHash = await deployerAccount.writeContract({
|
||||
address: whitelistOracleAddress,
|
||||
abi: whitelistOracleAbi,
|
||||
functionName: "addOracle",
|
||||
args: [ownerAddress],
|
||||
});
|
||||
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
||||
addOracleReceipts.push(receipt);
|
||||
}
|
||||
|
||||
// Map owner => created oracle address from events
|
||||
const ownerToOracleAddress = new Map<string, string>();
|
||||
for (const receipt of addOracleReceipts) {
|
||||
const oracleAddedEvent = receipt.logs.find(log => {
|
||||
try {
|
||||
const decoded = decodeEventLog({
|
||||
abi: whitelistOracleAbi,
|
||||
data: log.data,
|
||||
topics: log.topics,
|
||||
}) as { eventName: string; args: { oracleAddress: string; oracleOwner: string } };
|
||||
return decoded.eventName === "OracleAdded";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!oracleAddedEvent) continue;
|
||||
const decoded = decodeEventLog({
|
||||
abi: whitelistOracleAbi,
|
||||
data: oracleAddedEvent.data,
|
||||
topics: oracleAddedEvent.topics,
|
||||
}) as { eventName: string; args: { oracleAddress: string; oracleOwner: string } };
|
||||
ownerToOracleAddress.set(decoded.args.oracleOwner.toLowerCase(), decoded.args.oracleAddress);
|
||||
console.log(`✅ Created SimpleOracle at: ${decoded.args.oracleAddress}`);
|
||||
}
|
||||
|
||||
const createdOracleAddresses: string[] = nodeAccounts.map(acc => {
|
||||
const addr = ownerToOracleAddress.get(acc.account.address.toLowerCase());
|
||||
if (!addr) throw new Error(`Missing oracle address for owner ${acc.account.address}`);
|
||||
return addr;
|
||||
});
|
||||
|
||||
// Set initial prices for each created SimpleOracle
|
||||
console.log("Setting initial prices for each SimpleOracle...");
|
||||
const initialPrice = await fetchPriceFromUniswap();
|
||||
// Get SimpleOracle ABI from deployments
|
||||
const simpleOracleDeployment = await hre.deployments.getArtifact("SimpleOracle");
|
||||
const simpleOracleAbi = simpleOracleDeployment.abi;
|
||||
// Fire all setPrice transactions concurrently from each node owner
|
||||
const setPriceTxPromises = nodeAccounts.map((account, i) => {
|
||||
const oracleAddress = createdOracleAddresses[i];
|
||||
return account.writeContract({
|
||||
address: oracleAddress as `0x${string}`,
|
||||
abi: simpleOracleAbi,
|
||||
functionName: "setPrice",
|
||||
args: [initialPrice],
|
||||
});
|
||||
});
|
||||
const setPriceTxHashes = await Promise.all(setPriceTxPromises);
|
||||
await Promise.all(setPriceTxHashes.map(hash => publicClient.waitForTransactionReceipt({ hash })));
|
||||
for (let i = 0; i < createdOracleAddresses.length; i++) {
|
||||
console.log(`Set price for SimpleOracle ${i + 1} to: ${initialPrice}`);
|
||||
}
|
||||
|
||||
// Calculate initial median price
|
||||
console.log("Calculating initial median price...");
|
||||
const medianPrice = await publicClient.readContract({
|
||||
address: whitelistOracleAddress,
|
||||
abi: whitelistOracleAbi,
|
||||
functionName: "getPrice",
|
||||
args: [],
|
||||
});
|
||||
console.log(`Initial median price: ${medianPrice?.toString()}`);
|
||||
}
|
||||
console.log("WhitelistOracle contract deployed and configured successfully!");
|
||||
};
|
||||
|
||||
export default deployWhitelistOracleContracts;
|
||||
deployWhitelistOracleContracts.tags = ["Oracles"];
|
||||
61
packages/hardhat/deploy/01_deploy_staking.ts
Normal file
61
packages/hardhat/deploy/01_deploy_staking.ts
Normal file
@@ -0,0 +1,61 @@
|
||||
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { DeployFunction } from "hardhat-deploy/types";
|
||||
|
||||
const deployStakingOracle: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const { deployer } = await hre.getNamedAccounts();
|
||||
const { deploy } = hre.deployments;
|
||||
const { viem } = hre;
|
||||
|
||||
// Deploy ORA independently, then wire it into StakingOracle and transfer ownership to StakingOracle.
|
||||
console.log("Deploying ORA token...");
|
||||
const oraDeployment = await deploy("ORA", {
|
||||
contract: "ORA",
|
||||
from: deployer,
|
||||
args: [],
|
||||
log: true,
|
||||
autoMine: false,
|
||||
});
|
||||
|
||||
console.log("Deploying StakingOracle (wired to ORA)...");
|
||||
const stakingDeployment = await deploy("StakingOracle", {
|
||||
contract: "StakingOracle",
|
||||
from: deployer,
|
||||
args: [oraDeployment.address],
|
||||
log: true,
|
||||
autoMine: false,
|
||||
});
|
||||
|
||||
const stakingOracleAddress = stakingDeployment.address as `0x${string}`;
|
||||
console.log("StakingOracle deployed at:", stakingOracleAddress);
|
||||
|
||||
// Set ORA owner to StakingOracle so it can mint rewards via ORA.mint(...)
|
||||
const publicClient = await viem.getPublicClient();
|
||||
const walletClients = await viem.getWalletClients();
|
||||
const deployerClient = walletClients.find(wc => wc.account.address.toLowerCase() === deployer.toLowerCase());
|
||||
if (!deployerClient) throw new Error("Deployer wallet client not found");
|
||||
|
||||
// Check current owner before attempting transfer
|
||||
const currentOwner = await publicClient.readContract({
|
||||
address: oraDeployment.address as `0x${string}`,
|
||||
abi: oraDeployment.abi,
|
||||
functionName: "owner",
|
||||
args: [],
|
||||
});
|
||||
|
||||
if ((currentOwner as unknown as string).toLowerCase() === stakingOracleAddress.toLowerCase()) {
|
||||
console.log("ORA ownership already transferred to StakingOracle, skipping...");
|
||||
} else {
|
||||
console.log("Transferring ORA ownership to StakingOracle...");
|
||||
const txHash = await deployerClient.writeContract({
|
||||
address: oraDeployment.address as `0x${string}`,
|
||||
abi: oraDeployment.abi,
|
||||
functionName: "transferOwnership",
|
||||
args: [stakingOracleAddress],
|
||||
});
|
||||
await publicClient.waitForTransactionReceipt({ hash: txHash });
|
||||
}
|
||||
|
||||
console.log("ORA deployed at:", oraDeployment.address);
|
||||
};
|
||||
|
||||
export default deployStakingOracle;
|
||||
47
packages/hardhat/deploy/02_deploy_optimistic.ts
Normal file
47
packages/hardhat/deploy/02_deploy_optimistic.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { DeployFunction } from "hardhat-deploy/types";
|
||||
|
||||
const deployOptimisticOracle: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const { deployments, getNamedAccounts } = hre;
|
||||
const { deploy } = deployments;
|
||||
const { deployer } = await getNamedAccounts();
|
||||
|
||||
console.log("Deploying OptimisticOracle...");
|
||||
// Get the deployer's current nonce
|
||||
const deployerNonce = await hre.ethers.provider.getTransactionCount(deployer);
|
||||
|
||||
const futureDeciderAddress = hre.ethers.getCreateAddress({
|
||||
from: deployer,
|
||||
nonce: deployerNonce + 1, // +1 because it will be our second deployment
|
||||
});
|
||||
// Deploy the OptimisticOracle contract with deployer as temporary decider
|
||||
const optimisticOracle = await deploy("OptimisticOracle", {
|
||||
contract: "OptimisticOracle",
|
||||
from: deployer,
|
||||
args: [futureDeciderAddress],
|
||||
log: true,
|
||||
autoMine: false,
|
||||
});
|
||||
|
||||
// Deploy the Decider contract
|
||||
const decider = await deploy("Decider", {
|
||||
contract: "Decider",
|
||||
from: deployer,
|
||||
args: [optimisticOracle.address],
|
||||
log: true,
|
||||
autoMine: false,
|
||||
});
|
||||
|
||||
// Check if the decider address matches the expected address
|
||||
if (decider.address !== futureDeciderAddress) {
|
||||
throw new Error("Decider address does not match expected address");
|
||||
}
|
||||
|
||||
console.log("OptimisticOracle deployed to:", optimisticOracle.address);
|
||||
console.log("Decider deployed to:", decider.address);
|
||||
};
|
||||
|
||||
deployOptimisticOracle.id = "deploy_optimistic_oracle";
|
||||
deployOptimisticOracle.tags = ["OptimisticOracle"];
|
||||
|
||||
export default deployOptimisticOracle;
|
||||
Reference in New Issue
Block a user