Files
smom-dbis-138/contracts/vault/GRUVaultIndex.sol
T
defiQUGandCursor 651fb59786 Add mainnet checkpoint stack: ISO attestation, participant Etherscan surface, and services.
Ship AddressActivityRegistry V1/V2, ISO20022IntakeGateway, Chain138ParticipantSurface,
checkpoint hub contracts, checkpoint-core package, aggregator/indexer/sdk services,
relay profile guards, M00 diamond bridge facet, and OMNL compliance contracts.

Co-authored-by: Cursor <[email protected]>
2026-06-24 21:54:05 -07:00

132 lines
4.1 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @title GRUVaultIndex
* @notice Canonical index of GRU vault instances across tiers, tokens, IBAN, and URA policy profiles.
* @dev Written by VaultFactory (FACTORY_ROLE) or registrar during vault creation.
*/
contract GRUVaultIndex is AccessControl {
bytes32 public constant FACTORY_ROLE = keccak256("FACTORY_ROLE");
bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE");
/// @dev GRU monetary tier: 0=M00, 1=M0, 2=M1
struct VaultRecord {
address entity;
address baseToken;
address depositToken;
address debtToken;
uint8 gruTier;
bytes32 ibanHash;
bytes32 policyProfileKey;
uint256 recordedAt;
bool active;
}
mapping(address => VaultRecord) public vaults;
address[] public allVaults;
event VaultRecorded(
address indexed vault,
address indexed entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 policyProfileKey
);
event PolicyProfileKeyPatched(address indexed vault, bytes32 policyProfileKey);
event VaultImported(
address indexed vault,
address indexed entity,
address baseToken,
bytes32 policyProfileKey
);
constructor(address admin) {
require(admin != address(0), "GRUVaultIndex: zero admin");
_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(REGISTRAR_ROLE, admin);
}
function grantFactoryRole(address factory) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(factory != address(0), "GRUVaultIndex: zero factory");
_grantRole(FACTORY_ROLE, factory);
}
function recordVault(
address vault,
address entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 policyProfileKey
) external onlyRole(FACTORY_ROLE) {
require(vault != address(0), "GRUVaultIndex: zero vault");
require(!vaults[vault].active, "GRUVaultIndex: exists");
vaults[vault] = VaultRecord({
entity: entity,
baseToken: baseToken,
depositToken: depositToken,
debtToken: debtToken,
gruTier: gruTier,
ibanHash: ibanHash,
policyProfileKey: policyProfileKey,
recordedAt: block.timestamp,
active: true
});
allVaults.push(vault);
emit VaultRecorded(vault, entity, baseToken, depositToken, debtToken, gruTier, ibanHash, policyProfileKey);
}
/// @notice Admin backfill when vaults were indexed before policy profile publish.
function patchPolicyProfileKey(address vault, bytes32 policyProfileKey)
external
onlyRole(DEFAULT_ADMIN_ROLE)
{
require(vaults[vault].active, "GRUVaultIndex: unknown");
vaults[vault].policyProfileKey = policyProfileKey;
emit PolicyProfileKeyPatched(vault, policyProfileKey);
}
/// @notice Registrar migration import (e.g. re-index with policy keys from a prior GRUVaultIndex).
function importVault(
address vault,
address entity,
address baseToken,
address depositToken,
address debtToken,
uint8 gruTier,
bytes32 ibanHash,
bytes32 policyProfileKey,
uint256 recordedAt
) external onlyRole(REGISTRAR_ROLE) {
require(vault != address(0), "GRUVaultIndex: zero vault");
require(!vaults[vault].active, "GRUVaultIndex: exists");
vaults[vault] = VaultRecord({
entity: entity,
baseToken: baseToken,
depositToken: depositToken,
debtToken: debtToken,
gruTier: gruTier,
ibanHash: ibanHash,
policyProfileKey: policyProfileKey,
recordedAt: recordedAt,
active: true
});
allVaults.push(vault);
emit VaultImported(vault, entity, baseToken, policyProfileKey);
}
}