// SPDX-License-Identifier: MIT
* @dev Smart contract para registro inmutable de decisiones IA
// ========== STRUCTS ==========
string eventType; // 'ai_execution', 'human_approval', etc.
uint256 actorId; // ID del usuario/agente
bytes32 dataHash; // SHA-256 hash de los datos
uint16 confidenceScore; // 0-10000 (0.00% - 100.00%)
bool isSensitiveData; // Procesado con MPC?
bytes32 mpcProofHash; // Hash del ZKP (si aplica)
address logger; // Dirección que registró
uint256 blockNumber; // Bloque en que se registró
bytes32 originalDecisionHash;
bytes32 modifiedOutputHash;
uint256 approvalTimestamp;
// ========== STATE VARIABLES ==========
mapping(bytes32 => AIDecision) public decisions;
mapping(bytes32 => HumanApproval) public approvals;
bytes32[] public decisionHashes;
bytes32[] public approvalHashes;
uint256 public totalDecisions;
uint256 public totalApprovals;
// ========== EVENTS ==========
bytes32 indexed decisionHash,
event HumanApprovalLogged(
bytes32 indexed approvalHash,
bytes32 indexed originalDecisionHash,
uint256 indexed supervisorId,
// ========== MODIFIERS ==========
modifier validConfidence(uint16 confidence) {
require(confidence <= 10000, "Confidence must be <= 10000");
// ========== FUNCTIONS ==========
* @dev Registra una decisión IA
) public validConfidence(confidenceScore) returns (bytes32) {
bytes32 decisionHash = keccak256(
// Verificar que no existe
require(decisions[decisionHash].timestamp == 0, "Decision already exists");
decisions[decisionHash] = AIDecision({
confidenceScore: confidenceScore,
requiresApproval: requiresApproval,
isSensitiveData: isSensitiveData,
mpcProofHash: mpcProofHash,
blockNumber: block.number
decisionHashes.push(decisionHash);
* @dev Registra una aprobación humana
function logHumanApproval(
bytes32 originalDecisionHash,
bytes32 modifiedOutputHash,
string memory justification,
uint256 approvalTimestamp
) public returns (bytes32) {
// Verificar que la decisión original existe
decisions[originalDecisionHash].timestamp != 0,
"Original decision not found"
// Generar hash de aprobación
bytes32 approvalHash = keccak256(
approvals[approvalHash] = HumanApproval({
originalDecisionHash: originalDecisionHash,
supervisorId: supervisorId,
modifiedOutputHash: modifiedOutputHash,
justification: justification,
approvalTimestamp: approvalTimestamp
approvalHashes.push(approvalHash);
emit HumanApprovalLogged(
* @dev Obtiene decisión por hash
function getDecision(bytes32 decisionHash)
returns (AIDecision memory)
require(decisions[decisionHash].timestamp != 0, "Decision not found");
return decisions[decisionHash];
* @dev Obtiene aprobación por hash
function getApproval(bytes32 approvalHash)
returns (HumanApproval memory)
approvals[approvalHash].approvalTimestamp != 0,
return approvals[approvalHash];
* @dev Obtiene estadísticas generales
function getStats() public view returns (
return (totalDecisions, totalApprovals, block.number);
* @dev Verifica integridad de una decisión
function verifyDecisionIntegrity(
) public view returns (bool) {
AIDecision memory decision = decisions[decisionHash];
keccak256(bytes(decision.eventType)) == keccak256(bytes(eventType)) &&
decision.actorId == actorId &&
decision.dataHash == dataHash &&
decision.timestamp == timestamp