📄 ProjectManagerStorage.sol
D-OPEN SOVEREIGN

Documentation & Insights

@dev Directly sets a user's balance snapshot. Used by migration scripts only.
Does not enforce authorization — only admin can call.
@dev Directly inserts a historical StripeDonation record.
Used by migration scripts to replay donation history into a new contract.
1/*
2 * Copyright (c) 2026 DataPond D-Library Pty Ltd. ("The Sanctuary")
3 * Non-Profit Public Library — The World Library
4 * 
5 * D-SAFE Certification issued by POND Enterprise.
6 * Published under the D-Open Code Sovereign Licence v1.0 framework
7 * DataPond D-Library All exclusive Right reserved on modifiying the code - CC Attribution to data pond, Non modifiable, Non Commercial.
8 * https://registry.world.bibliotech.com/licence
9 * Source code donated to DataPond D-Library by it's author: data pond.
10 * 
11 * Technical Guardian ("The Shield"): Pond Enterprise Pty Ltd. (ACN 694 747 987)
12 * All liability claims about D-SAFE certification issues coming from the published D-Safe direction must be addressed with Pond Enterprise Pty Ltd.
13 * Code Modification automatically voids the certified liability protection provided by Pond Enterprise.
14 */
15
16// SPDX-License-Identifier: Apache-2.0
17pragma solidity ^0.8.24;
18
19import "./IProjectManagerStorage.sol";
20import {ErrorLibrary} from "./ErrorLibrary.sol";
21
22contract ProjectManagerStorage is IProjectManagerStorage {
23    address public admin;
24    mapping(address => bool) public isAuthorized;
25
26    uint16 private _nbProjects;
27    mapping(uint16 => Project) private projects;
28    mapping(uint16 => uint16) private nbLanguages;
29    mapping(uint16 => mapping(bytes4 => uint16)) private availableLanguagesToIndex;
30    mapping(uint16 => mapping(uint16 => bytes4)) private availableLanguagesFromIndex;
31    mapping(uint16 => mapping(bytes4 => mapping(uint16 => Version))) private versions;
32    mapping(uint16 => mapping(bytes4 => uint16)) private nbVersions;
33    mapping(uint16 => mapping(bytes4 => uint256)) private projectVotingBalances;
34    mapping(uint16 => mapping(address => uint256)) private projectDonations;
35    mapping(address => mapping(uint16 => uint256)) private donations;
36    mapping(address => uint256[3]) private balances;
37    mapping(uint256 => StripeDonation[]) private _weeklyDonations;
38
39    modifier onlyAdmin() {
40        require(msg.sender == admin, "not admin");
41        _;
42    }
43
44    modifier onlyAuthorized() {
45        require(isAuthorized[msg.sender] || msg.sender == admin, "not authorized");
46        _;
47    }
48
49    constructor() {
50        admin = msg.sender;
51    }
52
53    function addAuthorized(address caller) external onlyAdmin {
54        isAuthorized[caller] = true;
55    }
56
57    function removeAuthorized(address caller) external onlyAdmin {
58        isAuthorized[caller] = false;
59    }
60
61    // --- Read Methods ---
62    function nbProjects() external view returns (uint16) { return _nbProjects; }
63    function getProject(uint16 projectId) external view returns (uint16 id) { return projects[projectId].id; }
64    function getNbLanguages(uint16 projectId) external view returns (uint16) { return nbLanguages[projectId]; }
65    function getLanguageAtIndex(uint16 projectId, uint16 index) external view returns (bytes4) { return availableLanguagesFromIndex[projectId][index]; }
66    function getLanguageIndex(uint16 projectId, bytes4 lang) external view returns (uint16) { return availableLanguagesToIndex[projectId][lang]; }
67    function getNbVersions(uint16 projectId, bytes4 lang) external view returns (uint16) { return nbVersions[projectId][lang]; }
68    function getVersion(uint16 projectId, bytes4 lang, uint16 versionNumber) external view returns (Version memory) { return versions[projectId][lang][versionNumber]; }
69    function getVotingBalance(uint16 projectId, bytes4 lang) external view returns (uint256) { return projectVotingBalances[projectId][lang]; }
70    function getUserProjectDonation(uint16 projectId, address user) external view returns (uint256) { return projectDonations[projectId][user]; }
71    function getUserTotalDonationForProject(address user, uint16 projectId) external view returns (uint256) { return donations[user][projectId]; }
72    function getUserBalances(address user) external view returns (uint256[3] memory) { return balances[user]; }
73
74    function getWeeklyDonations(uint256 week) external view returns (StripeDonation[] memory) {
75        return _weeklyDonations[week];
76    }
77
78    function getDonationsRange(uint256 fromWeek, uint256 toWeek) external view returns (StripeDonation[] memory) {
79        uint256 totalCount = 0;
80        for (uint256 w = fromWeek; w <= toWeek; w++) {
81            totalCount += _weeklyDonations[w].length;
82        }
83
84        StripeDonation[] memory allDonations = new StripeDonation[](totalCount);
85        uint256 index = 0;
86        for (uint256 w = fromWeek; w <= toWeek; w++) {
87            StripeDonation[] storage weekDonations = _weeklyDonations[w];
88            for (uint256 i = 0; i < weekDonations.length; i++) {
89                allDonations[index] = weekDonations[i];
90                index++;
91            }
92        }
93        return allDonations;
94    }
95
96    // --- Write Methods ---
97    function incrementNbProjects() external onlyAuthorized returns (uint16) {
98        _nbProjects++;
99        return _nbProjects;
100    }
101
102    function setProject(uint16 projectId) external onlyAuthorized {
103        projects[projectId] = Project(projectId);
104    }
105
106    function setNbLanguages(uint16 projectId, uint16 count) external onlyAuthorized {
107        nbLanguages[projectId] = count;
108    }
109
110    function setLanguageMapping(uint16 projectId, bytes4 lang, uint16 index) external onlyAuthorized {
111        availableLanguagesToIndex[projectId][lang] = index;
112        availableLanguagesFromIndex[projectId][index] = lang;
113    }
114
115    function setNbVersions(uint16 projectId, bytes4 lang, uint16 count) external onlyAuthorized {
116        nbVersions[projectId][lang] = count;
117    }
118
119    function setVersion(uint16 projectId, bytes4 lang, uint16 versionNumber, Version calldata version) external onlyAuthorized {
120        versions[projectId][lang][versionNumber] = version;
121    }
122
123    function updateVotingBalance(uint16 projectId, bytes4 lang, uint256 amount, bool add) external onlyAuthorized {
124        if (add) projectVotingBalances[projectId][lang] += amount;
125        else projectVotingBalances[projectId][lang] -= amount;
126    }
127
128    function updateUserProjectDonation(uint16 projectId, address user, uint256 amount, bool add) external onlyAuthorized {
129        if (add) projectDonations[projectId][user] += amount;
130        else projectDonations[projectId][user] -= amount;
131    }
132
133    function updateUserTotalDonationForProject(address user, uint16 projectId, uint256 amount, bool add) external onlyAuthorized {
134        if (add) donations[user][projectId] += amount;
135        else donations[user][projectId] -= amount;
136    }
137
138    function updateUserBalances(address user, uint256[3] calldata newBalances) external onlyAuthorized {
139        balances[user] = newBalances;
140    }
141
142    function recordStripeDonation(uint256 week, StripeDonation calldata donation) external onlyAuthorized {
143        _weeklyDonations[week].push(donation);
144    }
145
146    // ===== Admin bulk-import (migration scripts only) =====
147
148    /**
149     * @dev Directly sets a user's balance snapshot. Used by migration scripts only.
150     * Does not enforce authorization — only admin can call.
151     */
152    function importUserBalances(address user, uint256[3] calldata bals) external onlyAdmin {
153        require(user != address(0), "zero addr");
154        balances[user] = bals;
155    }
156
157    /**
158     * @dev Directly inserts a historical StripeDonation record.
159     * Used by migration scripts to replay donation history into a new contract.
160     */
161    function importStripeDonation(uint256 week, StripeDonation calldata donation) external onlyAdmin {
162        _weeklyDonations[week].push(donation);
163    }
164}