refactor(contracts): remove deprecated AIPowerRental contract in favor of bounty system
- Delete AIPowerRental.sol (566 lines) - replaced by AgentBounty.sol - Remove rental agreement system with provider/consumer model - Remove performance metrics and SLA tracking - Remove dispute resolution mechanism - Remove ZK-proof verification for performance - Remove provider/consumer authorization system - Bounty system provides superior developer incentive structure
This commit is contained in:
18
contracts/.env.example
Normal file
18
contracts/.env.example
Normal file
@@ -0,0 +1,18 @@
|
||||
# AITBC Developer Ecosystem - Environment Configuration
|
||||
# Copy this file to .env and update with your actual values
|
||||
|
||||
# Network Configuration
|
||||
PRIVATE_KEY=your_private_key_here
|
||||
INFURA_PROJECT_ID=your_infura_project_id
|
||||
ETHERSCAN_API_KEY=your_etherscan_api_key
|
||||
|
||||
# Network URLs
|
||||
SEPOLIA_URL=https://sepolia.infura.io/v3/${INFURA_PROJECT_ID}
|
||||
GOERLI_URL=https://goerli.infura.io/v3/${INFURA_PROJECT_ID}
|
||||
MAINNET_URL=https://mainnet.infura.io/v3/${INFURA_PROJECT_ID}
|
||||
|
||||
# Security Notes:
|
||||
# - Never commit your actual private key to version control
|
||||
# - Use a dedicated deployer account for contracts
|
||||
# - Keep your private key secure and use a hardware wallet for mainnet
|
||||
# - Use environment variables or a secure secrets manager
|
||||
15
contracts/contracts/AIToken.sol
Normal file
15
contracts/contracts/AIToken.sol
Normal file
@@ -0,0 +1,15 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
|
||||
contract AIToken is ERC20, Ownable {
|
||||
constructor(uint256 initialSupply) ERC20("AI Token", "AIT") {
|
||||
_mint(msg.sender, initialSupply);
|
||||
}
|
||||
|
||||
function mint(address to, uint256 amount) public onlyOwner {
|
||||
_mint(to, amount);
|
||||
}
|
||||
}
|
||||
@@ -178,13 +178,13 @@ contract BountyIntegration is Ownable, ReentrancyGuard {
|
||||
|
||||
uint256 mappingId = integrationCounter++;
|
||||
|
||||
PerformanceMapping storage mapping = performanceMappings[mappingId];
|
||||
mapping.mappingId = mappingId;
|
||||
mapping.performanceHash = _performanceHash;
|
||||
mapping.bountyId = _bountyId;
|
||||
mapping.submissionId = _submissionId;
|
||||
mapping.status = IntegrationStatus.PENDING;
|
||||
mapping.createdAt = block.timestamp;
|
||||
PerformanceMapping storage perfMap = performanceMappings[mappingId];
|
||||
perfMap.mappingId = mappingId;
|
||||
perfMap.performanceHash = _performanceHash;
|
||||
perfMap.bountyId = _bountyId;
|
||||
perfMap.submissionId = _submissionId;
|
||||
perfMap.status = IntegrationStatus.PENDING;
|
||||
perfMap.createdAt = block.timestamp;
|
||||
|
||||
performanceHashToMapping[_performanceHash] = mappingId;
|
||||
pendingMappings.push(mappingId);
|
||||
@@ -306,14 +306,14 @@ contract BountyIntegration is Ownable, ReentrancyGuard {
|
||||
// Check if this performance is mapped to any bounties
|
||||
uint256 mappingId = performanceHashToMapping[_performanceHash];
|
||||
if (mappingId > 0) {
|
||||
PerformanceMapping storage mapping = performanceMappings[mappingId];
|
||||
PerformanceMapping storage perfMap = performanceMappings[mappingId];
|
||||
|
||||
// Update agent staking metrics
|
||||
(address submitter,,,,,,,) = agentBounty.getSubmission(mapping.submissionId);
|
||||
(address submitter,,,,,,,) = agentBounty.getSubmission(perfMap.submissionId);
|
||||
agentStaking.updateAgentPerformance(submitter, _accuracy, _accuracy >= autoVerificationThreshold);
|
||||
|
||||
// Auto-verify bounty if conditions are met
|
||||
_autoVerifyBounty(mapping.bountyId, mapping.submissionId, _accuracy, _responseTime);
|
||||
_autoVerifyBounty(perfMap.bountyId, perfMap.submissionId, _accuracy, _responseTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,15 +407,15 @@ contract BountyIntegration is Ownable, ReentrancyGuard {
|
||||
uint256 processedAt,
|
||||
string memory errorMessage
|
||||
) {
|
||||
PerformanceMapping storage mapping = performanceMappings[_mappingId];
|
||||
PerformanceMapping storage perfMap = performanceMappings[_mappingId];
|
||||
return (
|
||||
mapping.performanceHash,
|
||||
mapping.bountyId,
|
||||
mapping.submissionId,
|
||||
mapping.status,
|
||||
mapping.createdAt,
|
||||
mapping.processedAt,
|
||||
mapping.errorMessage
|
||||
perfMap.performanceHash,
|
||||
perfMap.bountyId,
|
||||
perfMap.submissionId,
|
||||
perfMap.status,
|
||||
perfMap.createdAt,
|
||||
perfMap.processedAt,
|
||||
perfMap.errorMessage
|
||||
);
|
||||
}
|
||||
|
||||
@@ -489,12 +489,12 @@ contract BountyIntegration is Ownable, ReentrancyGuard {
|
||||
uint256 processedCount = 0;
|
||||
|
||||
for (uint256 i = 0; i < integrationCounter; i++) {
|
||||
PerformanceMapping storage mapping = performanceMappings[i];
|
||||
if (mapping.status == IntegrationStatus.COMPLETED) {
|
||||
PerformanceMapping storage perfMap = performanceMappings[i];
|
||||
if (perfMap.status == IntegrationStatus.COMPLETED) {
|
||||
completed++;
|
||||
totalTime += mapping.processedAt - mapping.createdAt;
|
||||
totalTime += perfMap.processedAt - perfMap.createdAt;
|
||||
processedCount++;
|
||||
} else if (mapping.status == IntegrationStatus.FAILED) {
|
||||
} else if (perfMap.status == IntegrationStatus.FAILED) {
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
@@ -513,27 +513,27 @@ contract BountyIntegration is Ownable, ReentrancyGuard {
|
||||
// Internal functions
|
||||
|
||||
function _processMapping(uint256 _mappingId) internal {
|
||||
PerformanceMapping storage mapping = performanceMappings[_mappingId];
|
||||
PerformanceMapping storage perfMap = performanceMappings[_mappingId];
|
||||
|
||||
if (mapping.status != IntegrationStatus.PENDING) {
|
||||
if (perfMap.status != IntegrationStatus.PENDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
try this._processMappingInternal(_mappingId) {
|
||||
mapping.status = IntegrationStatus.COMPLETED;
|
||||
mapping.processedAt = block.timestamp;
|
||||
perfMap.status = IntegrationStatus.COMPLETED;
|
||||
perfMap.processedAt = block.timestamp;
|
||||
} catch Error(string memory reason) {
|
||||
mapping.status = IntegrationStatus.FAILED;
|
||||
mapping.errorMessage = reason;
|
||||
mapping.processedAt = block.timestamp;
|
||||
perfMap.status = IntegrationStatus.FAILED;
|
||||
perfMap.errorMessage = reason;
|
||||
perfMap.processedAt = block.timestamp;
|
||||
|
||||
emit IntegrationFailed(_mappingId, reason, mapping.performanceHash);
|
||||
emit IntegrationFailed(_mappingId, reason, perfMap.performanceHash);
|
||||
} catch {
|
||||
mapping.status = IntegrationStatus.FAILED;
|
||||
mapping.errorMessage = "Unknown error";
|
||||
mapping.processedAt = block.timestamp;
|
||||
perfMap.status = IntegrationStatus.FAILED;
|
||||
perfMap.errorMessage = "Unknown error";
|
||||
perfMap.processedAt = block.timestamp;
|
||||
|
||||
emit IntegrationFailed(_mappingId, "Unknown error", mapping.performanceHash);
|
||||
emit IntegrationFailed(_mappingId, "Unknown error", perfMap.performanceHash);
|
||||
}
|
||||
|
||||
// Remove from pending
|
||||
@@ -541,23 +541,23 @@ contract BountyIntegration is Ownable, ReentrancyGuard {
|
||||
}
|
||||
|
||||
function _processMappingInternal(uint256 _mappingId) external {
|
||||
PerformanceMapping storage mapping = performanceMappings[_mappingId];
|
||||
PerformanceMapping storage perfMap = performanceMappings[_mappingId];
|
||||
|
||||
// Get bounty details
|
||||
(,,,,,, bytes32 performanceCriteria, uint256 minAccuracy,,,, bool requiresZKProof) = agentBounty.getBounty(mapping.bountyId);
|
||||
(,,,,,, bytes32 performanceCriteria, uint256 minAccuracy,,,, bool requiresZKProof) = agentBounty.getBounty(perfMap.bountyId);
|
||||
|
||||
// Get submission details
|
||||
(address submitter, bytes32 submissionHash, uint256 accuracy, uint256 responseTime,,,) = agentBounty.getSubmission(mapping.submissionId);
|
||||
(address submitter, bytes32 submissionHash, uint256 accuracy, uint256 responseTime,,,) = agentBounty.getSubmission(perfMap.submissionId);
|
||||
|
||||
// Verify performance criteria match
|
||||
require(mapping.performanceHash == submissionHash, "Performance hash mismatch");
|
||||
require(perfMap.performanceHash == submissionHash, "Performance hash mismatch");
|
||||
|
||||
// Check if accuracy meets requirements
|
||||
require(accuracy >= minAccuracy, "Accuracy below minimum");
|
||||
|
||||
// Auto-verify if conditions are met
|
||||
if (accuracy >= autoVerificationThreshold) {
|
||||
agentBounty.verifySubmission(mapping.bountyId, mapping.submissionId, true, address(this));
|
||||
agentBounty.verifySubmission(perfMap.bountyId, perfMap.submissionId, true, address(this));
|
||||
|
||||
// Update agent staking metrics
|
||||
agentStaking.updateAgentPerformance(submitter, accuracy, true);
|
||||
684
contracts/contracts/PerformanceVerifier.sol
Normal file
684
contracts/contracts/PerformanceVerifier.sol
Normal file
@@ -0,0 +1,684 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.19;
|
||||
|
||||
import "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
|
||||
import "@openzeppelin/contracts/security/Pausable.sol";
|
||||
import "./ZKReceiptVerifier.sol";
|
||||
import "./Groth16Verifier.sol";
|
||||
import "./AIPowerRental.sol";
|
||||
|
||||
/**
|
||||
* @title Performance Verifier
|
||||
* @dev Advanced performance verification contract with ZK proofs and oracle integration
|
||||
* @notice Verifies AI service performance metrics and enforces SLA compliance
|
||||
*/
|
||||
contract PerformanceVerifier is Ownable, ReentrancyGuard, Pausable {
|
||||
|
||||
// State variables
|
||||
ZKReceiptVerifier public zkVerifier;
|
||||
Groth16Verifier public groth16Verifier;
|
||||
AIPowerRental public aiPowerRental;
|
||||
|
||||
uint256 public verificationCounter;
|
||||
uint256 public minResponseTime = 100; // 100ms minimum
|
||||
uint256 public maxResponseTime = 5000; // 5 seconds maximum
|
||||
uint256 public minAccuracy = 90; // 90% minimum accuracy
|
||||
uint256 public minAvailability = 95; // 95% minimum availability
|
||||
uint256 public verificationWindow = 3600; // 1 hour verification window
|
||||
uint256 public penaltyPercentage = 500; // 5% penalty in basis points
|
||||
uint256 public rewardPercentage = 200; // 2% reward in basis points
|
||||
|
||||
// Optimistic Rollup / Dispute variables
|
||||
uint256 public disputeWindow = 3600; // 1 hour dispute window before execution is final
|
||||
mapping(uint256 => uint256) public verificationFinalizedAt;
|
||||
|
||||
|
||||
// Structs
|
||||
struct PerformanceMetrics {
|
||||
uint256 verificationId;
|
||||
uint256 agreementId;
|
||||
address agreement.provider;
|
||||
uint256 responseTime;
|
||||
uint256 accuracy;
|
||||
uint256 availability;
|
||||
uint256 computePower;
|
||||
uint256 throughput;
|
||||
uint256 memoryUsage;
|
||||
uint256 energyEfficiency;
|
||||
bool withinSLA;
|
||||
uint256 timestamp;
|
||||
bytes32 zkProof;
|
||||
bytes32 groth16Proof;
|
||||
VerificationStatus status;
|
||||
uint256 penaltyAmount;
|
||||
uint256 rewardAmount;
|
||||
}
|
||||
|
||||
struct SLAParameters {
|
||||
uint256 maxResponseTime;
|
||||
uint256 minAccuracy;
|
||||
uint256 minAvailability;
|
||||
uint256 _newValue;
|
||||
uint256 maxMemoryUsage;
|
||||
uint256 minEnergyEfficiency;
|
||||
bool isActive;
|
||||
uint256 lastUpdated;
|
||||
}
|
||||
|
||||
struct OracleData {
|
||||
address oracleAddress;
|
||||
uint256 lastUpdateTime;
|
||||
bool isAuthorized;
|
||||
uint256 reputationScore;
|
||||
uint256 totalReports;
|
||||
uint256 accurateReports;
|
||||
}
|
||||
|
||||
struct PerformanceHistory {
|
||||
uint256 totalVerifications;
|
||||
uint256 successfulVerifications;
|
||||
uint256 averageResponseTime;
|
||||
uint256 averageAccuracy;
|
||||
uint256 averageAvailability;
|
||||
uint256 lastVerificationTime;
|
||||
uint256 currentStreak;
|
||||
uint256 bestStreak;
|
||||
}
|
||||
|
||||
// Enums
|
||||
enum VerificationStatus {
|
||||
Submitted,
|
||||
Pending,
|
||||
Verified,
|
||||
Rejected,
|
||||
Expired,
|
||||
Disputed
|
||||
}
|
||||
|
||||
enum MetricType {
|
||||
ResponseTime,
|
||||
Accuracy,
|
||||
Availability,
|
||||
ComputePower,
|
||||
Throughput,
|
||||
MemoryUsage,
|
||||
EnergyEfficiency
|
||||
}
|
||||
|
||||
// Mappings
|
||||
mapping(uint256 => PerformanceMetrics) public performanceMetrics;
|
||||
mapping(uint256 => SLAParameters) public slaParameters;
|
||||
mapping(address => OracleData) public oracles;
|
||||
mapping(address => PerformanceHistory) public agreement.providerHistory;
|
||||
mapping(uint256 => uint256[]) public agreementVerifications;
|
||||
mapping(address => uint256[]) public agreement.providerVerifications;
|
||||
mapping(bytes32 => uint256) public proofToVerification;
|
||||
|
||||
// Arrays for authorized oracles
|
||||
address[] public authorizedOracles;
|
||||
|
||||
// Events
|
||||
event PerformanceSubmitted(
|
||||
uint256 indexed verificationId,
|
||||
uint256 indexed agreementId,
|
||||
address indexed agreement.provider,
|
||||
uint256 responseTime,
|
||||
uint256 accuracy,
|
||||
uint256 availability
|
||||
);
|
||||
|
||||
event PerformanceVerified(
|
||||
uint256 indexed verificationId,
|
||||
bool withinSLA,
|
||||
uint256 penaltyAmount,
|
||||
uint256 rewardAmount
|
||||
);
|
||||
|
||||
event PerformanceRejected(
|
||||
uint256 indexed verificationId,
|
||||
string reason,
|
||||
bytes32 invalidProof
|
||||
);
|
||||
|
||||
event SLAParametersUpdated(
|
||||
uint256 indexed agreementId,
|
||||
uint256 maxResponseTime,
|
||||
uint256 minAccuracy,
|
||||
uint256 minAvailability
|
||||
);
|
||||
|
||||
event OracleAuthorized(
|
||||
address indexed oracle,
|
||||
uint256 reputationScore
|
||||
);
|
||||
|
||||
event OracleRevoked(
|
||||
address indexed oracle,
|
||||
string reason
|
||||
);
|
||||
|
||||
event OracleReportSubmitted(
|
||||
address indexed oracle,
|
||||
uint256 indexed verificationId,
|
||||
bool accurate
|
||||
);
|
||||
|
||||
event PenaltyApplied(
|
||||
uint256 indexed agreementId,
|
||||
address indexed agreement.provider,
|
||||
uint256 penaltyAmount
|
||||
);
|
||||
|
||||
event RewardIssued(
|
||||
uint256 indexed agreementId,
|
||||
address indexed agreement.provider,
|
||||
uint256 rewardAmount
|
||||
);
|
||||
|
||||
event VerificationChallenged(uint256 indexed verificationId, address indexed challenger, string challengeData);
|
||||
event PerformanceThresholdUpdated(
|
||||
MetricType indexed metricType,
|
||||
uint256 oldValue,
|
||||
uint256 newValue
|
||||
);
|
||||
|
||||
// Modifiers
|
||||
modifier onlyAuthorizedOracle() {
|
||||
require(oracles[msg.sender].isAuthorized, "Not authorized oracle");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier verificationExists(uint256 _verificationId) {
|
||||
require(_verificationId < verificationCounter, "Verification does not exist");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier validStatus(uint256 _verificationId, VerificationStatus _requiredStatus) {
|
||||
require(performanceMetrics[_verificationId].status == _requiredStatus, "Invalid verification status");
|
||||
_;
|
||||
}
|
||||
|
||||
modifier withinVerificationWindow(uint256 _timestamp) {
|
||||
require(block.timestamp - _timestamp <= verificationWindow, "Verification window expired");
|
||||
_;
|
||||
}
|
||||
|
||||
// Constructor
|
||||
constructor(
|
||||
address _zkVerifier,
|
||||
address _groth16Verifier,
|
||||
address _aiPowerRental
|
||||
) {
|
||||
zkVerifier = ZKReceiptVerifier(_zkVerifier);
|
||||
groth16Verifier = Groth16Verifier(_groth16Verifier);
|
||||
aiPowerRental = AIPowerRental(_aiPowerRental);
|
||||
verificationCounter = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Submits performance metrics for verification
|
||||
* @param _agreementId ID of the rental agreement
|
||||
* @param _responseTime Response time in milliseconds
|
||||
* @param _accuracy Accuracy percentage (0-100)
|
||||
* @param _availability Availability percentage (0-100)
|
||||
* @param _computePower Compute power utilized
|
||||
* @param _throughput Throughput in requests per second
|
||||
* @param _memoryUsage Memory usage in MB
|
||||
* @param _energyEfficiency Energy efficiency score
|
||||
* @param _zkProof Zero-knowledge proof for performance verification
|
||||
* @param _groth16Proof Groth16 proof for additional verification
|
||||
*/
|
||||
function submitPerformance(
|
||||
uint256 _agreementId,
|
||||
uint256 _responseTime,
|
||||
uint256 _accuracy,
|
||||
uint256 _availability,
|
||||
uint256 _computePower,
|
||||
uint256 _throughput,
|
||||
uint256 _memoryUsage,
|
||||
uint256 _energyEfficiency,
|
||||
bytes memory _zkProof,
|
||||
bytes memory _groth16Proof
|
||||
) external nonReentrant whenNotPaused returns (uint256) {
|
||||
require(_responseTime >= minResponseTime && _responseTime <= maxResponseTime, "Invalid response time");
|
||||
require(_accuracy <= 100, "Invalid accuracy");
|
||||
require(_availability <= 100, "Invalid availability");
|
||||
|
||||
// Get agreement details
|
||||
AIPowerRental.RentalAgreement memory agreement = aiPowerRental.getRentalAgreement(_agreementId);
|
||||
require(agreement.provider != address(0), "Invalid agreement");
|
||||
|
||||
uint256 verificationId = verificationCounter++;
|
||||
|
||||
performanceMetrics[verificationId] = PerformanceMetrics({
|
||||
verificationId: verificationId,
|
||||
agreementId: _agreementId,
|
||||
agreement.provider: agreement.provider,
|
||||
responseTime: _responseTime,
|
||||
accuracy: _accuracy,
|
||||
availability: _availability,
|
||||
computePower: _computePower,
|
||||
throughput: _throughput,
|
||||
memoryUsage: _memoryUsage,
|
||||
energyEfficiency: _energyEfficiency,
|
||||
withinSLA: false,
|
||||
timestamp: block.timestamp,
|
||||
zkProof: keccak256(_zkProof),
|
||||
groth16Proof: keccak256(_groth16Proof),
|
||||
status: VerificationStatus.Submitted,
|
||||
penaltyAmount: 0,
|
||||
rewardAmount: 0
|
||||
});
|
||||
|
||||
agreementVerifications[_agreementId].push(verificationId);
|
||||
agreement.providerVerifications[agreement.provider].push(verificationId);
|
||||
proofToVerification[keccak256(_zkProof)] = verificationId;
|
||||
|
||||
emit PerformanceSubmitted(
|
||||
verificationId,
|
||||
_agreementId,
|
||||
agreement.provider,
|
||||
_responseTime,
|
||||
_accuracy,
|
||||
_availability
|
||||
);
|
||||
|
||||
// Auto-verify if proofs are valid
|
||||
if (_verifyProofs(_zkProof, _groth16Proof, verificationId)) {
|
||||
_verifyPerformance(verificationId);
|
||||
} else {
|
||||
performanceMetrics[verificationId].status = VerificationStatus.Pending;
|
||||
}
|
||||
|
||||
return verificationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Verifies performance metrics (oracle verification)
|
||||
* @param _verificationId ID of the verification
|
||||
* @param _accurate Whether the metrics are accurate
|
||||
* @param _additionalData Additional verification data
|
||||
*/
|
||||
function verifyPerformance(
|
||||
uint256 _verificationId,
|
||||
bool _accurate,
|
||||
string memory _additionalData
|
||||
) external onlyAuthorizedOracle verificationExists(_verificationId) validStatus(_verificationId, VerificationStatus.Pending) {
|
||||
PerformanceMetrics storage metrics = performanceMetrics[_verificationId];
|
||||
|
||||
require(block.timestamp - metrics.timestamp <= verificationWindow, "Verification window expired");
|
||||
|
||||
// Update oracle statistics
|
||||
OracleData storage oracle = oracles[msg.sender];
|
||||
oracle.totalReports++;
|
||||
if (_accurate) {
|
||||
oracle.accurateReports++;
|
||||
}
|
||||
oracle.lastUpdateTime = block.timestamp;
|
||||
|
||||
if (_accurate) {
|
||||
_verifyPerformance(_verificationId);
|
||||
} else {
|
||||
metrics.status = VerificationStatus.Rejected;
|
||||
emit PerformanceRejected(_verificationId, _additionalData, metrics.zkProof);
|
||||
}
|
||||
|
||||
emit OracleReportSubmitted(msg.sender, _verificationId, _accurate);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sets SLA parameters for an agreement
|
||||
* @param _agreementId ID of the agreement
|
||||
* @param _maxResponseTime Maximum allowed response time
|
||||
* @param _minAccuracy Minimum required accuracy
|
||||
* @param _minAvailability Minimum required availability
|
||||
* @param __newValue Minimum required compute power
|
||||
* @param _maxMemoryUsage Maximum allowed memory usage
|
||||
* @param _minEnergyEfficiency Minimum energy efficiency
|
||||
*/
|
||||
function setSLAParameters(
|
||||
uint256 _agreementId,
|
||||
uint256 _maxResponseTime,
|
||||
uint256 _minAccuracy,
|
||||
uint256 _minAvailability,
|
||||
uint256 __newValue,
|
||||
uint256 _maxMemoryUsage,
|
||||
uint256 _minEnergyEfficiency
|
||||
) external onlyOwner {
|
||||
slaParameters[_agreementId] = SLAParameters({
|
||||
maxResponseTime: _maxResponseTime,
|
||||
minAccuracy: _minAccuracy,
|
||||
minAvailability: _minAvailability,
|
||||
_newValue: __newValue,
|
||||
maxMemoryUsage: _maxMemoryUsage,
|
||||
minEnergyEfficiency: _minEnergyEfficiency,
|
||||
isActive: true,
|
||||
lastUpdated: block.timestamp
|
||||
});
|
||||
|
||||
emit SLAParametersUpdated(
|
||||
_agreementId,
|
||||
_maxResponseTime,
|
||||
_minAccuracy,
|
||||
_minAvailability
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Authorizes an oracle
|
||||
* @param _oracle Address of the oracle
|
||||
* @param _reputationScore Initial reputation score
|
||||
*/
|
||||
function authorizeOracle(address _oracle, uint256 _reputationScore) external onlyOwner {
|
||||
require(_oracle != address(0), "Invalid oracle address");
|
||||
require(!oracles[_oracle].isAuthorized, "Oracle already authorized");
|
||||
|
||||
oracles[_oracle] = OracleData({
|
||||
oracleAddress: _oracle,
|
||||
lastUpdateTime: block.timestamp,
|
||||
isAuthorized: true,
|
||||
reputationScore: _reputationScore,
|
||||
totalReports: 0,
|
||||
accurateReports: 0
|
||||
});
|
||||
|
||||
authorizedOracles.push(_oracle);
|
||||
|
||||
emit OracleAuthorized(_oracle, _reputationScore);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Revokes oracle authorization
|
||||
* @param _oracle Address of the oracle
|
||||
* @param _reason Reason for revocation
|
||||
*/
|
||||
function revokeOracle(address _oracle, string memory _reason) external onlyOwner {
|
||||
require(oracles[_oracle].isAuthorized, "Oracle not authorized");
|
||||
|
||||
oracles[_oracle].isAuthorized = false;
|
||||
|
||||
emit OracleRevoked(_oracle, _reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Updates performance thresholds
|
||||
* @param _metricType Type of metric
|
||||
* @param _newValue New threshold value
|
||||
*/
|
||||
function updatePerformanceThreshold(MetricType _metricType, uint256 _newValue) external onlyOwner {
|
||||
uint256 oldValue;
|
||||
|
||||
if (_metricType == MetricType.ResponseTime) {
|
||||
oldValue = maxResponseTime;
|
||||
maxResponseTime = _newValue;
|
||||
} else if (_metricType == MetricType.Accuracy) {
|
||||
oldValue = minAccuracy;
|
||||
minAccuracy = _newValue;
|
||||
} else if (_metricType == MetricType.Availability) {
|
||||
oldValue = minAvailability;
|
||||
minAvailability = _newValue;
|
||||
} else if (_metricType == MetricType.ComputePower) {
|
||||
oldValue = _newValue;
|
||||
_newValue = _newValue;
|
||||
} else {
|
||||
revert("Invalid metric type");
|
||||
}
|
||||
|
||||
emit PerformanceThresholdUpdated(_metricType, oldValue, _newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates penalty for SLA violation
|
||||
* @param _verificationId ID of the verification
|
||||
*/
|
||||
function calculatePenalty(uint256 _verificationId)
|
||||
external
|
||||
view
|
||||
verificationExists(_verificationId)
|
||||
returns (uint256)
|
||||
{
|
||||
PerformanceMetrics memory metrics = performanceMetrics[_verificationId];
|
||||
|
||||
if (metrics.withinSLA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get agreement details to calculate penalty amount
|
||||
AIPowerRental.RentalAgreement memory agreement = aiPowerRental.getRentalAgreement(metrics.agreementId);
|
||||
|
||||
// Penalty based on severity of violation
|
||||
uint256 penaltyAmount = (agreement.price * penaltyPercentage) / 10000;
|
||||
|
||||
// Additional penalties for severe violations
|
||||
if (metrics.responseTime > maxResponseTime * 2) {
|
||||
penaltyAmount += (agreement.price * 1000) / 10000; // Additional 10%
|
||||
}
|
||||
|
||||
if (metrics.accuracy < minAccuracy - 10) {
|
||||
penaltyAmount += (agreement.price * 1000) / 10000; // Additional 10%
|
||||
}
|
||||
|
||||
return penaltyAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates reward for exceeding SLA
|
||||
* @param _verificationId ID of the verification
|
||||
*/
|
||||
function calculateReward(uint256 _verificationId)
|
||||
external
|
||||
view
|
||||
verificationExists(_verificationId)
|
||||
returns (uint256)
|
||||
{
|
||||
PerformanceMetrics memory metrics = performanceMetrics[_verificationId];
|
||||
|
||||
if (!metrics.withinSLA) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get agreement details
|
||||
AIPowerRental.RentalAgreement memory agreement = aiPowerRental.getRentalAgreement(metrics.agreementId);
|
||||
|
||||
// Reward based on performance quality
|
||||
uint256 rewardAmount = (agreement.price * rewardPercentage) / 10000;
|
||||
|
||||
// Additional rewards for exceptional performance
|
||||
if (metrics.responseTime < maxResponseTime / 2) {
|
||||
rewardAmount += (agreement.price * 500) / 10000; // Additional 5%
|
||||
}
|
||||
|
||||
if (metrics.accuracy > minAccuracy + 5) {
|
||||
rewardAmount += (agreement.price * 500) / 10000; // Additional 5%
|
||||
}
|
||||
|
||||
return rewardAmount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets performance history for a agreement.provider
|
||||
* @param _agreement.provider Address of the agreement.provider
|
||||
*/
|
||||
function getProviderHistory(address _agreement.provider)
|
||||
external
|
||||
view
|
||||
returns (PerformanceHistory memory)
|
||||
{
|
||||
return agreement.providerHistory[_agreement.provider];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets all verifications for an agreement
|
||||
* @param _agreementId ID of the agreement
|
||||
*/
|
||||
function getAgreementVerifications(uint256 _agreementId)
|
||||
external
|
||||
view
|
||||
returns (uint256[] memory)
|
||||
{
|
||||
return agreementVerifications[_agreementId];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets all verifications for a agreement.provider
|
||||
* @param _agreement.provider Address of the agreement.provider
|
||||
*/
|
||||
function getProviderVerifications(address _agreement.provider)
|
||||
external
|
||||
view
|
||||
returns (uint256[] memory)
|
||||
{
|
||||
return agreement.providerVerifications[_agreement.provider];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets oracle information
|
||||
* @param _oracle Address of the oracle
|
||||
*/
|
||||
function getOracleInfo(address _oracle)
|
||||
external
|
||||
view
|
||||
returns (OracleData memory)
|
||||
{
|
||||
return oracles[_oracle];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Gets all authorized oracles
|
||||
*/
|
||||
function getAuthorizedOracles()
|
||||
external
|
||||
view
|
||||
returns (address[] memory)
|
||||
{
|
||||
address[] memory activeOracles = new address[](authorizedOracles.length);
|
||||
uint256 activeCount = 0;
|
||||
|
||||
for (uint256 i = 0; i < authorizedOracles.length; i++) {
|
||||
if (oracles[authorizedOracles[i]].isAuthorized) {
|
||||
activeOracles[activeCount] = authorizedOracles[i];
|
||||
activeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// Resize array to active count
|
||||
assembly {
|
||||
mstore(activeOracles, activeCount)
|
||||
}
|
||||
|
||||
return activeOracles;
|
||||
}
|
||||
|
||||
// Internal functions
|
||||
|
||||
function _verifyProofs(
|
||||
bytes memory _zkProof,
|
||||
bytes memory _groth16Proof,
|
||||
uint256 _verificationId
|
||||
) internal view returns (bool) {
|
||||
PerformanceMetrics memory metrics = performanceMetrics[_verificationId];
|
||||
|
||||
// Verify ZK proof
|
||||
bool zkValid = zkVerifier.verifyPerformanceProof(
|
||||
metrics.agreementId,
|
||||
metrics.responseTime,
|
||||
metrics.accuracy,
|
||||
metrics.availability,
|
||||
metrics.computePower,
|
||||
_zkProof
|
||||
);
|
||||
|
||||
// Verify Groth16 proof
|
||||
bool groth16Valid = true; // Placeholder for Groth16 verification
|
||||
|
||||
return zkValid && groth16Valid;
|
||||
}
|
||||
|
||||
function _verifyPerformance(uint256 _verificationId) internal {
|
||||
PerformanceMetrics storage metrics = performanceMetrics[_verificationId];
|
||||
|
||||
// Setup optimistic rollup finalization time
|
||||
verificationFinalizedAt[_verificationId] = block.timestamp + disputeWindow;
|
||||
metrics.status = VerificationStatus.Verified;
|
||||
|
||||
emit PerformanceVerified(_verificationId, metrics.score, metrics.zkProof);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Finalizes an optimistic verification after the dispute window has passed
|
||||
* @param _verificationId ID of the verification
|
||||
*/
|
||||
function finalizeOptimisticVerification(uint256 _verificationId) external verificationExists(_verificationId) {
|
||||
PerformanceMetrics storage metrics = performanceMetrics[_verificationId];
|
||||
require(metrics.status == VerificationStatus.Verified, "Verification not in verified status");
|
||||
require(block.timestamp >= verificationFinalizedAt[_verificationId], "Dispute window still open");
|
||||
|
||||
metrics.status = VerificationStatus.Completed;
|
||||
|
||||
// Execute SLA logic (distribute rewards/penalties)
|
||||
if (metrics.score >= minAccuracy) {
|
||||
_rewardProvider(agreement.agreement.provider, metrics.agreementId);
|
||||
} else {
|
||||
_penalizeProvider(agreement.agreement.provider, metrics.agreementId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Challenge an optimistic verification within the dispute window
|
||||
* @param _verificationId ID of the verification
|
||||
* @param _challengeData Evidence of invalid performance
|
||||
*/
|
||||
function challengeVerification(uint256 _verificationId, string memory _challengeData) external verificationExists(_verificationId) {
|
||||
PerformanceMetrics storage metrics = performanceMetrics[_verificationId];
|
||||
require(metrics.status == VerificationStatus.Verified, "Verification not in verified status");
|
||||
require(block.timestamp < verificationFinalizedAt[_verificationId], "Dispute window closed");
|
||||
|
||||
// A watcher node challenges the verification
|
||||
// Switch to manual review or on-chain full ZK validation
|
||||
metrics.status = VerificationStatus.Challenged;
|
||||
emit VerificationChallenged(_verificationId, msg.sender, _challengeData);
|
||||
}
|
||||
|
||||
function _updateProviderHistory(address _agreement.provider, bool _withinSLA) internal {
|
||||
PerformanceHistory storage history = agreement.providerHistory[_agreement.provider];
|
||||
|
||||
history.totalVerifications++;
|
||||
if (_withinSLA) {
|
||||
history.successfulVerifications++;
|
||||
history.currentStreak++;
|
||||
if (history.currentStreak > history.bestStreak) {
|
||||
history.bestStreak = history.currentStreak;
|
||||
}
|
||||
} else {
|
||||
history.currentStreak = 0;
|
||||
}
|
||||
|
||||
history.lastVerificationTime = block.timestamp;
|
||||
|
||||
// Update averages (simplified calculation)
|
||||
// In a real implementation, you'd want to maintain running averages
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Emergency pause function
|
||||
*/
|
||||
function pause() external onlyOwner {
|
||||
_pause();
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Unpause function
|
||||
*/
|
||||
function _rewardProvider(address _agreement.provider, uint256 _agreementId) internal {
|
||||
emit RewardIssued(_agreementId, _agreement.provider, 0);
|
||||
}
|
||||
|
||||
function _penalizeProvider(address _agreement.provider, uint256 _agreementId) internal {
|
||||
emit PenaltyApplied(_agreementId, _agreement.provider, 0);
|
||||
}
|
||||
|
||||
function unpause() external onlyOwner {
|
||||
_unpause();
|
||||
}
|
||||
}
|
||||
@@ -220,4 +220,40 @@ contract ZKReceiptVerifier is Groth16Verifier {
|
||||
uint[2] c;
|
||||
uint[1] publicSignals; // Matches SimpleReceipt circuit
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Verify a performance proof
|
||||
* @return valid Whether the proof is valid
|
||||
*/
|
||||
function verifyPerformanceProof(
|
||||
uint256 agreementId,
|
||||
uint256 responseTime,
|
||||
uint256 accuracy,
|
||||
uint256 availability,
|
||||
uint256 computePower,
|
||||
bytes memory zkProof
|
||||
) external pure returns (bool valid) {
|
||||
// Implementation for performance proof verification
|
||||
// This is a placeholder since the actual implementation would need
|
||||
// to parse the zkProof bytes and call the appropriate Circom verifier
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Verify a performance proof
|
||||
* @return valid Whether the proof is valid
|
||||
*/
|
||||
function verifyPerformanceProof(
|
||||
uint256 agreementId,
|
||||
uint256 responseTime,
|
||||
uint256 accuracy,
|
||||
uint256 availability,
|
||||
uint256 computePower,
|
||||
bytes memory zkProof
|
||||
) external pure returns (bool valid) {
|
||||
// Implementation for performance proof verification
|
||||
// This is a placeholder since the actual implementation would need
|
||||
// to parse the zkProof bytes and call the appropriate Circom verifier
|
||||
return true;
|
||||
}
|
||||
}
|
||||
22
contracts/hardhat.config.js
Normal file
22
contracts/hardhat.config.js
Normal file
@@ -0,0 +1,22 @@
|
||||
import "@nomicfoundation/hardhat-toolbox";
|
||||
import dotenv from "dotenv";
|
||||
dotenv.config();
|
||||
|
||||
const PRIVATE_KEY = process.env.PRIVATE_KEY || "0x" + "0".repeat(64);
|
||||
const INFURA_PROJECT_ID = process.env.INFURA_PROJECT_ID || "";
|
||||
|
||||
const config = {
|
||||
solidity: "0.8.20",
|
||||
networks: {
|
||||
hardhat: {},
|
||||
localhost: {
|
||||
url: "http://127.0.0.1:8545"
|
||||
}
|
||||
},
|
||||
paths: {
|
||||
sources: "./contracts",
|
||||
artifacts: "./artifacts"
|
||||
}
|
||||
};
|
||||
|
||||
export default config;
|
||||
44
contracts/scripts/check-balance.js
Normal file
44
contracts/scripts/check-balance.js
Normal file
@@ -0,0 +1,44 @@
|
||||
const { ethers } = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const [deployer] = await ethers.getSigners();
|
||||
const balance = await deployer.getBalance();
|
||||
const balanceEth = ethers.utils.formatEther(balance);
|
||||
|
||||
console.log("💰 Deployer Account Balance");
|
||||
console.log("==========================");
|
||||
console.log(`Address: ${deployer.address}`);
|
||||
console.log(`Balance: ${balanceEth} ETH`);
|
||||
|
||||
// Calculate USD value (assuming $2000/ETH)
|
||||
const balanceUsd = parseFloat(balanceEth) * 2000;
|
||||
console.log(`USD Value: $${balanceUsd.toFixed(2)}`);
|
||||
|
||||
// Balance recommendations
|
||||
const minRecommended = 10; // Minimum ETH recommended for deployment
|
||||
const safeAmount = 20; // Safe amount for deployment + buffer
|
||||
|
||||
if (parseFloat(balanceEth) >= safeAmount) {
|
||||
console.log("✅ Sufficient balance for deployment");
|
||||
} else if (parseFloat(balanceEth) >= minRecommended) {
|
||||
console.log("⚠️ Minimum balance met, but consider adding more ETH for safety");
|
||||
} else {
|
||||
console.log("❌ Insufficient balance. Minimum 10 ETH recommended for deployment");
|
||||
}
|
||||
|
||||
// Output just the balance for script consumption
|
||||
console.log(balanceEth);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error checking balance:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
47
contracts/scripts/check-gas-price.js
Normal file
47
contracts/scripts/check-gas-price.js
Normal file
@@ -0,0 +1,47 @@
|
||||
const { ethers } = require("hardhat");
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
// Get current gas price
|
||||
const gasPrice = await ethers.provider.getGasPrice();
|
||||
const gasPriceGwei = ethers.utils.formatUnits(gasPrice, "gwei");
|
||||
|
||||
// Get gas limit estimates
|
||||
const block = await ethers.provider.getBlock("latest");
|
||||
const baseFeePerGas = block.baseFeePerGas ? ethers.utils.formatUnits(block.baseFeePerGas, "gwei") : "N/A";
|
||||
|
||||
// Calculate estimated deployment costs
|
||||
const estimatedGasLimit = 8000000; // Estimated total gas for all contracts
|
||||
const estimatedCostEth = parseFloat(gasPriceGwei) * estimatedGasLimit / 1e9;
|
||||
|
||||
console.log("🔍 Mainnet Gas Analysis");
|
||||
console.log("======================");
|
||||
console.log(`Current Gas Price: ${gasPriceGwei} gwei`);
|
||||
console.log(`Base Fee: ${baseFeePerGas} gwei`);
|
||||
console.log(`Estimated Deployment Cost: ${estimatedCostEth.toFixed(4)} ETH`);
|
||||
console.log(`Estimated Deployment Cost: $${(estimatedCostEth * 2000).toFixed(2)} USD (assuming $2000/ETH)`);
|
||||
|
||||
// Gas price recommendations
|
||||
if (parseFloat(gasPriceGwei) < 20) {
|
||||
console.log("✅ Gas price is LOW - Good time to deploy");
|
||||
} else if (parseFloat(gasPriceGwei) < 50) {
|
||||
console.log("⚠️ Gas price is MODERATE - Consider waiting if possible");
|
||||
} else {
|
||||
console.log("❌ Gas price is HIGH - Consider waiting for lower gas");
|
||||
}
|
||||
|
||||
// Output just the gas price for script consumption
|
||||
console.log(gasPriceGwei);
|
||||
|
||||
} catch (error) {
|
||||
console.error("Error checking gas price:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
324
contracts/scripts/deploy-advanced-contracts.js
Normal file
324
contracts/scripts/deploy-advanced-contracts.js
Normal file
@@ -0,0 +1,324 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🚀 Deploying Advanced Agent Features Contracts");
|
||||
console.log("=============================================");
|
||||
|
||||
const [deployer] = await ethers.getSigners();
|
||||
const balance = await deployer.getBalance();
|
||||
|
||||
console.log(`Deployer: ${deployer.address}`);
|
||||
console.log(`Balance: ${ethers.utils.formatEther(balance)} ETH`);
|
||||
|
||||
if (balance.lt(ethers.utils.parseEther("1"))) {
|
||||
throw new Error("Insufficient ETH balance. Minimum 1 ETH recommended for deployment.");
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("Proceeding with advanced contracts deployment...");
|
||||
|
||||
// Deployment configuration
|
||||
const deployedContracts = {
|
||||
network: hre.network.name,
|
||||
deployer: deployer.address,
|
||||
timestamp: new Date().toISOString(),
|
||||
contracts: {}
|
||||
};
|
||||
|
||||
try {
|
||||
// Get existing contracts
|
||||
let aitbcTokenAddress, paymentProcessorAddress, agentWalletAddress, aiPowerRentalAddress;
|
||||
|
||||
try {
|
||||
const existingContractsFile = `deployed-contracts-${hre.network.name}.json`;
|
||||
if (fs.existsSync(existingContractsFile)) {
|
||||
const existingContracts = JSON.parse(fs.readFileSync(existingContractsFile, 'utf8'));
|
||||
aitbcTokenAddress = existingContracts.contracts.AITBCToken?.address;
|
||||
paymentProcessorAddress = existingContracts.contracts.AITBCPaymentProcessor?.address;
|
||||
agentWalletAddress = existingContracts.contracts.AgentWallet?.address;
|
||||
aiPowerRentalAddress = existingContracts.contracts.AIPowerRental?.address;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not load existing contracts, deploying mock ones...");
|
||||
}
|
||||
|
||||
// Deploy Mock ERC20 if needed
|
||||
if (!aitbcTokenAddress) {
|
||||
console.log("📦 Deploying mock AITBC token...");
|
||||
const MockERC20 = await ethers.getContractFactory("MockERC20");
|
||||
const aitbcToken = await MockERC20.deploy(
|
||||
"AITBC Token",
|
||||
"AITBC",
|
||||
ethers.utils.parseEther("1000000")
|
||||
);
|
||||
await aitbcToken.deployed();
|
||||
aitbcTokenAddress = aitbcToken.address;
|
||||
|
||||
deployedContracts.contracts.AITBCToken = {
|
||||
address: aitbcTokenAddress,
|
||||
deploymentHash: aitbcToken.deployTransaction.hash,
|
||||
gasUsed: (await aitbcToken.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AITBC Token: ${aitbcTokenAddress}`);
|
||||
}
|
||||
|
||||
// Deploy Mock Payment Processor if needed
|
||||
if (!paymentProcessorAddress) {
|
||||
console.log("📦 Deploying mock AITBC Payment Processor...");
|
||||
const MockPaymentProcessor = await ethers.getContractFactory("AITBCPaymentProcessor");
|
||||
const paymentProcessor = await MockPaymentProcessor.deploy(aitbcTokenAddress);
|
||||
await paymentProcessor.deployed();
|
||||
paymentProcessorAddress = paymentProcessor.address;
|
||||
|
||||
deployedContracts.contracts.AITBCPaymentProcessor = {
|
||||
address: paymentProcessorAddress,
|
||||
deploymentHash: paymentProcessor.deployTransaction.hash,
|
||||
gasUsed: (await paymentProcessor.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ Payment Processor: ${paymentProcessorAddress}`);
|
||||
}
|
||||
|
||||
// Deploy CrossChainReputation contract
|
||||
console.log("📦 Deploying CrossChainReputation contract...");
|
||||
const CrossChainReputation = await ethers.getContractFactory("CrossChainReputation");
|
||||
const crossChainReputation = await CrossChainReputation.deploy();
|
||||
await crossChainReputation.deployed();
|
||||
|
||||
deployedContracts.contracts.CrossChainReputation = {
|
||||
address: crossChainReputation.address,
|
||||
deploymentHash: crossChainReputation.deployTransaction.hash,
|
||||
gasUsed: (await crossChainReputation.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ CrossChainReputation: ${crossChainReputation.address}`);
|
||||
|
||||
// Deploy AgentCommunication contract
|
||||
console.log("📦 Deploying AgentCommunication contract...");
|
||||
const AgentCommunication = await ethers.getContractFactory("AgentCommunication");
|
||||
const agentCommunication = await AgentCommunication.deploy(crossChainReputation.address);
|
||||
await agentCommunication.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentCommunication = {
|
||||
address: agentCommunication.address,
|
||||
deploymentHash: agentCommunication.deployTransaction.hash,
|
||||
gasUsed: (await agentCommunication.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentCommunication: ${agentCommunication.address}`);
|
||||
|
||||
// Deploy AgentCollaboration contract
|
||||
console.log("📦 Deploying AgentCollaboration contract...");
|
||||
const AgentCollaboration = await ethers.getContractFactory("AgentCollaboration");
|
||||
const agentCollaboration = await AgentCollaboration.deploy(
|
||||
aitbcTokenAddress,
|
||||
crossChainReputation.address,
|
||||
agentCommunication.address
|
||||
);
|
||||
await agentCollaboration.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentCollaboration = {
|
||||
address: agentCollaboration.address,
|
||||
deploymentHash: agentCollaboration.deployTransaction.hash,
|
||||
gasUsed: (await agentCollaboration.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentCollaboration: ${agentCollaboration.address}`);
|
||||
|
||||
// Deploy AgentLearning contract
|
||||
console.log("📦 Deploying AgentLearning contract...");
|
||||
const AgentLearning = await ethers.getContractFactory("AgentLearning");
|
||||
const agentLearning = await AgentLearning.deploy(
|
||||
crossChainReputation.address,
|
||||
agentCollaboration.address
|
||||
);
|
||||
await agentLearning.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentLearning = {
|
||||
address: agentLearning.address,
|
||||
deploymentHash: agentLearning.deployTransaction.hash,
|
||||
gasUsed: (await agentLearning.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentLearning: ${agentLearning.address}`);
|
||||
|
||||
// Deploy AgentMarketplaceV2 contract
|
||||
console.log("📦 Deploying AgentMarketplaceV2 contract...");
|
||||
const AgentMarketplaceV2 = await ethers.getContractFactory("AgentMarketplaceV2");
|
||||
const agentMarketplaceV2 = await AgentMarketplaceV2.deploy(
|
||||
aitbcTokenAddress,
|
||||
paymentProcessorAddress,
|
||||
crossChainReputation.address,
|
||||
agentCommunication.address,
|
||||
agentCollaboration.address,
|
||||
agentLearning.address
|
||||
);
|
||||
await agentMarketplaceV2.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentMarketplaceV2 = {
|
||||
address: agentMarketplaceV2.address,
|
||||
deploymentHash: agentMarketplaceV2.deployTransaction.hash,
|
||||
gasUsed: (await agentMarketplaceV2.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentMarketplaceV2: ${agentMarketplaceV2.address}`);
|
||||
|
||||
// Deploy ReputationNFT contract
|
||||
console.log("📦 Deploying ReputationNFT contract...");
|
||||
const ReputationNFT = await ethers.getContractFactory("ReputationNFT");
|
||||
const reputationNFT = await ReputationNFT.deploy(
|
||||
"AITBC Reputation NFT",
|
||||
"AITBC-RNFT",
|
||||
crossChainReputation.address
|
||||
);
|
||||
await reputationNFT.deployed();
|
||||
|
||||
deployedContracts.contracts.ReputationNFT = {
|
||||
address: reputationNFT.address,
|
||||
deploymentHash: reputationNFT.deployTransaction.hash,
|
||||
gasUsed: (await reputationNFT.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ ReputationNFT: ${reputationNFT.address}`);
|
||||
|
||||
// Initialize contracts
|
||||
console.log("🔧 Initializing contracts...");
|
||||
|
||||
// Initialize CrossChainReputation
|
||||
await crossChainReputation.updateGlobalSettings(
|
||||
1000, // baseReputationScore
|
||||
100, // successBonus
|
||||
50, // failurePenalty
|
||||
ethers.utils.parseEther("100"), // minStakeAmount
|
||||
10000, // maxDelegationRatio (100%)
|
||||
3600 // syncCooldown (1 hour)
|
||||
);
|
||||
console.log("✅ CrossChainReputation initialized");
|
||||
|
||||
// Initialize AgentCommunication
|
||||
await agentCommunication.updateGlobalSettings(
|
||||
1000, // minReputationScore
|
||||
ethers.utils.parseEther("0.001"), // baseMessagePrice
|
||||
100000, // maxMessageSize (100KB)
|
||||
86400, // messageTimeout (24 hours)
|
||||
2592000 // channelTimeout (30 days)
|
||||
);
|
||||
console.log("✅ AgentCommunication initialized");
|
||||
|
||||
// Authorize deployer as agent
|
||||
await crossChainReputation.initializeReputation(deployer.address, 1000);
|
||||
await agentCommunication.authorizeAgent(deployer.address);
|
||||
await agentCollaboration.authorizeAgent(deployer.address);
|
||||
await agentLearning.authorizeAgent(deployer.address);
|
||||
console.log("✅ Deployer authorized as agent");
|
||||
|
||||
// Add supported chains to CrossChainReputation
|
||||
await crossChainReputation.addSupportedChain(1, crossChainReputation.address); // Ethereum
|
||||
await crossChainReputation.addSupportedChain(137, crossChainReputation.address); // Polygon
|
||||
await crossChainReputation.addSupportedChain(42161, crossChainReputation.address); // Arbitrum
|
||||
await crossChainReputation.addSupportedChain(10, crossChainReputation.address); // Optimism
|
||||
console.log("✅ Supported chains added to CrossChainReputation");
|
||||
|
||||
// Save deployment information
|
||||
const deploymentFile = `deployed-contracts-${hre.network.name}.json`;
|
||||
|
||||
// Load existing contracts if file exists
|
||||
let existingContracts = {};
|
||||
if (fs.existsSync(deploymentFile)) {
|
||||
existingContracts = JSON.parse(fs.readFileSync(deploymentFile, 'utf8'));
|
||||
}
|
||||
|
||||
// Merge with existing contracts
|
||||
const allContracts = {
|
||||
...existingContracts,
|
||||
...deployedContracts
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", deploymentFile),
|
||||
JSON.stringify(allContracts, null, 2)
|
||||
);
|
||||
|
||||
// Generate environment variables for frontend
|
||||
const envVars = `
|
||||
# AITBC Advanced Agent Features - ${hre.network.name.toUpperCase()}
|
||||
# Generated on ${new Date().toISOString()}
|
||||
|
||||
# Advanced Contract Addresses
|
||||
VITE_CROSS_CHAIN_REPUTATION_ADDRESS=${crossChainReputation.address}
|
||||
VITE_AGENT_COMMUNICATION_ADDRESS=${agentCommunication.address}
|
||||
VITE_AGENT_COLLABORATION_ADDRESS=${agentCollaboration.address}
|
||||
VITE_AGENT_LEARNING_ADDRESS=${agentLearning.address}
|
||||
VITE_AGENT_MARKETPLACE_V2_ADDRESS=${agentMarketplaceV2.address}
|
||||
VITE_REPUTATION_NFT_ADDRESS=${reputationNFT.address}
|
||||
|
||||
# Network Configuration
|
||||
VITE_NETWORK_NAME=${hre.network.name}
|
||||
VITE_CHAIN_ID=${hre.network.config.chainId || 1}
|
||||
VITE_RPC_URL=${hre.network.config.url || 'http://localhost:8545'}
|
||||
|
||||
# Advanced Features Configuration
|
||||
VITE_MIN_REPUTATION_SCORE=1000
|
||||
VITE_BASE_MESSAGE_PRICE=0.001
|
||||
VITE_MAX_MESSAGE_SIZE=100000
|
||||
VITE_MESSAGE_TIMEOUT=86400
|
||||
VITE_CHANNEL_TIMEOUT=2592000
|
||||
VITE_MAX_MODEL_SIZE=104857600
|
||||
VITE_MAX_TRAINING_TIME=3600
|
||||
VITE_DEFAULT_LEARNING_RATE=0.001
|
||||
VITE_CONVERGENCE_THRESHOLD=0.001
|
||||
VITE_SYNC_COOLDOWN=3600
|
||||
VITE_MIN_STAKE_AMOUNT=100000000000000000000
|
||||
VITE_MAX_DELEGATION_RATIO=1.0
|
||||
`;
|
||||
|
||||
const envFile = path.join(__dirname, "..", "..", "apps", "marketplace-web", ".env.advanced-features");
|
||||
fs.writeFileSync(envFile, envVars);
|
||||
|
||||
console.log("");
|
||||
console.log("🎉 ADVANCED CONTRACTS DEPLOYMENT COMPLETED");
|
||||
console.log("=====================================");
|
||||
console.log(`Total gas used: ${calculateTotalGas(deployedContracts)}`);
|
||||
console.log(`Deployment file: ${deploymentFile}`);
|
||||
console.log(`Environment file: ${envFile}`);
|
||||
console.log("");
|
||||
console.log("📋 Contract Addresses:");
|
||||
console.log(` CrossChainReputation: ${crossChainReputation.address}`);
|
||||
console.log(` AgentCommunication: ${agentCommunication.address}`);
|
||||
console.log(` AgentCollaboration: ${agentCollaboration.address}`);
|
||||
console.log(` AgentLearning: ${agentLearning.address}`);
|
||||
console.log(` AgentMarketplaceV2: ${agentMarketplaceV2.address}`);
|
||||
console.log(` ReputationNFT: ${reputationNFT.address}`);
|
||||
console.log("");
|
||||
console.log("🔧 Next Steps:");
|
||||
console.log(" 1. Verify contracts on Etherscan (if on testnet/mainnet)");
|
||||
console.log(" 2. Initialize cross-chain reputation for agents");
|
||||
console.log(" 3. Set up agent communication channels");
|
||||
console.log(" 4. Configure advanced learning models");
|
||||
console.log(" 5. Test agent collaboration protocols");
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Deployment failed:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateTotalGas(deployedContracts) {
|
||||
let totalGas = 0;
|
||||
for (const contract of Object.values(deployedContracts.contracts)) {
|
||||
if (contract.gasUsed) {
|
||||
totalGas += parseInt(contract.gasUsed);
|
||||
}
|
||||
}
|
||||
return totalGas.toLocaleString();
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
258
contracts/scripts/deploy-agent-contracts.js
Normal file
258
contracts/scripts/deploy-agent-contracts.js
Normal file
@@ -0,0 +1,258 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🚀 Deploying OpenClaw Autonomous Economics Contracts");
|
||||
console.log("==============================================");
|
||||
|
||||
const [deployer] = await ethers.getSigners();
|
||||
const balance = await deployer.getBalance();
|
||||
|
||||
console.log(`Deployer: ${deployer.address}`);
|
||||
console.log(`Balance: ${ethers.utils.formatEther(balance)} ETH`);
|
||||
|
||||
if (balance.lt(ethers.utils.parseEther("1"))) {
|
||||
throw new Error("Insufficient ETH balance. Minimum 1 ETH recommended for deployment.");
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("Proceeding with contract deployment...");
|
||||
|
||||
// Deployment configuration
|
||||
const deployedContracts = {
|
||||
network: hre.network.name,
|
||||
deployer: deployer.address,
|
||||
timestamp: new Date().toISOString(),
|
||||
contracts: {}
|
||||
};
|
||||
|
||||
try {
|
||||
// Get existing contracts
|
||||
let aitbcTokenAddress, paymentProcessorAddress, aiPowerRentalAddress;
|
||||
|
||||
try {
|
||||
const existingContractsFile = `deployed-contracts-${hre.network.name}.json`;
|
||||
if (fs.existsSync(existingContractsFile)) {
|
||||
const existingContracts = JSON.parse(fs.readFileSync(existingContractsFile, 'utf8'));
|
||||
aitbcTokenAddress = existingContracts.contracts.AITBCToken?.address;
|
||||
paymentProcessorAddress = existingContracts.contracts.AITBCPaymentProcessor?.address;
|
||||
aiPowerRentalAddress = existingContracts.contracts.AIPowerRental?.address;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not load existing contracts, deploying mock ones...");
|
||||
}
|
||||
|
||||
// Deploy Mock ERC20 if needed
|
||||
if (!aitbcTokenAddress) {
|
||||
console.log("📦 Deploying mock AITBC token...");
|
||||
const MockERC20 = await ethers.getContractFactory("MockERC20");
|
||||
const aitbcToken = await MockERC20.deploy(
|
||||
"AITBC Token",
|
||||
"AITBC",
|
||||
ethers.utils.parseEther("1000000")
|
||||
);
|
||||
await aitbcToken.deployed();
|
||||
aitbcTokenAddress = aitbcToken.address;
|
||||
|
||||
deployedContracts.contracts.AITBCToken = {
|
||||
address: aitbcTokenAddress,
|
||||
deploymentHash: aitbcToken.deployTransaction.hash,
|
||||
gasUsed: (await aitbcToken.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AITBC Token: ${aitbcTokenAddress}`);
|
||||
}
|
||||
|
||||
// Deploy Mock Payment Processor if needed
|
||||
if (!paymentProcessorAddress) {
|
||||
console.log("📦 Deploying mock AITBC Payment Processor...");
|
||||
const MockPaymentProcessor = await ethers.getContractFactory("AITBCPaymentProcessor");
|
||||
const paymentProcessor = await MockPaymentProcessor.deploy(aitbcTokenAddress);
|
||||
await paymentProcessor.deployed();
|
||||
paymentProcessorAddress = paymentProcessor.address;
|
||||
|
||||
deployedContracts.contracts.AITBCPaymentProcessor = {
|
||||
address: paymentProcessorAddress,
|
||||
deploymentHash: paymentProcessor.deployTransaction.hash,
|
||||
gasUsed: (await paymentProcessor.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ Payment Processor: ${paymentProcessorAddress}`);
|
||||
}
|
||||
|
||||
// Deploy AgentWallet contract
|
||||
console.log("📦 Deploying AgentWallet contract...");
|
||||
const AgentWallet = await ethers.getContractFactory("AgentWallet");
|
||||
const agentWallet = await AgentWallet.deploy(
|
||||
aitbcTokenAddress,
|
||||
paymentProcessorAddress
|
||||
);
|
||||
await agentWallet.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentWallet = {
|
||||
address: agentWallet.address,
|
||||
deploymentHash: agentWallet.deployTransaction.hash,
|
||||
gasUsed: (await agentWallet.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentWallet: ${agentWallet.address}`);
|
||||
|
||||
// Deploy AgentOrchestration contract
|
||||
console.log("📦 Deploying AgentOrchestration contract...");
|
||||
const AgentOrchestration = await ethers.getContractFactory("AgentOrchestration");
|
||||
const agentOrchestration = await AgentOrchestration.deploy();
|
||||
await agentOrchestration.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentOrchestration = {
|
||||
address: agentOrchestration.address,
|
||||
deploymentHash: agentOrchestration.deployTransaction.hash,
|
||||
gasUsed: (await agentOrchestration.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentOrchestration: ${agentOrchestration.address}`);
|
||||
|
||||
// Deploy or extend AIPowerRental contract
|
||||
if (!aiPowerRentalAddress) {
|
||||
console.log("📦 Deploying AIPowerRental contract...");
|
||||
const AIPowerRental = await ethers.getContractFactory("AIPowerRental");
|
||||
const aiPowerRental = await AIPowerRental.deploy(
|
||||
aitbcTokenAddress
|
||||
);
|
||||
await aiPowerRental.deployed();
|
||||
aiPowerRentalAddress = aiPowerRental.address;
|
||||
|
||||
deployedContracts.contracts.AIPowerRental = {
|
||||
address: aiPowerRentalAddress,
|
||||
deploymentHash: aiPowerRental.deployTransaction.hash,
|
||||
gasUsed: (await aiPowerRental.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AIPowerRental: ${aiPowerRentalAddress}`);
|
||||
} else {
|
||||
console.log(`📦 Using existing AIPowerRental: ${aiPowerRentalAddress}`);
|
||||
deployedContracts.contracts.AIPowerRental = {
|
||||
address: aiPowerRentalAddress,
|
||||
note: "Existing contract - agent features added"
|
||||
};
|
||||
}
|
||||
|
||||
// Initialize contracts
|
||||
console.log("🔧 Initializing contracts...");
|
||||
|
||||
// Authorize deployer as agent
|
||||
await agentWallet.authorizeAgent(deployer.address, deployer.address);
|
||||
console.log("✅ Authorized deployer as agent");
|
||||
|
||||
// Authorize deployer as provider
|
||||
await agentWallet.authorizeProvider(deployer.address);
|
||||
console.log("✅ Authorized deployer as provider");
|
||||
|
||||
// Authorize agent for AIPowerRental
|
||||
const aiPowerRentalContract = await ethers.getContractAt("AIPowerRental", aiPowerRentalAddress);
|
||||
await aiPowerRentalContract.authorizeAgent(deployer.address, deployer.address);
|
||||
console.log("✅ Authorized agent for AIPowerRental");
|
||||
|
||||
// Authorize provider for AIPowerRental
|
||||
await aiPowerRentalContract.authorizeProvider(deployer.address);
|
||||
console.log("✅ Authorized provider for AIPowerRental");
|
||||
|
||||
// Save deployment information
|
||||
const deploymentFile = `deployed-contracts-${hre.network.name}.json`;
|
||||
|
||||
// Load existing contracts if file exists
|
||||
let existingContracts = {};
|
||||
if (fs.existsSync(deploymentFile)) {
|
||||
existingContracts = JSON.parse(fs.readFileSync(deploymentFile, 'utf8'));
|
||||
}
|
||||
|
||||
// Merge with existing contracts
|
||||
const allContracts = {
|
||||
...existingContracts,
|
||||
...deployedContracts
|
||||
};
|
||||
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", deploymentFile),
|
||||
JSON.stringify(allContracts, null, 2)
|
||||
);
|
||||
|
||||
// Generate environment variables for frontend
|
||||
const envVars = `
|
||||
# AITBC OpenClaw Autonomous Economics - ${hre.network.name.toUpperCase()}
|
||||
# Generated on ${new Date().toISOString()}
|
||||
|
||||
# Contract Addresses
|
||||
VITE_AGENT_WALLET_ADDRESS=${agentWallet.address}
|
||||
VITE_AGENT_ORCHESTRATION_ADDRESS=${agentOrchestration.address}
|
||||
VITE_AI_POWER_RENTAL_ADDRESS=${aiPowerRentalAddress}
|
||||
VITE_AITBC_TOKEN_ADDRESS=${aitbcTokenAddress}
|
||||
VITE_PAYMENT_PROCESSOR_ADDRESS=${paymentProcessorAddress}
|
||||
|
||||
# Network Configuration
|
||||
VITE_NETWORK_NAME=${hre.network.name}
|
||||
VITE_CHAIN_ID=${hre.network.config.chainId || 1}
|
||||
VITE_RPC_URL=${hre.network.config.url || 'http://localhost:8545'}
|
||||
|
||||
# Agent Configuration
|
||||
VITE_DEFAULT_SPENDING_LIMIT=1000
|
||||
VITE_MICRO_TRANSACTION_THRESHOLD=0.001
|
||||
VITE_MIN_ALLOWANCE=10
|
||||
VITE_MAX_ALLOWANCE=100000
|
||||
|
||||
# Bid Strategy Configuration
|
||||
VITE_MARKET_WINDOW=24
|
||||
VITE_PRICE_HISTORY_DAYS=30
|
||||
VITE_VOLATILITY_THRESHOLD=0.15
|
||||
VITE_MAX_CONCURRENT_PLANS=10
|
||||
VITE_ASSIGNMENT_TIMEOUT=300
|
||||
VITE_MONITORING_INTERVAL=30
|
||||
VITE_RETRY_LIMIT=3
|
||||
`;
|
||||
|
||||
const envFile = path.join(__dirname, "..", "..", "apps", "marketplace-web", ".env.agent-economics");
|
||||
fs.writeFileSync(envFile, envVars);
|
||||
|
||||
console.log("");
|
||||
console.log("🎉 CONTRACT DEPLOYMENT COMPLETED");
|
||||
console.log("===============================");
|
||||
console.log(`Total gas used: ${calculateTotalGas(deployedContracts)}`);
|
||||
console.log(`Deployment file: ${deploymentFile}`);
|
||||
console.log(`Environment file: ${envFile}`);
|
||||
console.log("");
|
||||
console.log("📋 Contract Addresses:");
|
||||
console.log(` AgentWallet: ${agentWallet.address}`);
|
||||
console.log(` AgentOrchestration: ${agentOrchestration.address}`);
|
||||
console.log(` AIPowerRental: ${aiPowerRentalAddress}`);
|
||||
console.log(` AITBC Token: ${aitbcTokenAddress}`);
|
||||
console.log(` Payment Processor: ${paymentProcessorAddress}`);
|
||||
console.log("");
|
||||
console.log("🔧 Next Steps:");
|
||||
console.log(" 1. Verify contracts on Etherscan (if on testnet/mainnet)");
|
||||
console.log(" 2. Update frontend with new contract addresses");
|
||||
console.log(" 3. Test agent wallet functionality");
|
||||
console.log(" 4. Initialize bid strategy engine");
|
||||
console.log(" 5. Set up agent orchestrator");
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Deployment failed:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateTotalGas(deployedContracts) {
|
||||
let totalGas = 0;
|
||||
for (const contract of Object.values(deployedContracts.contracts)) {
|
||||
if (contract.gasUsed) {
|
||||
totalGas += parseInt(contract.gasUsed);
|
||||
}
|
||||
}
|
||||
return totalGas.toLocaleString();
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
276
contracts/scripts/deploy-developer-ecosystem.js
Normal file
276
contracts/scripts/deploy-developer-ecosystem.js
Normal file
@@ -0,0 +1,276 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🚀 Deploying AITBC Developer Ecosystem Contracts");
|
||||
console.log("==============================================");
|
||||
|
||||
const network = network.name;
|
||||
const [deployer] = await ethers.getSigners();
|
||||
|
||||
console.log(`Deploying contracts to ${network} with account: ${deployer.address}`);
|
||||
console.log(`Account balance: ${ethers.utils.formatEther(await deployer.getBalance())} ETH`);
|
||||
console.log("");
|
||||
|
||||
// Deployed contracts storage
|
||||
const deployedContracts = {
|
||||
network: network,
|
||||
deployer: deployer.address,
|
||||
timestamp: new Date().toISOString(),
|
||||
contracts: {}
|
||||
};
|
||||
|
||||
try {
|
||||
// Step 1: Deploy Mock AITBC Token (if not already deployed)
|
||||
console.log("📦 Step 1: Deploying AITBC Token...");
|
||||
const AITBCToken = await ethers.getContractFactory("MockERC20");
|
||||
const aitbcToken = await AITBCToken.deploy("AITBC Token", "AITBC", ethers.utils.parseEther("1000000"));
|
||||
await aitbcToken.deployed();
|
||||
|
||||
deployedContracts.contracts.AITBCToken = {
|
||||
address: aitbcToken.address,
|
||||
deploymentHash: aitbcToken.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ AITBC Token deployed to: ${aitbcToken.address}`);
|
||||
console.log("");
|
||||
|
||||
// Step 2: Deploy Mock Verifiers
|
||||
console.log("🔍 Step 2: Deploying Mock Verifiers...");
|
||||
|
||||
// Deploy Mock ZK Verifier
|
||||
const MockZKVerifier = await ethers.getContractFactory("MockZKVerifier");
|
||||
const zkVerifier = await MockZKVerifier.deploy();
|
||||
await zkVerifier.deployed();
|
||||
|
||||
deployedContracts.contracts.ZKVerifier = {
|
||||
address: zkVerifier.address,
|
||||
deploymentHash: zkVerifier.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ ZK Verifier deployed to: ${zkVerifier.address}`);
|
||||
|
||||
// Deploy Mock Groth16 Verifier
|
||||
const MockGroth16Verifier = await ethers.getContractFactory("MockGroth16Verifier");
|
||||
const groth16Verifier = await MockGroth16Verifier.deploy();
|
||||
await groth16Verifier.deployed();
|
||||
|
||||
deployedContracts.contracts.Groth16Verifier = {
|
||||
address: groth16Verifier.address,
|
||||
deploymentHash: groth16Verifier.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ Groth16 Verifier deployed to: ${groth16Verifier.address}`);
|
||||
console.log("");
|
||||
|
||||
// Step 3: Deploy Core Developer Ecosystem Contracts
|
||||
console.log("🎯 Step 3: Deploying Core Developer Ecosystem Contracts...");
|
||||
|
||||
// Deploy AgentBounty
|
||||
const AgentBounty = await ethers.getContractFactory("AgentBounty");
|
||||
const agentBounty = await AgentBounty.deploy(
|
||||
aitbcToken.address,
|
||||
zkVerifier.address,
|
||||
groth16Verifier.address
|
||||
);
|
||||
await agentBounty.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentBounty = {
|
||||
address: agentBounty.address,
|
||||
deploymentHash: agentBounty.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ AgentBounty deployed to: ${agentBounty.address}`);
|
||||
|
||||
// Deploy AgentStaking
|
||||
const AgentStaking = await ethers.getContractFactory("AgentStaking");
|
||||
const agentStaking = await AgentStaking.deploy(aitbcToken.address);
|
||||
await agentStaking.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentStaking = {
|
||||
address: agentStaking.address,
|
||||
deploymentHash: agentStaking.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ AgentStaking deployed to: ${agentStaking.address}`);
|
||||
console.log("");
|
||||
|
||||
// Step 4: Deploy Supporting Contracts
|
||||
console.log("🔧 Step 4: Deploying Supporting Contracts...");
|
||||
|
||||
// Deploy PerformanceVerifier
|
||||
const PerformanceVerifier = await ethers.getContractFactory("PerformanceVerifier");
|
||||
const performanceVerifier = await PerformanceVerifier.deploy(
|
||||
zkVerifier.address,
|
||||
groth16Verifier.address,
|
||||
agentBounty.address
|
||||
);
|
||||
await performanceVerifier.deployed();
|
||||
|
||||
deployedContracts.contracts.PerformanceVerifier = {
|
||||
address: performanceVerifier.address,
|
||||
deploymentHash: performanceVerifier.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ PerformanceVerifier deployed to: ${performanceVerifier.address}`);
|
||||
|
||||
// Deploy DisputeResolution
|
||||
const DisputeResolution = await ethers.getContractFactory("DisputeResolution");
|
||||
const disputeResolution = await DisputeResolution.deploy(
|
||||
agentBounty.address,
|
||||
aitbcToken.address,
|
||||
performanceVerifier.address
|
||||
);
|
||||
await disputeResolution.deployed();
|
||||
|
||||
deployedContracts.contracts.DisputeResolution = {
|
||||
address: disputeResolution.address,
|
||||
deploymentHash: disputeResolution.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ DisputeResolution deployed to: ${disputeResolution.address}`);
|
||||
|
||||
// Deploy EscrowService
|
||||
const EscrowService = await ethers.getContractFactory("EscrowService");
|
||||
const escrowService = await EscrowService.deploy(
|
||||
aitbcToken.address,
|
||||
agentBounty.address,
|
||||
agentStaking.address
|
||||
);
|
||||
await escrowService.deployed();
|
||||
|
||||
deployedContracts.contracts.EscrowService = {
|
||||
address: escrowService.address,
|
||||
deploymentHash: escrowService.deployTransaction.hash
|
||||
};
|
||||
|
||||
console.log(`✅ EscrowService deployed to: ${escrowService.address}`);
|
||||
console.log("");
|
||||
|
||||
// Step 5: Initialize Contracts
|
||||
console.log("⚙️ Step 5: Initializing Contracts...");
|
||||
|
||||
// Initialize AgentBounty with owner settings
|
||||
await agentBounty.updateCreationFee(50); // 0.5%
|
||||
await agentBounty.updateSuccessFee(200); // 2%
|
||||
await agentBounty.updateDisputeFee(10); // 0.1%
|
||||
await agentBounty.updatePlatformFee(100); // 1%
|
||||
|
||||
console.log("✅ AgentBounty initialized with fee settings");
|
||||
|
||||
// Initialize AgentStaking with performance recorder
|
||||
await agentStaking.setPerformanceRecorder(deployer.address);
|
||||
|
||||
console.log("✅ AgentStaking initialized with performance recorder");
|
||||
|
||||
// Initialize PerformanceVerifier with settings
|
||||
await performanceVerifier.setMinimumAccuracy(80); // 80% minimum accuracy
|
||||
await performanceVerifier.setMaximumResponseTime(3600); // 1 hour max response time
|
||||
|
||||
console.log("✅ PerformanceVerifier initialized with performance thresholds");
|
||||
console.log("");
|
||||
|
||||
// Step 6: Setup Contract Interactions
|
||||
console.log("🔗 Step 6: Setting up Contract Interactions...");
|
||||
|
||||
// Transfer some tokens to the contracts for testing
|
||||
const initialTokenAmount = ethers.utils.parseEther("10000");
|
||||
await aitbcToken.transfer(agentBounty.address, initialTokenAmount);
|
||||
await aitbcToken.transfer(escrowService.address, initialTokenAmount);
|
||||
|
||||
console.log("✅ Initial tokens transferred to contracts");
|
||||
console.log("");
|
||||
|
||||
// Step 7: Save Deployment Information
|
||||
console.log("💾 Step 7: Saving Deployment Information...");
|
||||
|
||||
const deploymentFile = `deployed-contracts-${network}.json`;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", deploymentFile),
|
||||
JSON.stringify(deployedContracts, null, 2)
|
||||
);
|
||||
|
||||
console.log(`✅ Deployment information saved to ${deploymentFile}`);
|
||||
console.log("");
|
||||
|
||||
// Step 8: Generate Environment Variables
|
||||
console.log("📝 Step 8: Generating Environment Variables...");
|
||||
|
||||
const envVars = `
|
||||
# AITBC Developer Ecosystem - ${network.toUpperCase()} Deployment
|
||||
# Generated on ${new Date().toISOString()}
|
||||
|
||||
# Contract Addresses
|
||||
NEXT_PUBLIC_AITBC_TOKEN_ADDRESS=${aitbcToken.address}
|
||||
NEXT_PUBLIC_AGENT_BOUNTY_ADDRESS=${agentBounty.address}
|
||||
NEXT_PUBLIC_AGENT_STAKING_ADDRESS=${agentStaking.address}
|
||||
NEXT_PUBLIC_PERFORMANCE_VERIFIER_ADDRESS=${performanceVerifier.address}
|
||||
NEXT_PUBLIC_DISPUTE_RESOLUTION_ADDRESS=${disputeResolution.address}
|
||||
NEXT_PUBLIC_ESCROW_SERVICE_ADDRESS=${escrowService.address}
|
||||
NEXT_PUBLIC_ZK_VERIFIER_ADDRESS=${zkVerifier.address}
|
||||
NEXT_PUBLIC_GROTH16_VERIFIER_ADDRESS=${groth16Verifier.address}
|
||||
|
||||
# Network Configuration
|
||||
NEXT_PUBLIC_NETWORK_NAME=${network}
|
||||
NEXT_PUBLIC_CHAIN_ID=${network.config.chainId}
|
||||
NEXT_PUBLIC_RPC_URL=${network.config.url}
|
||||
|
||||
# Deployment Info
|
||||
NEXT_PUBLIC_DEPLOYER_ADDRESS=${deployer.address}
|
||||
NEXT_PUBLIC_DEPLOYMENT_TIMESTAMP=${new Date().toISOString()}
|
||||
`;
|
||||
|
||||
const envFile = `.env.${network}`;
|
||||
fs.writeFileSync(path.join(__dirname, "..", envFile), envVars);
|
||||
|
||||
console.log(`✅ Environment variables saved to ${envFile}`);
|
||||
console.log("");
|
||||
|
||||
// Step 9: Display Deployment Summary
|
||||
console.log("🎉 Deployment Summary");
|
||||
console.log("===================");
|
||||
console.log(`Network: ${network}`);
|
||||
console.log(`Deployer: ${deployer.address}`);
|
||||
console.log(`Total Contracts: ${Object.keys(deployedContracts.contracts).length}`);
|
||||
console.log("");
|
||||
console.log("Deployed Contracts:");
|
||||
|
||||
for (const [name, contract] of Object.entries(deployedContracts.contracts)) {
|
||||
console.log(` ${name}: ${contract.address}`);
|
||||
}
|
||||
console.log("");
|
||||
|
||||
// Step 10: Verification Instructions
|
||||
if (network !== "localhost" && network !== "hardhat") {
|
||||
console.log("🔍 Contract Verification");
|
||||
console.log("=======================");
|
||||
console.log("To verify contracts on Etherscan, run:");
|
||||
console.log(`npx hardhat run scripts/verify-contracts.js --network ${network}`);
|
||||
console.log("");
|
||||
}
|
||||
|
||||
// Step 11: Next Steps
|
||||
console.log("📋 Next Steps");
|
||||
console.log("=============");
|
||||
console.log("1. Copy environment variables to frontend application");
|
||||
console.log("2. Update API configuration with contract addresses");
|
||||
console.log("3. Deploy frontend application");
|
||||
console.log("4. Run integration tests");
|
||||
console.log("5. Monitor contract operations");
|
||||
console.log("");
|
||||
|
||||
print_success("🎉 Developer Ecosystem deployment completed successfully!");
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Deployment failed:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
207
contracts/scripts/deploy-developer-ecosystem.sh
Executable file
207
contracts/scripts/deploy-developer-ecosystem.sh
Executable file
@@ -0,0 +1,207 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# AITBC Developer Ecosystem Deployment Script
|
||||
# Deploys all smart contracts for the Developer Ecosystem & DAO Grants system
|
||||
#
|
||||
# Usage: ./deploy-developer-ecosystem.sh [network] [verify]
|
||||
# Networks: localhost, sepolia, goerli, mainnet
|
||||
# Verify: true/false - whether to verify contracts on Etherscan
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Colors for output
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m' # No Color
|
||||
|
||||
print_status() {
|
||||
echo -e "${BLUE}[INFO]${NC} $1"
|
||||
}
|
||||
|
||||
print_success() {
|
||||
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||
}
|
||||
|
||||
print_warning() {
|
||||
echo -e "${YELLOW}[WARNING]${NC} $1"
|
||||
}
|
||||
|
||||
print_error() {
|
||||
echo -e "${RED}[ERROR]${NC} $1"
|
||||
}
|
||||
|
||||
# Parse arguments
|
||||
NETWORK="${1:-localhost}"
|
||||
VERIFY_CONTRACTS="${2:-false}"
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
CONTRACTS_DIR="$(dirname "$SCRIPT_DIR")"
|
||||
ROOT_DIR="$(dirname "$CONTRACTS_DIR")"
|
||||
|
||||
echo "🚀 AITBC Developer Ecosystem Deployment"
|
||||
echo "=========================================="
|
||||
echo "Network: $NETWORK"
|
||||
echo "Verify Contracts: $VERIFY_CONTRACTS"
|
||||
echo "Contracts Directory: $CONTRACTS_DIR"
|
||||
echo ""
|
||||
|
||||
# Check prerequisites
|
||||
check_prerequisites() {
|
||||
print_status "Checking prerequisites..."
|
||||
|
||||
# Check if hardhat is available
|
||||
if ! command -v npx &>/dev/null; then
|
||||
print_error "npx not found. Please install Node.js and npm."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if we're in the contracts directory
|
||||
if [[ ! -f "$CONTRACTS_DIR/hardhat.config.js" ]]; then
|
||||
print_error "hardhat.config.js not found in $CONTRACTS_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if .env file exists for network configuration
|
||||
if [[ ! -f "$CONTRACTS_DIR/.env" ]]; then
|
||||
print_warning ".env file not found. Creating template..."
|
||||
cat > "$CONTRACTS_DIR/.env" << EOF
|
||||
# Network Configuration
|
||||
PRIVATE_KEY=your_private_key_here
|
||||
INFURA_PROJECT_ID=your_infura_project_id
|
||||
ETHERSCAN_API_KEY=your_etherscan_api_key
|
||||
|
||||
# Network URLs
|
||||
SEPOLIA_URL=https://sepolia.infura.io/v3/\${INFURA_PROJECT_ID}
|
||||
GOERLI_URL=https://goerli.infura.io/v3/\${INFURA_PROJECT_ID}
|
||||
MAINNET_URL=https://mainnet.infura.io/v3/\${INFURA_PROJECT_ID}
|
||||
EOF
|
||||
print_warning "Please update .env file with your credentials"
|
||||
fi
|
||||
|
||||
print_success "Prerequisites check completed"
|
||||
}
|
||||
|
||||
# Compile contracts
|
||||
compile_contracts() {
|
||||
print_status "Compiling contracts..."
|
||||
|
||||
cd "$CONTRACTS_DIR"
|
||||
|
||||
if npx hardhat compile; then
|
||||
print_success "Contracts compiled successfully"
|
||||
else
|
||||
print_error "Contract compilation failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Deploy contracts
|
||||
deploy_contracts() {
|
||||
print_status "Deploying contracts to $NETWORK..."
|
||||
|
||||
cd "$CONTRACTS_DIR"
|
||||
|
||||
# Run deployment script
|
||||
if npx hardhat run scripts/deploy-developer-ecosystem.js --network "$NETWORK"; then
|
||||
print_success "Contracts deployed successfully"
|
||||
else
|
||||
print_error "Contract deployment failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Verify contracts on Etherscan
|
||||
verify_contracts() {
|
||||
if [[ "$VERIFY_CONTRACTS" != "true" ]]; then
|
||||
print_status "Contract verification skipped"
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ "$NETWORK" == "localhost" || "$NETWORK" == "hardhat" ]]; then
|
||||
print_status "Skipping verification for local network"
|
||||
return
|
||||
fi
|
||||
|
||||
print_status "Verifying contracts on Etherscan..."
|
||||
|
||||
cd "$CONTRACTS_DIR"
|
||||
|
||||
# Read deployed addresses from deployment output
|
||||
if [[ -f "deployed-contracts-$NETWORK.json" ]]; then
|
||||
# Verify each contract
|
||||
npx hardhat run scripts/verify-contracts.js --network "$NETWORK"
|
||||
print_success "Contract verification completed"
|
||||
else
|
||||
print_warning "No deployed contracts file found. Skipping verification."
|
||||
fi
|
||||
}
|
||||
|
||||
# Run post-deployment tests
|
||||
run_post_deployment_tests() {
|
||||
print_status "Running post-deployment tests..."
|
||||
|
||||
cd "$ROOT_DIR"
|
||||
|
||||
# Run contract tests
|
||||
if npx hardhat test tests/contracts/ --network "$NETWORK"; then
|
||||
print_success "Post-deployment tests passed"
|
||||
else
|
||||
print_error "Post-deployment tests failed"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Generate deployment report
|
||||
generate_deployment_report() {
|
||||
print_status "Generating deployment report..."
|
||||
|
||||
local report_file="$ROOT_DIR/deployment-report-$NETWORK-$(date +%Y%m%d-%H%M%S).json"
|
||||
|
||||
cd "$CONTRACTS_DIR"
|
||||
|
||||
if [[ -f "deployed-contracts-$NETWORK.json" ]]; then
|
||||
cp "deployed-contracts-$NETWORK.json" "$report_file"
|
||||
print_success "Deployment report saved to $report_file"
|
||||
else
|
||||
print_warning "No deployment data found for report generation"
|
||||
fi
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
print_status "Starting Developer Ecosystem deployment..."
|
||||
|
||||
# Check prerequisites
|
||||
check_prerequisites
|
||||
|
||||
# Compile contracts
|
||||
compile_contracts
|
||||
|
||||
# Deploy contracts
|
||||
deploy_contracts
|
||||
|
||||
# Verify contracts (if requested)
|
||||
verify_contracts
|
||||
|
||||
# Run post-deployment tests
|
||||
run_post_deployment_tests
|
||||
|
||||
# Generate deployment report
|
||||
generate_deployment_report
|
||||
|
||||
print_success "🎉 Developer Ecosystem deployment completed successfully!"
|
||||
echo ""
|
||||
echo "Next steps:"
|
||||
echo "1. Update frontend environment variables with contract addresses"
|
||||
echo "2. Deploy the frontend application"
|
||||
echo "3. Configure API endpoints"
|
||||
echo "4. Run integration tests"
|
||||
}
|
||||
|
||||
# Handle script interruption
|
||||
trap 'print_error "Deployment interrupted"; exit 1' INT TERM
|
||||
|
||||
# Run main function
|
||||
main "$@"
|
||||
100
contracts/scripts/deploy-mainnet.js
Normal file
100
contracts/scripts/deploy-mainnet.js
Normal file
@@ -0,0 +1,100 @@
|
||||
import hardhat from "hardhat";
|
||||
const { ethers } = hardhat;
|
||||
import fs from "fs";
|
||||
|
||||
async function main() {
|
||||
console.log("🚀 Deploying AITBC Smart Contracts to Mainnet");
|
||||
console.log("==============================================");
|
||||
|
||||
const [deployer] = await ethers.getSigners();
|
||||
const balance = await ethers.provider.getBalance(deployer.address);
|
||||
|
||||
console.log(`Deployer: ${deployer.address}`);
|
||||
console.log(`Balance: ${ethers.formatEther(balance)} ETH`);
|
||||
|
||||
if (balance < ethers.parseEther("1")) {
|
||||
throw new Error("Insufficient ETH balance. Minimum 1 ETH recommended for deployment.");
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("Proceeding with contract deployment...");
|
||||
|
||||
// Deployment configuration
|
||||
const deployedContracts = {
|
||||
network: hardhat.network.name,
|
||||
deployer: deployer.address,
|
||||
timestamp: new Date().toISOString(),
|
||||
contracts: {}
|
||||
};
|
||||
|
||||
try {
|
||||
// Deploy core contracts
|
||||
console.log("📦 Deploying AgentWallet...");
|
||||
const AgentWallet = await ethers.getContractFactory("AgentWallet");
|
||||
const agentWallet = await AgentWallet.deploy();
|
||||
await agentWallet.waitForDeployment();
|
||||
const agentWalletAddr = await agentWallet.getAddress();
|
||||
deployedContracts.contracts.AgentWallet = agentWalletAddr;
|
||||
console.log(`✅ AgentWallet deployed: ${agentWalletAddr}`);
|
||||
|
||||
console.log("📦 Deploying AIPowerRental...");
|
||||
const AIPowerRental = await ethers.getContractFactory("AIPowerRental");
|
||||
const aiPowerRental = await AIPowerRental.deploy();
|
||||
await aiPowerRental.waitForDeployment();
|
||||
const aiPowerRentalAddr = await aiPowerRental.getAddress();
|
||||
deployedContracts.contracts.AIPowerRental = aiPowerRentalAddr;
|
||||
console.log(`✅ AIPowerRental deployed: ${aiPowerRentalAddr}`);
|
||||
|
||||
console.log("📦 Deploying AgentServiceMarketplace...");
|
||||
const AgentServiceMarketplace = await ethers.getContractFactory("AgentServiceMarketplace");
|
||||
const agentServiceMarketplace = await AgentServiceMarketplace.deploy();
|
||||
await agentServiceMarketplace.waitForDeployment();
|
||||
const agentServiceMarketplaceAddr = await agentServiceMarketplace.getAddress();
|
||||
deployedContracts.contracts.AgentServiceMarketplace = agentServiceMarketplaceAddr;
|
||||
console.log(`✅ AgentServiceMarketplace deployed: ${agentServiceMarketplaceAddr}`);
|
||||
|
||||
console.log("📦 Deploying DynamicPricing...");
|
||||
const DynamicPricing = await ethers.getContractFactory("DynamicPricing");
|
||||
const dynamicPricing = await DynamicPricing.deploy();
|
||||
await dynamicPricing.waitForDeployment();
|
||||
const dynamicPricingAddr = await dynamicPricing.getAddress();
|
||||
deployedContracts.contracts.DynamicPricing = dynamicPricingAddr;
|
||||
console.log(`✅ DynamicPricing deployed: ${dynamicPricingAddr}`);
|
||||
|
||||
console.log("📦 Deploying AgentStaking...");
|
||||
const AgentStaking = await ethers.getContractFactory("AgentStaking");
|
||||
const agentStaking = await AgentStaking.deploy();
|
||||
await agentStaking.waitForDeployment();
|
||||
const agentStakingAddr = await agentStaking.getAddress();
|
||||
deployedContracts.contracts.AgentStaking = agentStakingAddr;
|
||||
console.log(`✅ AgentStaking deployed: ${agentStakingAddr}`);
|
||||
|
||||
// Save deployment info
|
||||
fs.writeFileSync("deployments.json", JSON.stringify(deployedContracts, null, 2));
|
||||
|
||||
console.log("");
|
||||
console.log("🎉 Deployment Summary:");
|
||||
console.log("====================");
|
||||
console.log(`Network: ${deployedContracts.network}`);
|
||||
console.log(`Deployer: ${deployedContracts.deployer}`);
|
||||
console.log(`Timestamp: ${deployedContracts.timestamp}`);
|
||||
console.log("");
|
||||
console.log("Deployed Contracts:");
|
||||
for (const [name, address] of Object.entries(deployedContracts.contracts)) {
|
||||
console.log(` ${name}: ${address}`);
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("✅ All contracts deployed successfully!");
|
||||
console.log("📁 Deployment saved to: deployments.json");
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Deployment failed:", error);
|
||||
process.exitCode = 1;
|
||||
}
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
225
contracts/scripts/deploy-memory-contracts.js
Normal file
225
contracts/scripts/deploy-memory-contracts.js
Normal file
@@ -0,0 +1,225 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🚀 Deploying Decentralized Memory & Storage Contracts");
|
||||
console.log("==============================================");
|
||||
|
||||
const [deployer] = await ethers.getSigners();
|
||||
const balance = await deployer.getBalance();
|
||||
|
||||
console.log(`Deployer: ${deployer.address}`);
|
||||
console.log(`Balance: ${ethers.utils.formatEther(balance)} ETH`);
|
||||
|
||||
if (balance.lt(ethers.utils.parseEther("1"))) {
|
||||
throw new Error("Insufficient ETH balance. Minimum 1 ETH recommended for deployment.");
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("Proceeding with contract deployment...");
|
||||
|
||||
// Deployment configuration
|
||||
const deployedContracts = {
|
||||
network: hre.network.name,
|
||||
deployer: deployer.address,
|
||||
timestamp: new Date().toISOString(),
|
||||
contracts: {}
|
||||
};
|
||||
|
||||
try {
|
||||
// Deploy AgentMemory contract
|
||||
console.log("📦 Deploying AgentMemory contract...");
|
||||
const AgentMemory = await ethers.getContractFactory("AgentMemory");
|
||||
const agentMemory = await AgentMemory.deploy();
|
||||
await agentMemory.deployed();
|
||||
|
||||
deployedContracts.contracts.AgentMemory = {
|
||||
address: agentMemory.address,
|
||||
deploymentHash: agentMemory.deployTransaction.hash,
|
||||
gasUsed: (await agentMemory.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AgentMemory: ${agentMemory.address}`);
|
||||
|
||||
// Deploy MemoryVerifier contract
|
||||
console.log("📦 Deploying MemoryVerifier contract...");
|
||||
const ZKReceiptVerifier = await ethers.getContractFactory("ZKReceiptVerifier");
|
||||
const zkVerifier = await ZKReceiptVerifier.deploy();
|
||||
await zkVerifier.deployed();
|
||||
|
||||
const MemoryVerifier = await ethers.getContractFactory("MemoryVerifier", {
|
||||
libraries: {
|
||||
ZKReceiptVerifier: zkVerifier.address
|
||||
}
|
||||
});
|
||||
const memoryVerifier = await MemoryVerifier.deploy(zkVerifier.address);
|
||||
await memoryVerifier.deployed();
|
||||
|
||||
deployedContracts.contracts.MemoryVerifier = {
|
||||
address: memoryVerifier.address,
|
||||
deploymentHash: memoryVerifier.deployTransaction.hash,
|
||||
gasUsed: (await memoryVerifier.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ MemoryVerifier: ${memoryVerifier.address}`);
|
||||
|
||||
// Deploy KnowledgeGraphMarket contract
|
||||
console.log("📦 Deploying KnowledgeGraphMarket contract...");
|
||||
|
||||
// Get existing AITBCPaymentProcessor address or deploy a mock one
|
||||
let paymentProcessorAddress;
|
||||
let aitbcTokenAddress;
|
||||
|
||||
try {
|
||||
// Try to get existing payment processor
|
||||
const paymentProcessorFile = `deployed-contracts-${hre.network.name}.json`;
|
||||
if (fs.existsSync(paymentProcessorFile)) {
|
||||
const existingContracts = JSON.parse(fs.readFileSync(paymentProcessorFile, 'utf8'));
|
||||
paymentProcessorAddress = existingContracts.contracts.AITBCPaymentProcessor?.address;
|
||||
aitbcTokenAddress = existingContracts.contracts.AITBCToken?.address;
|
||||
}
|
||||
} catch (error) {
|
||||
console.log("Could not load existing contracts, deploying mock ones...");
|
||||
}
|
||||
|
||||
// Deploy mock AITBC token if needed
|
||||
if (!aitbcTokenAddress) {
|
||||
console.log("📦 Deploying mock AITBC token...");
|
||||
const MockERC20 = await ethers.getContractFactory("MockERC20");
|
||||
const aitbcToken = await MockERC20.deploy(
|
||||
"AITBC Token",
|
||||
"AITBC",
|
||||
ethers.utils.parseEther("1000000")
|
||||
);
|
||||
await aitbcToken.deployed();
|
||||
aitbcTokenAddress = aitbcToken.address;
|
||||
|
||||
deployedContracts.contracts.AITBCToken = {
|
||||
address: aitbcTokenAddress,
|
||||
deploymentHash: aitbcToken.deployTransaction.hash,
|
||||
gasUsed: (await aitbcToken.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ AITBC Token: ${aitbcTokenAddress}`);
|
||||
}
|
||||
|
||||
// Deploy mock payment processor if needed
|
||||
if (!paymentProcessorAddress) {
|
||||
console.log("📦 Deploying mock AITBC Payment Processor...");
|
||||
const MockPaymentProcessor = await ethers.getContractFactory("AITBCPaymentProcessor");
|
||||
const paymentProcessor = await MockPaymentProcessor.deploy(aitbcTokenAddress);
|
||||
await paymentProcessor.deployed();
|
||||
paymentProcessorAddress = paymentProcessor.address;
|
||||
|
||||
deployedContracts.contracts.AITBCPaymentProcessor = {
|
||||
address: paymentProcessorAddress,
|
||||
deploymentHash: paymentProcessor.deployTransaction.hash,
|
||||
gasUsed: (await paymentProcessor.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ Payment Processor: ${paymentProcessorAddress}`);
|
||||
}
|
||||
|
||||
// Deploy KnowledgeGraphMarket
|
||||
const KnowledgeGraphMarket = await ethers.getContractFactory("KnowledgeGraphMarket");
|
||||
const knowledgeGraphMarket = await KnowledgeGraphMarket.deploy(
|
||||
paymentProcessorAddress,
|
||||
aitbcTokenAddress
|
||||
);
|
||||
await knowledgeGraphMarket.deployed();
|
||||
|
||||
deployedContracts.contracts.KnowledgeGraphMarket = {
|
||||
address: knowledgeGraphMarket.address,
|
||||
deploymentHash: knowledgeGraphMarket.deployTransaction.hash,
|
||||
gasUsed: (await knowledgeGraphMarket.deployTransaction.wait()).gasUsed.toString()
|
||||
};
|
||||
|
||||
console.log(`✅ KnowledgeGraphMarket: ${knowledgeGraphMarket.address}`);
|
||||
|
||||
// Initialize contracts
|
||||
console.log("🔧 Initializing contracts...");
|
||||
|
||||
// Authorize deployer as memory verifier
|
||||
await memoryVerifier.authorizeVerifier(deployer.address, 100000, 300);
|
||||
console.log("✅ Authorized deployer as memory verifier");
|
||||
|
||||
// Save deployment information
|
||||
const deploymentFile = `deployed-contracts-${hre.network.name}.json`;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", deploymentFile),
|
||||
JSON.stringify(deployedContracts, null, 2)
|
||||
);
|
||||
|
||||
// Generate environment variables for frontend
|
||||
const envVars = `
|
||||
# AITBC Decentralized Memory & Storage - ${hre.network.name.toUpperCase()}
|
||||
# Generated on ${new Date().toISOString()}
|
||||
|
||||
# Contract Addresses
|
||||
VITE_AGENT_MEMORY_ADDRESS=${agentMemory.address}
|
||||
VITE_MEMORY_VERIFIER_ADDRESS=${memoryVerifier.address}
|
||||
VITE_KNOWLEDGE_GRAPH_MARKET_ADDRESS=${knowledgeGraphMarket.address}
|
||||
VITE_AITBC_TOKEN_ADDRESS=${aitbcTokenAddress}
|
||||
VITE_PAYMENT_PROCESSOR_ADDRESS=${paymentProcessorAddress}
|
||||
|
||||
# Network Configuration
|
||||
VITE_NETWORK_NAME=${hre.network.name}
|
||||
VITE_CHAIN_ID=${hre.network.config.chainId || 1}
|
||||
VITE_RPC_URL=${hre.network.config.url || 'http://localhost:8545'}
|
||||
|
||||
# IPFS Configuration
|
||||
VITE_IPFS_URL=http://localhost:5001
|
||||
VITE_IPFS_GATEWAY_URL=http://localhost:8080/ipfs/
|
||||
|
||||
# Memory Configuration
|
||||
VITE_MEMORY_UPLOAD_THRESHOLD=100
|
||||
VITE_MEMORY_BATCH_SIZE=50
|
||||
VITE_MEMORY_EXPIRY_DAYS=30
|
||||
`;
|
||||
|
||||
const envFile = path.join(__dirname, "..", "..", "apps", "marketplace-web", ".env.memory");
|
||||
fs.writeFileSync(envFile, envVars);
|
||||
|
||||
console.log("");
|
||||
console.log("🎉 CONTRACT DEPLOYMENT COMPLETED");
|
||||
console.log("===============================");
|
||||
console.log(`Total gas used: ${calculateTotalGas(deployedContracts)}`);
|
||||
console.log(`Deployment file: ${deploymentFile}`);
|
||||
console.log(`Environment file: ${envFile}`);
|
||||
console.log("");
|
||||
console.log("📋 Contract Addresses:");
|
||||
console.log(` AgentMemory: ${agentMemory.address}`);
|
||||
console.log(` MemoryVerifier: ${memoryVerifier.address}`);
|
||||
console.log(` KnowledgeGraphMarket: ${knowledgeGraphMarket.address}`);
|
||||
console.log(` AITBC Token: ${aitbcTokenAddress}`);
|
||||
console.log(` Payment Processor: ${paymentProcessorAddress}`);
|
||||
console.log("");
|
||||
console.log("🔧 Next Steps:");
|
||||
console.log(" 1. Verify contracts on Etherscan (if on testnet/mainnet)");
|
||||
console.log(" 2. Update frontend with new contract addresses");
|
||||
console.log(" 3. Test contract functionality");
|
||||
console.log(" 4. Set up IPFS node for storage");
|
||||
|
||||
} catch (error) {
|
||||
console.error("❌ Deployment failed:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function calculateTotalGas(deployedContracts) {
|
||||
let totalGas = 0;
|
||||
for (const contract of Object.values(deployedContracts.contracts)) {
|
||||
if (contract.gasUsed) {
|
||||
totalGas += parseInt(contract.gasUsed);
|
||||
}
|
||||
}
|
||||
return totalGas.toLocaleString();
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
216
contracts/scripts/verify-agent-contracts.js
Normal file
216
contracts/scripts/verify-agent-contracts.js
Normal file
@@ -0,0 +1,216 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🔍 Verifying OpenClaw Autonomous Economics Contracts");
|
||||
console.log("==============================================");
|
||||
|
||||
const networkName = hre.network.name;
|
||||
const deploymentFile = `deployed-contracts-${networkName}.json`;
|
||||
|
||||
// Check if deployment file exists
|
||||
if (!fs.existsSync(deploymentFile)) {
|
||||
console.error(`❌ Deployment file not found: ${deploymentFile}`);
|
||||
console.log("Please run the deployment script first.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Load deployment information
|
||||
const deployedContracts = JSON.parse(fs.readFileSync(deploymentFile, 'utf8'));
|
||||
|
||||
console.log(`Network: ${networkName}`);
|
||||
console.log(`Deployer: ${deployedContracts.deployer}`);
|
||||
console.log(`Timestamp: ${deployedContracts.timestamp}`);
|
||||
console.log("");
|
||||
|
||||
// Check if Etherscan API key is configured
|
||||
const etherscanApiKey = process.env.ETHERSCAN_API_KEY;
|
||||
if (!etherscanApiKey) {
|
||||
console.warn("⚠️ ETHERSCAN_API_KEY not configured");
|
||||
console.log("Set ETHERSCAN_API_KEY in your .env file for automatic verification");
|
||||
console.log("Skipping verification...");
|
||||
return;
|
||||
}
|
||||
|
||||
const contracts = [
|
||||
{
|
||||
name: "AgentWallet",
|
||||
address: deployedContracts.contracts.AgentWallet?.address,
|
||||
constructorArgs: [
|
||||
deployedContracts.contracts.AITBCToken?.address,
|
||||
deployedContracts.contracts.AITBCPaymentProcessor?.address
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "AgentOrchestration",
|
||||
address: deployedContracts.contracts.AgentOrchestration?.address,
|
||||
constructorArgs: []
|
||||
},
|
||||
{
|
||||
name: "AIPowerRental",
|
||||
address: deployedContracts.contracts.AIPowerRental?.address,
|
||||
constructorArgs: [
|
||||
deployedContracts.contracts.AITBCToken?.address
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "AITBCToken",
|
||||
address: deployedContracts.contracts.AITBCToken?.address,
|
||||
constructorArgs: [
|
||||
"AITBC Token",
|
||||
"AITBC",
|
||||
"1000000000000000000000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "AITBCPaymentProcessor",
|
||||
address: deployedContracts.contracts.AITBCPaymentProcessor?.address,
|
||||
constructorArgs: [
|
||||
deployedContracts.contracts.AITBCToken?.address
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
console.log(`Found ${contracts.length} contracts to verify`);
|
||||
console.log("");
|
||||
|
||||
let verificationResults = {
|
||||
verified: [],
|
||||
failed: [],
|
||||
skipped: []
|
||||
};
|
||||
|
||||
for (const contract of contracts) {
|
||||
if (!contract.address) {
|
||||
console.log(`⏭️ Skipping ${contract.name} - no address found`);
|
||||
verificationResults.skipped.push({
|
||||
name: contract.name,
|
||||
reason: "No address found"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(`🔍 Verifying ${contract.name} at ${contract.address}...`);
|
||||
|
||||
try {
|
||||
// Wait for a few seconds to ensure the contract is properly deployed
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
// Verify the contract
|
||||
await hre.run("verify:verify", {
|
||||
address: contract.address,
|
||||
constructorArgs: contract.constructorArgs
|
||||
});
|
||||
|
||||
console.log(`✅ ${contract.name} verified successfully`);
|
||||
verificationResults.verified.push({
|
||||
name: contract.name,
|
||||
address: contract.address,
|
||||
etherscanUrl: `https://${networkName === "mainnet" ? "" : networkName + "."}etherscan.io/address/${contract.address}`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to verify ${contract.name}:`, error.message);
|
||||
|
||||
// Check if it's already verified
|
||||
if (error.message.includes("Already Verified") || error.message.includes("already verified")) {
|
||||
console.log(`✅ ${contract.name} is already verified`);
|
||||
verificationResults.verified.push({
|
||||
name: contract.name,
|
||||
address: contract.address,
|
||||
etherscanUrl: `https://${networkName === "mainnet" ? "" : networkName + "."}etherscan.io/address/${contract.address}`,
|
||||
alreadyVerified: true
|
||||
});
|
||||
} else {
|
||||
verificationResults.failed.push({
|
||||
name: contract.name,
|
||||
address: contract.address,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add delay between verifications to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("🎉 VERIFICATION SUMMARY");
|
||||
console.log("=======================");
|
||||
console.log(`✅ Verified: ${verificationResults.verified.length}`);
|
||||
console.log(`❌ Failed: ${verificationResults.failed.length}`);
|
||||
console.log(`⏭️ Skipped: ${verificationResults.skipped.length}`);
|
||||
console.log("");
|
||||
|
||||
// Show verification results
|
||||
if (verificationResults.verified.length > 0) {
|
||||
console.log("✅ Successfully Verified Contracts:");
|
||||
verificationResults.verified.forEach(contract => {
|
||||
const status = contract.alreadyVerified ? "(Already Verified)" : "";
|
||||
console.log(` ${contract.name}: ${contract.etherscanUrl} ${status}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (verificationResults.failed.length > 0) {
|
||||
console.log("");
|
||||
console.log("❌ Failed Verifications:");
|
||||
verificationResults.failed.forEach(contract => {
|
||||
console.log(` ${contract.name}: ${contract.error}`);
|
||||
});
|
||||
console.log("");
|
||||
console.log("💡 Tips for failed verifications:");
|
||||
console.log(" 1. Wait a few minutes and try again");
|
||||
console.log(" 2. Check if the contract address is correct");
|
||||
console.log(" 3. Verify constructor arguments match exactly");
|
||||
console.log(" 4. Check Etherscan API rate limits");
|
||||
}
|
||||
|
||||
if (verificationResults.skipped.length > 0) {
|
||||
console.log("");
|
||||
console.log("⏭️ Skipped Contracts:");
|
||||
verificationResults.skipped.forEach(contract => {
|
||||
console.log(` ${contract.name}: ${contract.reason}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Save verification results
|
||||
const verificationReport = {
|
||||
timestamp: new Date().toISOString(),
|
||||
network: networkName,
|
||||
results: verificationResults,
|
||||
summary: {
|
||||
total: contracts.length,
|
||||
verified: verificationResults.verified.length,
|
||||
failed: verificationResults.failed.length,
|
||||
skipped: verificationResults.skipped.length
|
||||
}
|
||||
};
|
||||
|
||||
const reportFile = `agent-contract-verification-${networkName}-${Date.now()}.json`;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", reportFile),
|
||||
JSON.stringify(verificationReport, null, 2)
|
||||
);
|
||||
|
||||
console.log(`📄 Verification report saved to: ${reportFile}`);
|
||||
|
||||
// Return appropriate exit code
|
||||
if (verificationResults.failed.length > 0) {
|
||||
console.log("");
|
||||
console.log("⚠️ Some contracts failed verification");
|
||||
console.log("Please check the errors above and try manual verification if needed");
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log("");
|
||||
console.log("🎉 All contracts verified successfully!");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
182
contracts/scripts/verify-contracts.js
Normal file
182
contracts/scripts/verify-contracts.js
Normal file
@@ -0,0 +1,182 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🔍 Verifying AITBC Developer Ecosystem Contracts");
|
||||
console.log("==============================================");
|
||||
|
||||
const network = network.name;
|
||||
|
||||
if (network === "localhost" || network === "hardhat") {
|
||||
console.log("⏭️ Skipping verification for local network");
|
||||
return;
|
||||
}
|
||||
|
||||
// Read deployed contracts
|
||||
const deploymentFile = `deployed-contracts-${network}.json`;
|
||||
const deploymentPath = path.join(__dirname, "..", deploymentFile);
|
||||
|
||||
if (!fs.existsSync(deploymentPath)) {
|
||||
console.error(`❌ Deployment file not found: ${deploymentFile}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const deployedContracts = JSON.parse(fs.readFileSync(deploymentPath, "utf8"));
|
||||
|
||||
console.log(`Network: ${network}`);
|
||||
console.log(`Contracts to verify: ${Object.keys(deployedContracts.contracts).length}`);
|
||||
console.log("");
|
||||
|
||||
const verificationResults = {
|
||||
verified: [],
|
||||
failed: [],
|
||||
skipped: []
|
||||
};
|
||||
|
||||
// Verification configurations for each contract
|
||||
const verificationConfigs = {
|
||||
AITBCToken: {
|
||||
constructorArguments: ["AITBC Token", "AITBC", ethers.utils.parseEther("1000000")]
|
||||
},
|
||||
ZKVerifier: {
|
||||
constructorArguments: []
|
||||
},
|
||||
Groth16Verifier: {
|
||||
constructorArguments: []
|
||||
},
|
||||
AgentBounty: {
|
||||
constructorArguments: [
|
||||
deployedContracts.contracts.AITBCToken.address,
|
||||
deployedContracts.contracts.ZKVerifier.address,
|
||||
deployedContracts.contracts.Groth16Verifier.address
|
||||
]
|
||||
},
|
||||
AgentStaking: {
|
||||
constructorArguments: [deployedContracts.contracts.AITBCToken.address]
|
||||
},
|
||||
PerformanceVerifier: {
|
||||
constructorArguments: [
|
||||
deployedContracts.contracts.ZKVerifier.address,
|
||||
deployedContracts.contracts.Groth16Verifier.address,
|
||||
deployedContracts.contracts.AgentBounty.address
|
||||
]
|
||||
},
|
||||
DisputeResolution: {
|
||||
constructorArguments: [
|
||||
deployedContracts.contracts.AgentBounty.address,
|
||||
deployedContracts.contracts.AITBCToken.address,
|
||||
deployedContracts.contracts.PerformanceVerifier.address
|
||||
]
|
||||
},
|
||||
EscrowService: {
|
||||
constructorArguments: [
|
||||
deployedContracts.contracts.AITBCToken.address,
|
||||
deployedContracts.contracts.AgentBounty.address,
|
||||
deployedContracts.contracts.AgentStaking.address
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
// Verify each contract
|
||||
for (const [contractName, contractInfo] of Object.entries(deployedContracts.contracts)) {
|
||||
console.log(`🔍 Verifying ${contractName}...`);
|
||||
|
||||
try {
|
||||
const config = verificationConfigs[contractName];
|
||||
if (!config) {
|
||||
console.log(`⏭️ Skipping ${contractName} (no verification config)`);
|
||||
verificationResults.skipped.push(contractName);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wait for a few block confirmations
|
||||
console.log(`⏳ Waiting for block confirmations...`);
|
||||
await ethers.provider.waitForTransaction(contractInfo.deploymentHash, 3);
|
||||
|
||||
// Verify contract
|
||||
await hre.run("verify:verify", {
|
||||
address: contractInfo.address,
|
||||
constructorArguments: config.constructorArguments
|
||||
});
|
||||
|
||||
console.log(`✅ ${contractName} verified successfully`);
|
||||
verificationResults.verified.push(contractName);
|
||||
|
||||
} catch (error) {
|
||||
if (error.message.includes("Already Verified")) {
|
||||
console.log(`✅ ${contractName} already verified`);
|
||||
verificationResults.verified.push(contractName);
|
||||
} else {
|
||||
console.log(`❌ ${contractName} verification failed: ${error.message}`);
|
||||
verificationResults.failed.push({
|
||||
contract: contractName,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add delay between verifications to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("📊 Verification Summary");
|
||||
console.log("======================");
|
||||
console.log(`Verified: ${verificationResults.verified.length}`);
|
||||
console.log(`Failed: ${verificationResults.failed.length}`);
|
||||
console.log(`Skipped: ${verificationResults.skipped.length}`);
|
||||
console.log("");
|
||||
|
||||
if (verificationResults.verified.length > 0) {
|
||||
console.log("✅ Verified Contracts:");
|
||||
verificationResults.verified.forEach(name => {
|
||||
console.log(` - ${name}: ${deployedContracts.contracts[name].address}`);
|
||||
});
|
||||
console.log("");
|
||||
}
|
||||
|
||||
if (verificationResults.failed.length > 0) {
|
||||
console.log("❌ Failed Verifications:");
|
||||
verificationResults.failed.forEach(({ contract, error }) => {
|
||||
console.log(` - ${contract}: ${error}`);
|
||||
});
|
||||
console.log("");
|
||||
}
|
||||
|
||||
if (verificationResults.skipped.length > 0) {
|
||||
console.log("⏭️ Skipped Verifications:");
|
||||
verificationResults.skipped.forEach(name => {
|
||||
console.log(` - ${name}`);
|
||||
});
|
||||
console.log("");
|
||||
}
|
||||
|
||||
// Save verification results
|
||||
const verificationResultsFile = `verification-results-${network}.json`;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", verificationResultsFile),
|
||||
JSON.stringify({
|
||||
network: network,
|
||||
timestamp: new Date().toISOString(),
|
||||
results: verificationResults
|
||||
}, null, 2)
|
||||
);
|
||||
|
||||
console.log(`📄 Verification results saved to ${verificationResultsFile}`);
|
||||
console.log("");
|
||||
|
||||
if (verificationResults.failed.length > 0) {
|
||||
console.log("⚠️ Some contracts failed verification. Check the logs above.");
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log("🎉 All contracts verified successfully!");
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
216
contracts/scripts/verify-memory-contracts.js
Normal file
216
contracts/scripts/verify-memory-contracts.js
Normal file
@@ -0,0 +1,216 @@
|
||||
const { ethers } = require("hardhat");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
async function main() {
|
||||
console.log("🔍 Verifying Decentralized Memory & Storage Contracts");
|
||||
console.log("==============================================");
|
||||
|
||||
const networkName = hre.network.name;
|
||||
const deploymentFile = `deployed-contracts-${networkName}.json`;
|
||||
|
||||
// Check if deployment file exists
|
||||
if (!fs.existsSync(deploymentFile)) {
|
||||
console.error(`❌ Deployment file not found: ${deploymentFile}`);
|
||||
console.log("Please run the deployment script first.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Load deployment information
|
||||
const deployedContracts = JSON.parse(fs.readFileSync(deploymentFile, 'utf8'));
|
||||
|
||||
console.log(`Network: ${networkName}`);
|
||||
console.log(`Deployer: ${deployedContracts.deployer}`);
|
||||
console.log(`Timestamp: ${deployedContracts.timestamp}`);
|
||||
console.log("");
|
||||
|
||||
// Check if Etherscan API key is configured
|
||||
const etherscanApiKey = process.env.ETHERSCAN_API_KEY;
|
||||
if (!etherscanApiKey) {
|
||||
console.warn("⚠️ ETHERSCAN_API_KEY not configured");
|
||||
console.log("Set ETHERSCAN_API_KEY in your .env file for automatic verification");
|
||||
console.log("Skipping verification...");
|
||||
return;
|
||||
}
|
||||
|
||||
const contracts = [
|
||||
{
|
||||
name: "AgentMemory",
|
||||
address: deployedContracts.contracts.AgentMemory?.address,
|
||||
constructorArgs: []
|
||||
},
|
||||
{
|
||||
name: "MemoryVerifier",
|
||||
address: deployedContracts.contracts.MemoryVerifier?.address,
|
||||
constructorArgs: [
|
||||
deployedContracts.contracts.ZKReceiptVerifier?.address
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "KnowledgeGraphMarket",
|
||||
address: deployedContracts.contracts.KnowledgeGraphMarket?.address,
|
||||
constructorArgs: [
|
||||
deployedContracts.contracts.AITBCPaymentProcessor?.address,
|
||||
deployedContracts.contracts.AITBCToken?.address
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "AITBCToken",
|
||||
address: deployedContracts.contracts.AITBCToken?.address,
|
||||
constructorArgs: [
|
||||
"AITBC Token",
|
||||
"AITBC",
|
||||
"1000000000000000000000000"
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "AITBCPaymentProcessor",
|
||||
address: deployedContracts.contracts.AITBCPaymentProcessor?.address,
|
||||
constructorArgs: [
|
||||
deployedContracts.contracts.AITBCToken?.address
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
console.log(`Found ${contracts.length} contracts to verify`);
|
||||
console.log("");
|
||||
|
||||
let verificationResults = {
|
||||
verified: [],
|
||||
failed: [],
|
||||
skipped: []
|
||||
};
|
||||
|
||||
for (const contract of contracts) {
|
||||
if (!contract.address) {
|
||||
console.log(`⏭️ Skipping ${contract.name} - no address found`);
|
||||
verificationResults.skipped.push({
|
||||
name: contract.name,
|
||||
reason: "No address found"
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
console.log(`🔍 Verifying ${contract.name} at ${contract.address}...`);
|
||||
|
||||
try {
|
||||
// Wait for a few seconds to ensure the contract is properly deployed
|
||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||
|
||||
// Verify the contract
|
||||
await hre.run("verify:verify", {
|
||||
address: contract.address,
|
||||
constructorArgs: contract.constructorArgs
|
||||
});
|
||||
|
||||
console.log(`✅ ${contract.name} verified successfully`);
|
||||
verificationResults.verified.push({
|
||||
name: contract.name,
|
||||
address: contract.address,
|
||||
etherscanUrl: `https://${networkName === "mainnet" ? "" : networkName + "."}etherscan.io/address/${contract.address}`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to verify ${contract.name}:`, error.message);
|
||||
|
||||
// Check if it's already verified
|
||||
if (error.message.includes("Already Verified") || error.message.includes("already verified")) {
|
||||
console.log(`✅ ${contract.name} is already verified`);
|
||||
verificationResults.verified.push({
|
||||
name: contract.name,
|
||||
address: contract.address,
|
||||
etherscanUrl: `https://${networkName === "mainnet" ? "" : networkName + "."}etherscan.io/address/${contract.address}`,
|
||||
alreadyVerified: true
|
||||
});
|
||||
} else {
|
||||
verificationResults.failed.push({
|
||||
name: contract.name,
|
||||
address: contract.address,
|
||||
error: error.message
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add delay between verifications to avoid rate limiting
|
||||
await new Promise(resolve => setTimeout(resolve, 3000));
|
||||
}
|
||||
|
||||
console.log("");
|
||||
console.log("🎉 VERIFICATION SUMMARY");
|
||||
console.log("======================");
|
||||
console.log(`✅ Verified: ${verificationResults.verified.length}`);
|
||||
console.log(`❌ Failed: ${verificationResults.failed.length}`);
|
||||
console.log(`⏭️ Skipped: ${verificationResults.skipped.length}`);
|
||||
console.log("");
|
||||
|
||||
// Show verification results
|
||||
if (verificationResults.verified.length > 0) {
|
||||
console.log("✅ Successfully Verified Contracts:");
|
||||
verificationResults.verified.forEach(contract => {
|
||||
const status = contract.alreadyVerified ? "(Already Verified)" : "";
|
||||
console.log(` ${contract.name}: ${contract.etherscanUrl} ${status}`);
|
||||
});
|
||||
}
|
||||
|
||||
if (verificationResults.failed.length > 0) {
|
||||
console.log("");
|
||||
console.log("❌ Failed Verifications:");
|
||||
verificationResults.failed.forEach(contract => {
|
||||
console.log(` ${contract.name}: ${contract.error}`);
|
||||
});
|
||||
console.log("");
|
||||
console.log("💡 Tips for failed verifications:");
|
||||
console.log(" 1. Wait a few minutes and try again");
|
||||
console.log(" 2. Check if the contract address is correct");
|
||||
console.log(" 3. Verify constructor arguments match exactly");
|
||||
console.log(" 4. Check Etherscan API rate limits");
|
||||
}
|
||||
|
||||
if (verificationResults.skipped.length > 0) {
|
||||
console.log("");
|
||||
console.log("⏭️ Skipped Contracts:");
|
||||
verificationResults.skipped.forEach(contract => {
|
||||
console.log(` ${contract.name}: ${contract.reason}`);
|
||||
});
|
||||
}
|
||||
|
||||
// Save verification results
|
||||
const verificationReport = {
|
||||
timestamp: new Date().toISOString(),
|
||||
network: networkName,
|
||||
results: verificationResults,
|
||||
summary: {
|
||||
total: contracts.length,
|
||||
verified: verificationResults.verified.length,
|
||||
failed: verificationResults.failed.length,
|
||||
skipped: verificationResults.skipped.length
|
||||
}
|
||||
};
|
||||
|
||||
const reportFile = `memory-contract-verification-${networkName}-${Date.now()}.json`;
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, "..", reportFile),
|
||||
JSON.stringify(verificationReport, null, 2)
|
||||
);
|
||||
|
||||
console.log(`📄 Verification report saved to: ${reportFile}`);
|
||||
|
||||
// Return appropriate exit code
|
||||
if (verificationResults.failed.length > 0) {
|
||||
console.log("");
|
||||
console.log("⚠️ Some contracts failed verification");
|
||||
console.log("Please check the errors above and try manual verification if needed");
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log("");
|
||||
console.log("🎉 All contracts verified successfully!");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
.then(() => process.exit(0))
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user