Economic models
Trustless Economic Core Inspect the rules and evidence around a simulated economic settlement system.
Code & guide What to expect This directory includes code and documentation. Its guide defines dependencies, execution modes and what the results demonstrate.
Guides & runbooks 1
Registered commands 0 Environment setup ↗ Guided tour Inspect the sources Try it locally Architecture Complete library
A CLOSER LOOK
Can economic settlement rules be exercised on a disposable chain? For contract developers: follow a dedicated Hardhat scenario and inspect the generated economic report and dashboard.
01 02 03 Read the original architecture Connect the scenario to the wider core and owner controls. The preserved systems map is architectural context, not independent security review.
demo/Trustless-Economic-Core-v0/README.md ↗ Inspect this source ↓
REAL REPOSITORY MATERIAL
Inspect. Understand. Reproduce. Reading the exact source at revision 5b4cebb3. This browser inspection does not execute the demo.
demo/Trustless-Economic-Core-v0/hardhat.config.ts
Select a walkthrough step to explore its source.
Show more fields ↓ Full source text import { HardhatUserConfig } from 'hardhat/config';
import '@nomicfoundation/hardhat-toolbox';
console.log('[Trustless Economic Core] Loading dedicated Hardhat config');
const config: HardhatUserConfig = {
solidity: {
version: '0.8.25',
settings: {
optimizer: { enabled: true, runs: 200 },
},
},
paths: {
root: __dirname,
sources: './contracts',
tests: '../test/demo',
cache: './cache',
artifacts: './artifacts',
},
};
export default config;
SHA-256 3c88ee11b4df3e04a39785595105ad465855db517a6b17558840a418c7bf0aa4
The first source is shown in full. All walkthrough source links and the complete document library remain available without JavaScript.
{"revision":"5b4cebb309a83a7a6749d8911d8bf96a1921e042","sources":[{"file":"demo/Trustless-Economic-Core-v0/hardhat.config.ts","content":"import { HardhatUserConfig } from 'hardhat/config';\nimport '@nomicfoundation/hardhat-toolbox';\n\nconsole.log('[Trustless Economic Core] Loading dedicated Hardhat config');\n\nconst config: HardhatUserConfig = {\n solidity: {\n version: '0.8.25',\n settings: {\n optimizer: { enabled: true, runs: 200 },\n },\n },\n paths: {\n root: __dirname,\n sources: './contracts',\n tests: '../test/demo',\n cache: './cache',\n artifacts: './artifacts',\n },\n};\n\nexport default config;\n","format":"text","sha256":"3c88ee11b4df3e04a39785595105ad465855db517a6b17558840a418c7bf0aa4","bytes":491,"download":"/AGIJobsv0/examples/3c88ee11b4df3e04-hardhat.config.ts","source":"https://github.com/MontrealAI/AGIJobsv0/blob/5b4cebb309a83a7a6749d8911d8bf96a1921e042/demo/Trustless-Economic-Core-v0/hardhat.config.ts"},{"file":"demo/Trustless-Economic-Core-v0/scripts/runScenario.ts","content":"import { ethers } from 'hardhat';\nimport type { ContractTransactionReceipt } from 'ethers';\nimport { mkdirSync, writeFileSync } from 'node:fs';\nimport path from 'node:path';\n\ntype TimelineEntry = {\n step: number;\n title: string;\n actor: string;\n txHash?: string;\n blockNumber?: number;\n gasUsed?: string;\n details: string[];\n};\n\ntype MilestoneExecution = {\n id: number;\n approvals: string[];\n agentAmount: string;\n validatorAmount: string;\n feeAmount: string;\n burnAmount: string;\n};\n\ntype BalanceSheet = Record<string, { start: bigint; end: bigint; delta: bigint }>;\n\ntype ParticipantLabel = {\n role: string;\n name: string;\n ens?: string;\n};\n\nconst BASIS_POINTS = 10_000n;\n\nconst labels: Record<string, ParticipantLabel> = {};\nconst timeline: TimelineEntry[] = [];\nconst milestoneExecutions: MilestoneExecution[] = [];\nconst approvals = new Map<number, string[]>();\n\nconst formatToken = (value: bigint): string => ethers.formatUnits(value, 18);\n\nconst checksum = (address: string): string => ethers.getAddress(address);\n\nconst labelFor = (address: string): ParticipantLabel => {\n const key = checksum(address);\n if (!labels[key]) {\n labels[key] = { role: 'Participant', name: key };\n }\n return labels[key];\n};\n\nfunction recordStep(\n title: string,\n actor: ParticipantLabel,\n details: string[],\n receipt?: ContractTransactionReceipt | null\n) {\n const entry: TimelineEntry = {\n step: timeline.length + 1,\n title,\n actor: `${actor.name} • ${actor.role}` + (actor.ens ? ` (${actor.ens})` : ''),\n txHash: receipt?.hash,\n blockNumber: receipt?.blockNumber,\n gasUsed: receipt?.gasUsed ? receipt.gasUsed.toString() : undefined,\n details,\n };\n timeline.push(entry);\n\n // Console narration for the non-technical operator.\n console.log(`\\n[${entry.step}] ${entry.title}`);\n console.log(` Actor: ${entry.actor}`);\n if (entry.txHash) {\n console.log(` Tx: ${entry.txHash} (block ${entry.blockNumber}, gas ${entry.gasUsed})`);\n }\n for (const detail of entry.details) {\n console.log(` • ${detail}`);\n }\n}\n\nasync function persistArtefacts(\n outputDir: string,\n sheet: BalanceSheet,\n networkName: string,\n parameters: {\n validatorRewardPct: bigint;\n protocolFeePct: bigint;\n burnPct: bigint;\n jobStakeLockPct: bigint;\n slashEmployerPct: bigint;\n slashValidatorPct: bigint;\n slashTreasuryPct: bigint;\n slashBurnPct: bigint;\n },\n context: {\n jobId: number;\n milestones: number;\n slashAmount: bigint;\n agentAddress: string;\n employerAddress: string;\n treasuryAddress: string;\n validatorAddresses: string[];\n totalSupplyBefore: bigint;\n totalSupplyAfter: bigint;\n }\n) {\n mkdirSync(outputDir, { recursive: true });\n\n const summary = {\n generatedAt: new Date().toISOString(),\n network: networkName,\n job: {\n id: context.jobId,\n milestoneCount: context.milestones,\n slashAmount: formatToken(context.slashAmount),\n },\n economics: {\n validatorRewardPct: Number(parameters.validatorRewardPct) / Number(BASIS_POINTS),\n protocolFeePct: Number(parameters.protocolFeePct) / Number(BASIS_POINTS),\n burnPct: Number(parameters.burnPct) / Number(BASIS_POINTS),\n jobStakeLockPct: Number(parameters.jobStakeLockPct) / Number(BASIS_POINTS),\n slashBreakdown: {\n employer: Number(parameters.slashEmployerPct) / Number(BASIS_POINTS),\n validator: Number(parameters.slashValidatorPct) / Number(BASIS_POINTS),\n treasury: Number(parameters.slashTreasuryPct) / Number(BASIS_POINTS),\n burn: Number(parameters.slashBurnPct) / Number(BASIS_POINTS),\n },\n },\n balances: Object.fromEntries(\n Object.entries(sheet).map(([address, entry]) => [\n checksum(address),\n {\n start: formatToken(entry.start),\n end: formatToken(entry.end),\n delta: formatToken(entry.delta),\n label: labelFor(address),\n },\n ])\n ),\n milestones: milestoneExecutions,\n timeline,\n supply: {\n before: formatToken(context.totalSupplyBefore),\n after: formatToken(context.totalSupplyAfter),\n delta: formatToken(context.totalSupplyAfter - context.totalSupplyBefore),\n },\n governance: {\n agent: checksum(context.agentAddress),\n employer: checksum(context.employerAddress),\n treasury: checksum(context.treasuryAddress),\n validators: context.validatorAddresses.map(checksum),\n },\n };\n\n const jsonPath = path.join(outputDir, 'trustless-core-report.json');\n writeFileSync(jsonPath, JSON.stringify(summary, null, 2));\n\n const markdownLines: string[] = [];\n markdownLines.push('# Trustless Economic Core Demo Run');\n markdownLines.push('');\n markdownLines.push(`- Generated: ${summary.generatedAt}`);\n markdownLines.push(`- Network: **${networkName}**`);\n markdownLines.push(`- Job ID: **${context.jobId}** with **${context.milestones} milestones**`);\n markdownLines.push(`- Total Supply → ${formatToken(context.totalSupplyBefore)} → ${formatToken(context.totalSupplyAfter)} $AGIALPHA`);\n markdownLines.push('');\n markdownLines.push('## Economic Parameters');\n markdownLines.push('');\n markdownLines.push('| Parameter | Value |');\n markdownLines.push('| --- | --- |');\n markdownLines.push(`| Validator reward | ${(summary.economics.validatorRewardPct * 100).toFixed(2)}% |`);\n markdownLines.push(`| Protocol fee | ${(summary.economics.protocolFeePct * 100).toFixed(2)}% |`);\n markdownLines.push(`| Burn | ${(summary.economics.burnPct * 100).toFixed(2)}% |`);\n markdownLines.push(`| Agent stake lock | ${(summary.economics.jobStakeLockPct * 100).toFixed(2)}% |`);\n markdownLines.push(`| Slash → Employer | ${(summary.economics.slashBreakdown.employer * 100).toFixed(2)}% |`);\n markdownLines.push(`| Slash → Validators | ${(summary.economics.slashBreakdown.validator * 100).toFixed(2)}% |`);\n markdownLines.push(`| Slash → Treasury | ${(summary.economics.slashBreakdown.treasury * 100).toFixed(2)}% |`);\n markdownLines.push(`| Slash → Burn | ${(summary.economics.slashBreakdown.burn * 100).toFixed(2)}% |`);\n markdownLines.push('');\n markdownLines.push('## Participant Balance Sheet (in $AGIALPHA)');\n markdownLines.push('');\n markdownLines.push('| Participant | Start | End | Δ |');\n markdownLines.push('| --- | --- | --- | --- |');\n for (const [address, entry] of Object.entries(summary.balances)) {\n const label = summary.balances[address].label as ParticipantLabel | undefined;\n const name = label ? `${label.name} (${label.role})` : address;\n markdownLines.push(`| ${name} | ${summary.balances[address].start} | ${summary.balances[address].end} | ${summary.balances[address].delta} |`);\n }\n markdownLines.push('');\n markdownLines.push('## Milestone Releases');\n markdownLines.push('');\n markdownLines.push('| Milestone | Approvals | Agent | Validators | Fee | Burn |');\n markdownLines.push('| --- | --- | --- | --- | --- | --- |');\n for (const execution of milestoneExecutions) {\n markdownLines.push(\n `| ${execution.id + 1} | ${execution.approvals.length} | ${execution.agentAmount} | ${execution.validatorAmount} | ${execution.feeAmount} | ${execution.burnAmount} |`\n );\n }\n markdownLines.push('');\n markdownLines.push('## Timeline');\n markdownLines.push('');\n markdownLines.push('| # | Title | Actor | Details |');\n markdownLines.push('| --- | --- | --- | --- |');\n for (const entry of timeline) {\n const details = entry.details.join('<br/>');\n markdownLines.push(`| ${entry.step} | ${entry.title} | ${entry.actor} | ${details} |`);\n }\n markdownLines.push('');\n markdownLines.push('```mermaid');\n markdownLines.push('sequenceDiagram');\n markdownLines.push(' participant GOV as Governance Owner');\n markdownLines.push(' participant EMP as Employer');\n markdownLines.push(' participant AGT as Agent');\n markdownLines.push(' participant VAL as Validator Council');\n markdownLines.push(' participant TRE as Treasury');\n markdownLines.push(' participant BURN as Burn Sink');\n markdownLines.push(' GOV->>GOV: Deploy contracts & register identities');\n markdownLines.push(' EMP->>GOV: Escrow 3 milestone tranches');\n markdownLines.push(' AGT->>GOV: Stake collateral locked by policy');\n markdownLines.push(' VAL->>GOV: Approve Milestone 1');\n markdownLines.push(' GOV->>AGT: Release tranche 1 (fees+burn routed)');\n markdownLines.push(' GOV->>VAL: Stream validator rewards');\n markdownLines.push(' GOV-->>GOV: System-wide pause engaged');\n markdownLines.push(' VAL-xGOV: Paused milestone attempt rejected');\n markdownLines.push(' GOV-->>GOV: System unpaused');\n markdownLines.push(' VAL->>GOV: Approve Milestone 2');\n markdownLines.push(' GOV->>AGT: Release tranche 2 (fees+burn routed)');\n markdownLines.push(' GOV->>VAL: Stream validator rewards');\n markdownLines.push(' GOV->>AGT: Slash collateral for fraud');\n markdownLines.push(' GOV->>EMP: Refund remaining escrow & slash award');\n markdownLines.push(' GOV->>TRE: Route protocol fees & slash share');\n markdownLines.push(' GOV->>BURN: Destroy economic penalties');\n markdownLines.push(' AGT->>AGT: Withdraw released stake');\n markdownLines.push('```');\n\n const markdownPath = path.join(outputDir, 'trustless-core-report.md');\n writeFileSync(markdownPath, markdownLines.join('\\n'));\n\n const htmlRows = Object.entries(summary.balances)\n .map(([_, entry]) => {\n const label = entry.label as ParticipantLabel | undefined;\n const name = label ? `${label.name} <small>${label.role}</small>` : checksum(_);\n return `<tr><td>${name}</td><td>${entry.start}</td><td>${entry.end}</td><td>${entry.delta}</td></tr>`;\n })\n .join('\\n');\n\n const htmlTimeline = timeline\n .map(\n (entry) =>\n `<tr><td>${entry.step}</td><td>${entry.title}</td><td>${entry.actor}</td><td>${entry.details\n .map((line) => `<div>${line}</div>`)\n .join('')}</td></tr>`\n )\n .join('\\n');\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <title>Trustless Economic Core Demo</title>\n <style>\n body { font-family: 'Inter', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; margin: 2rem; background: #05060f; color: #eef2ff; }\n h1, h2 { color: #f0abfc; }\n table { width: 100%; border-collapse: collapse; margin-bottom: 1.5rem; }\n th, td { border: 1px solid rgba(255,255,255,0.1); padding: 0.5rem 0.75rem; text-align: left; }\n thead { background: rgba(240, 171, 252, 0.1); }\n code { background: rgba(15, 23, 42, 0.8); padding: 0.25rem 0.4rem; border-radius: 0.4rem; }\n .badge { display: inline-block; background: linear-gradient(135deg, #22d3ee, #818cf8); padding: 0.4rem 0.75rem; border-radius: 999px; font-size: 0.85rem; margin-right: 0.5rem; }\n footer { margin-top: 2rem; font-size: 0.85rem; opacity: 0.8; }\n </style>\n </head>\n <body>\n <h1>Trustless Economic Core Demo</h1>\n <div class=\"badge\">Network: ${networkName}</div>\n <div class=\"badge\">Job #${context.jobId}</div>\n <div class=\"badge\">Milestones: ${context.milestones}</div>\n <p>The AGI Jobs trustless core executed autonomously. Every transfer, pause, and slash was enforced entirely on-chain.</p>\n <h2>Economic Parameters</h2>\n <table>\n <thead><tr><th>Parameter</th><th>Value</th></tr></thead>\n <tbody>\n <tr><td>Validator reward</td><td>${(summary.economics.validatorRewardPct * 100).toFixed(2)}%</td></tr>\n <tr><td>Protocol fee</td><td>${(summary.economics.protocolFeePct * 100).toFixed(2)}%</td></tr>\n <tr><td>Burn</td><td>${(summary.economics.burnPct * 100).toFixed(2)}%</td></tr>\n <tr><td>Agent stake lock</td><td>${(summary.economics.jobStakeLockPct * 100).toFixed(2)}%</td></tr>\n <tr><td>Slash → Employer</td><td>${(summary.economics.slashBreakdown.employer * 100).toFixed(2)}%</td></tr>\n <tr><td>Slash → Validators</td><td>${(summary.economics.slashBreakdown.validator * 100).toFixed(2)}%</td></tr>\n <tr><td>Slash → Treasury</td><td>${(summary.economics.slashBreakdown.treasury * 100).toFixed(2)}%</td></tr>\n <tr><td>Slash → Burn</td><td>${(summary.economics.slashBreakdown.burn * 100).toFixed(2)}%</td></tr>\n </tbody>\n </table>\n <h2>Balances (in $AGIALPHA)</h2>\n <table>\n <thead><tr><th>Participant</th><th>Start</th><th>End</th><th>Δ</th></tr></thead>\n <tbody>${htmlRows}</tbody>\n </table>\n <h2>Milestone Releases</h2>\n <table>\n <thead><tr><th>#</th><th>Approvals</th><th>Agent</th><th>Validators</th><th>Fee</th><th>Burn</th></tr></thead>\n <tbody>\n ${milestoneExecutions\n .map(\n (execution) =>\n `<tr><td>${execution.id + 1}</td><td>${execution.approvals.length}</td><td>${execution.agentAmount}</td><td>${execution.validatorAmount}</td><td>${execution.feeAmount}</td><td>${execution.burnAmount}</td></tr>`\n )\n .join('')}\n </tbody>\n </table>\n <h2>Timeline</h2>\n <table>\n <thead><tr><th>#</th><th>Title</th><th>Actor</th><th>Details</th></tr></thead>\n <tbody>${htmlTimeline}</tbody>\n </table>\n <footer>Artefacts exported on ${summary.generatedAt}. Ready for executive circulation.</footer>\n </body>\n</html>`;\n\n const htmlPath = path.join(outputDir, 'trustless-core-dashboard.html');\n writeFileSync(htmlPath, html);\n\n console.log('\\nArtefacts generated:');\n console.log(` • ${jsonPath}`);\n console.log(` • ${markdownPath}`);\n console.log(` • ${htmlPath}`);\n}\n\nasync function main() {\n const [owner, employer, agent, validator1, validator2, validator3, treasury] = await ethers.getSigners();\n\n labels[checksum(owner.address)] = { role: 'Governance Owner', name: 'Owner' };\n labels[checksum(employer.address)] = { role: 'Employer', name: 'Employer' };\n labels[checksum(agent.address)] = {\n role: 'Agent',\n name: 'Prime Agent',\n ens: 'demo-agent.alpha.agent.agi.eth',\n };\n labels[checksum(validator1.address)] = {\n role: 'Validator',\n name: 'Validator One',\n ens: 'validator1.club.agi.eth',\n };\n labels[checksum(validator2.address)] = {\n role: 'Validator',\n name: 'Validator Two',\n ens: 'validator2.club.agi.eth',\n };\n labels[checksum(validator3.address)] = {\n role: 'Validator',\n name: 'Validator Three',\n ens: 'validator3.club.agi.eth',\n };\n labels[checksum(treasury.address)] = { role: 'Treasury', name: 'Treasury' };\n\n const Token = await ethers.getContractFactory('DemoAGIALPHAToken');\n const token = await Token.connect(owner).deploy();\n await token.waitForDeployment();\n recordStep('Deploy DemoAGIALPHA token', labelFor(owner.address), [\n `Address ${await token.getAddress()}`,\n ]);\n\n const participants = [owner, employer, agent, validator1, validator2, validator3, treasury];\n const mintAmount = ethers.parseUnits('1000');\n for (const signer of participants) {\n const tx = await token.connect(owner).mint(signer.address, mintAmount);\n await tx.wait();\n }\n recordStep('Seed $AGIALPHA balances', labelFor(owner.address), [\n 'Minted 1,000 $AGIALPHA to governance, employer, agent, validators, and treasury.',\n ]);\n\n const startingBalances: Record<string, bigint> = {};\n for (const signer of participants) {\n startingBalances[checksum(signer.address)] = await token.balanceOf(signer.address);\n }\n const totalSupplyBefore = await token.totalSupply();\n\n const validatorRewardPct = 1000n;\n const protocolFeePct = 500n;\n const burnPct = 200n;\n const minStake = ethers.parseUnits('150');\n const jobStakeLockPct = 2000n;\n\n const Demo = await ethers.getContractFactory('TrustlessEconomicCoreDemo');\n const demo = await Demo.connect(owner).deploy(\n await token.getAddress(),\n treasury.address,\n validatorRewardPct,\n protocolFeePct,\n burnPct,\n minStake,\n jobStakeLockPct\n );\n await demo.waitForDeployment();\n const demoAddress = await demo.getAddress();\n labels[checksum(demoAddress)] = { role: 'Smart Contract', name: 'Trustless Core' };\n startingBalances[checksum(demoAddress)] = await token.balanceOf(demoAddress);\n recordStep('Deploy Trustless Economic Core', labelFor(owner.address), [\n `Contract ${demoAddress}`,\n 'Validator reward 10%, fee 5%, burn 2%, stake lock 20%.',\n ]);\n\n const agentNode = ethers.id(labelFor(agent.address).ens!);\n const validatorNodes = [validator1, validator2, validator3].map((signer) =>\n ethers.id(labelFor(signer.address).ens!)\n );\n\n const registerAgentTx = await demo.connect(owner).registerAgentIdentity(agent.address, agentNode);\n recordStep('Register agent ENS identity', labelFor(owner.address), [\n `${labelFor(agent.address).ens} → ${agent.address}`,\n ], await registerAgentTx.wait());\n\n for (let i = 0; i < validatorNodes.length; i++) {\n const tx = await demo\n .connect(owner)\n .registerValidatorIdentity([validator1, validator2, validator3][i].address, validatorNodes[i]);\n recordStep(\n `Register validator ${i + 1} ENS identity`,\n labelFor(owner.address),\n [\n `${labelFor([validator1, validator2, validator3][i].address).ens} → ${[validator1, validator2, validator3][i].address}`,\n ],\n await tx.wait()\n );\n }\n\n const stakeAmount = ethers.parseUnits('200');\n const approveStakeTx = await token.connect(agent).approve(await demo.getAddress(), stakeAmount);\n await approveStakeTx.wait();\n const stakeTx = await demo.connect(agent).depositStake(stakeAmount);\n recordStep('Agent stakes collateral', labelFor(agent.address), ['Staked 200 $AGIALPHA. Policy requires ≥150 and locks 20% per job.'], await stakeTx.wait());\n\n const milestoneAmounts = [0, 1, 2].map(() => ethers.parseUnits('100'));\n const committee = [validator1.address, validator2.address, validator3.address];\n const threshold = 2;\n\n const approveJobTx = await token.connect(employer).approve(await demo.getAddress(), ethers.parseUnits('300'));\n await approveJobTx.wait();\n const createJobTx = await demo\n .connect(employer)\n .createJob(agent.address, milestoneAmounts, committee, threshold);\n const createJobReceipt = await createJobTx.wait();\n const jobCreatedLog = createJobReceipt?.logs\n .map((log) => {\n try {\n return demo.interface.parseLog(log);\n } catch (error) {\n return null;\n }\n })\n .find((parsed) => parsed && parsed.name === 'JobCreated');\n const jobId = jobCreatedLog?.args?.jobId ? Number(jobCreatedLog.args.jobId) : 1;\n recordStep(\n 'Employer escrows three-milestone job',\n labelFor(employer.address),\n [\n `Job ID ${jobId} with 3 × 100 $AGIALPHA milestones`,\n 'Validator threshold: 2 of 3',\n `Agent stake locked: ${formatToken(await demo.agentLockedStake(agent.address))} $AGIALPHA`,\n ],\n createJobReceipt\n );\n\n const pauseJobTx = await demo.connect(owner).pauseJob(jobId);\n recordStep(\n 'Governance pauses job-specific flow',\n labelFor(owner.address),\n ['Milestone approvals disabled for this job only.'],\n await pauseJobTx.wait()\n );\n\n try {\n await demo.connect(validator1).approveMilestone(jobId, 0);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n recordStep('Job-level pause rejects approval', labelFor(validator1.address), [\n 'Custom error captured: JobPausedOrCancelled',\n message.split('\\n')[0],\n ]);\n }\n\n const resumeJobTx = await demo.connect(owner).resumeJob(jobId);\n recordStep(\n 'Governance resumes job-specific flow',\n labelFor(owner.address),\n ['Validator approvals re-enabled for the job.'],\n await resumeJobTx.wait()\n );\n\n async function approveMilestone(actor: typeof validator1, milestoneId: number) {\n const tx = await demo.connect(actor).approveMilestone(jobId, milestoneId);\n const receipt = await tx.wait();\n const current = approvals.get(milestoneId) ?? [];\n current.push(actor.address);\n approvals.set(milestoneId, current);\n\n const releaseLog = receipt?.logs\n .map((log) => {\n try {\n return demo.interface.parseLog(log);\n } catch (error) {\n return null;\n }\n })\n .find((parsed) => parsed && parsed.name === 'MilestoneReleased');\n\n const detailLines = [`Milestone ${milestoneId + 1} approvals: ${current.length}/${threshold}`];\n\n if (releaseLog) {\n const execution: MilestoneExecution = {\n id: Number(releaseLog.args?.milestoneId ?? milestoneId),\n approvals: current.map(checksum),\n agentAmount: formatToken(releaseLog.args?.agentAmount ?? 0n),\n validatorAmount: formatToken(releaseLog.args?.validatorAmount ?? 0n),\n feeAmount: formatToken(releaseLog.args?.feeAmount ?? 0n),\n burnAmount: formatToken(releaseLog.args?.burnAmount ?? 0n),\n };\n milestoneExecutions.push(execution);\n detailLines.push(\n `Agent received ${execution.agentAmount} $AGIALPHA, validators ${execution.validatorAmount}, fee ${execution.feeAmount}, burn ${execution.burnAmount}.`\n );\n }\n\n recordStep(\n `Validator ${labelFor(actor.address).name} approves milestone ${milestoneId + 1}`,\n labelFor(actor.address),\n detailLines,\n receipt\n );\n }\n\n await approveMilestone(validator1, 0);\n await approveMilestone(validator2, 0);\n\n const pauseTx = await demo.connect(owner).pauseAll();\n recordStep('Governance executes global pause', labelFor(owner.address), ['All milestone approvals blocked.'], await pauseTx.wait());\n\n try {\n await demo.connect(validator1).approveMilestone(jobId, 1);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n recordStep('Paused milestone attempt rejected', labelFor(validator1.address), [\n 'Custom error captured: EnforcedPause',\n message.split('\\n')[0],\n ]);\n }\n\n const unpauseTx = await demo.connect(owner).unpauseAll();\n recordStep('Governance resumes payouts', labelFor(owner.address), ['Milestone approvals re-enabled.'], await unpauseTx.wait());\n\n await approveMilestone(validator2, 1);\n await approveMilestone(validator3, 1);\n\n const slashAmount = ethers.parseUnits('60');\n const slashTx = await demo.connect(owner).slashAgent(jobId, slashAmount);\n const slashReceipt = await slashTx.wait();\n const slashLog = slashReceipt?.logs\n .map((log) => {\n try {\n return demo.interface.parseLog(log);\n } catch (error) {\n return null;\n }\n })\n .find((parsed) => parsed && parsed.name === 'AgentSlashed');\n recordStep(\n 'Governance slashes agent for failed milestone',\n labelFor(owner.address),\n [\n `Slashed ${formatToken(slashAmount)} $AGIALPHA collateral`,\n `Employer share: ${formatToken(slashLog?.args?.employerShare ?? 0n)}`,\n `Validators share: ${formatToken(slashLog?.args?.validatorShare ?? 0n)}`,\n `Treasury share: ${formatToken(slashLog?.args?.treasuryShare ?? 0n)}`,\n `Burn: ${formatToken(slashLog?.args?.burnShare ?? 0n)}`,\n ],\n slashReceipt\n );\n\n const cancelTx = await demo.connect(employer).cancelJob(jobId);\n recordStep(\n 'Employer cancels job and retrieves escrow',\n labelFor(employer.address),\n ['Unused milestone funds reclaimed after slashing.'],\n await cancelTx.wait()\n );\n\n const remainingStake = await demo.agentStake(agent.address);\n if (remainingStake > 0n) {\n const withdrawTx = await demo.connect(agent).withdrawStake(remainingStake);\n recordStep(\n 'Agent withdraws released collateral',\n labelFor(agent.address),\n [`Recovered ${formatToken(remainingStake)} $AGIALPHA stake.`],\n await withdrawTx.wait()\n );\n }\n\n const trackedAddresses = [\n owner.address,\n employer.address,\n agent.address,\n validator1.address,\n validator2.address,\n validator3.address,\n treasury.address,\n demoAddress,\n ];\n const balanceSheet: BalanceSheet = {};\n for (const address of trackedAddresses) {\n const key = checksum(address);\n const start = startingBalances[key] ?? 0n;\n const end = await token.balanceOf(address);\n balanceSheet[key] = {\n start,\n end,\n delta: end - start,\n };\n }\n\n const network = await ethers.provider.getNetwork();\n const outputDir = path.join(__dirname, '..', 'reports');\n\n await persistArtefacts(\n outputDir,\n balanceSheet,\n network.name,\n {\n validatorRewardPct,\n protocolFeePct,\n burnPct,\n jobStakeLockPct,\n slashEmployerPct: 5000n,\n slashValidatorPct: 2000n,\n slashTreasuryPct: 2000n,\n slashBurnPct: 1000n,\n },\n {\n jobId,\n milestones: milestoneAmounts.length,\n slashAmount,\n agentAddress: agent.address,\n employerAddress: employer.address,\n treasuryAddress: treasury.address,\n validatorAddresses: committee,\n totalSupplyBefore,\n totalSupplyAfter: await token.totalSupply(),\n }\n );\n}\n\nmain().catch((error) => {\n console.error(error);\n process.exitCode = 1;\n});\n","format":"text","sha256":"e97a55b52c7b1e03068943ed5d4b61d583e12f35b0923d1caee8674981ddc337","bytes":24939,"download":"/AGIJobsv0/examples/e97a55b52c7b1e03-runScenario.ts","source":"https://github.com/MontrealAI/AGIJobsv0/blob/5b4cebb309a83a7a6749d8911d8bf96a1921e042/demo/Trustless-Economic-Core-v0/scripts/runScenario.ts"},{"file":"demo/Trustless-Economic-Core-v0/README.md","content":"# AGI Jobs v0 (v2) — Demo → Trustless Economic Core v0\n\n> AGI Jobs v0 (v2) is our sovereign intelligence engine; this module extends that superintelligent machine with specialised capabilities for `demo/Trustless-Economic-Core-v0`.\n\n## Overview\n- **Path:** `demo/Trustless-Economic-Core-v0/README.md`\n- **Module Focus:** Anchors Demo → Trustless Economic Core v0 inside the AGI Jobs v0 (v2) lattice so teams can orchestrate economic, governance, and operational missions with deterministic guardrails.\n- **Integration Role:** Interfaces with the unified owner control plane, telemetry mesh, and contract registry to deliver end-to-end resilience.\n\n## Capabilities\n- Provides opinionated configuration and assets tailored to `demo/Trustless-Economic-Core-v0` while remaining interoperable with the global AGI Jobs v0 (v2) runtime.\n- Ships with safety-first defaults so non-technical operators can activate the experience without compromising security or compliance.\n- Publishes ready-to-automate hooks for CI, observability, and ledger reconciliation.\n\n## Systems Map\n```mermaid\nflowchart LR\n Operators((Mission Owners)) --> demo_Trustless_Economic_Core_v0[[Demo → Trustless Economic Core v0]]\n demo_Trustless_Economic_Core_v0 --> Core[[AGI Jobs v0 (v2) Core Intelligence]]\n Core --> Observability[[Unified CI / CD & Observability]]\n Core --> Governance[[Owner Control Plane]]\n```\n\n## Working With This Module\n1. From the repository root run `npm install` once to hydrate all workspaces.\n2. Inspect the scripts under `scripts/` or this module's `package.json` entry (where applicable) to discover targeted automation for `demo/Trustless-Economic-Core-v0`.\n3. Execute `npm test` and `npm run lint --if-present` before pushing to guarantee a fully green AGI Jobs v0 (v2) CI signal.\n4. Capture mission telemetry with `make operator:green` or the module-specific runbooks documented in [`OperatorRunbook.md`](../../OperatorRunbook.md).\n\n## Directory Guide\n### Key Directories\n- `contracts`\n- `reports`\n- `scripts`\n### Key Files\n- `.gitignore`\n- `hardhat.config.ts`\n\n## Quality & Governance\n- Every change must land through a pull request with all required checks green (unit, integration, linting, security scan).\n- Reference [`RUNBOOK.md`](../../RUNBOOK.md) and [`OperatorRunbook.md`](../../OperatorRunbook.md) for escalation patterns and owner approvals.\n- Keep secrets outside the tree; use the secure parameter stores wired to the AGI Jobs v0 (v2) guardian mesh.\n\n## Next Steps\n- Review this module's issue board for open automation, data, or research threads.\n- Link new deliverables back to the central manifest via `npm run release:manifest`.\n- Publish artefacts (dashboards, mermaid charts, datasets) into `reports/` for downstream intelligence alignment.\n","format":"text","sha256":"8d545163e5ab0061f2c5541f0c151a900ee1ae66473d4e6c2aa5c5661dab784b","bytes":2779,"download":"/AGIJobsv0/examples/8d545163e5ab0061-README.md","source":"https://github.com/MontrealAI/AGIJobsv0/blob/5b4cebb309a83a7a6749d8911d8bf96a1921e042/demo/Trustless-Economic-Core-v0/README.md"}]}
FROM READING TO A REPRODUCIBLE RUN
Try the selected path. Node.js workspace Run from the repository root after nvm install, nvm use and npm ci. Use the versions pinned in .nvmrc and package.json. Commands below describe the selected path; optional app/server packages can have their own locked dependencies.
Complete environment setup ↗ SELECTED EXECUTION PATH Copy
npx hardhat run --config demo/Trustless-Economic-Core-v0/hardhat.config.ts demo/Trustless-Economic-Core-v0/scripts/runScenario.ts --network hardhatWhat you should observe The local scenario writes trustless-core-report.json, trustless-core-report.md and trustless-core-dashboard.html under its reports directory.
The source inspector above reads bundled repository material. Local commands run separately on your computer. Recorded examples may contain historical timestamps, placeholders and simulated metrics.
MAKE IT YOUR OWN
One useful experiment. Compare the report with the transaction receipts and assertions. Explain which settlement properties are demonstrated and which require adversarial contract testing.
THE SYSTEM, MADE VISIBLE
Architecture & relationships Architecture diagram · source preserved below
View original Mermaid source flowchart LR
Operators((Mission Owners)) --> demo_Trustless_Economic_Core_v0[[Demo → Trustless Economic Core v0]]
demo_Trustless_Economic_Core_v0 --> Core[[AGI Jobs v0 (v2) Core Intelligence]]
Core --> Observability[[Unified CI / CD & Observability]]
Core --> Governance[[Owner Control Plane]]
WHEN SOMETHING DOESN’T MATCH
Troubleshooting A command or service fails Start at the first error, confirm the working directory and pinned toolchain, then follow the linked component guide. Optional packages and provider services have separate prerequisites.
A report looks successful but lacks evidence Check its source revision, configuration, timestamps and underlying events. Historical fixtures and generated plans do not prove a fresh execution.
TRACE THE CHECKS
Verification & next steps This directory has no standalone test source files. Follow the shared implementation and its behavioral tests before making correctness claims.
For live commissioning, consult the production readiness record .
EVERY VARIANT, PRESERVED
Complete document library REPRODUCE & INSPECT
Registered commands Run commands from the repository root after following this demo's guide. Network and owner actions require their documented setup.
No root-level launch command is associated with this source path. Follow the guide or source directory for its own entry point.
Full command catalog and troubleshooting ↗