Skip to content

Commit c19e30b

Browse files
authored
Merge pull request #19 from ewdlop/ewdlop-patch-15
Create SmartContractRegistry.sol
2 parents d293d0e + dec07f3 commit c19e30b

File tree

1 file changed

+258
-0
lines changed

1 file changed

+258
-0
lines changed
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.19;
3+
4+
contract SmartContractRegistry {
5+
struct Contract {
6+
string name;
7+
string version;
8+
address owner;
9+
string sourceCode;
10+
string documentation;
11+
bool isVerified;
12+
uint256 creationTime;
13+
ContractStatus status;
14+
address[] authorizedUsers;
15+
uint256 lastUpdateTime;
16+
}
17+
18+
struct ContractVersion {
19+
string version;
20+
string sourceCode;
21+
uint256 deploymentTime;
22+
string changeLog;
23+
}
24+
25+
enum ContractStatus {
26+
Draft,
27+
UnderReview,
28+
Active,
29+
Deprecated,
30+
Paused
31+
}
32+
33+
// State variables
34+
mapping(bytes32 => Contract) public contracts;
35+
mapping(bytes32 => ContractVersion[]) public contractVersions;
36+
mapping(address => bytes32[]) public userContracts;
37+
mapping(address => bool) public administrators;
38+
39+
uint256 public totalContracts;
40+
address public owner;
41+
bool public paused;
42+
43+
// Events
44+
event ContractCreated(bytes32 indexed contractId, string name, address owner);
45+
event ContractUpdated(bytes32 indexed contractId, string version);
46+
event ContractStatusChanged(bytes32 indexed contractId, ContractStatus newStatus);
47+
event UserAuthorized(bytes32 indexed contractId, address user);
48+
event UserRevoked(bytes32 indexed contractId, address user);
49+
event AdministratorAdded(address administrator);
50+
event AdministratorRemoved(address administrator);
51+
52+
// Modifiers
53+
modifier onlyOwner() {
54+
require(msg.sender == owner, "Only owner can call this function");
55+
_;
56+
}
57+
58+
modifier onlyAdmin() {
59+
require(administrators[msg.sender], "Only administrators can call this function");
60+
_;
61+
}
62+
63+
modifier contractExists(bytes32 contractId) {
64+
require(contracts[contractId].owner != address(0), "Contract does not exist");
65+
_;
66+
}
67+
68+
modifier notPaused() {
69+
require(!paused, "Contract is paused");
70+
_;
71+
}
72+
73+
modifier onlyContractOwner(bytes32 contractId) {
74+
require(contracts[contractId].owner == msg.sender, "Only contract owner can call this function");
75+
_;
76+
}
77+
78+
constructor() {
79+
owner = msg.sender;
80+
administrators[msg.sender] = true;
81+
paused = false;
82+
}
83+
84+
// Core functions
85+
function createContract(
86+
string memory name,
87+
string memory version,
88+
string memory sourceCode,
89+
string memory documentation
90+
) external notPaused returns (bytes32) {
91+
require(bytes(name).length > 0, "Name cannot be empty");
92+
require(bytes(version).length > 0, "Version cannot be empty");
93+
require(bytes(sourceCode).length > 0, "Source code cannot be empty");
94+
95+
bytes32 contractId = keccak256(abi.encodePacked(name, msg.sender, block.timestamp));
96+
97+
require(contracts[contractId].owner == address(0), "Contract ID already exists");
98+
99+
Contract storage newContract = contracts[contractId];
100+
newContract.name = name;
101+
newContract.version = version;
102+
newContract.owner = msg.sender;
103+
newContract.sourceCode = sourceCode;
104+
newContract.documentation = documentation;
105+
newContract.isVerified = false;
106+
newContract.creationTime = block.timestamp;
107+
newContract.status = ContractStatus.Draft;
108+
newContract.lastUpdateTime = block.timestamp;
109+
110+
// Add initial version
111+
ContractVersion memory initialVersion = ContractVersion({
112+
version: version,
113+
sourceCode: sourceCode,
114+
deploymentTime: block.timestamp,
115+
changeLog: "Initial version"
116+
});
117+
contractVersions[contractId].push(initialVersion);
118+
119+
// Update user contracts
120+
userContracts[msg.sender].push(contractId);
121+
totalContracts++;
122+
123+
emit ContractCreated(contractId, name, msg.sender);
124+
return contractId;
125+
}
126+
127+
function updateContract(
128+
bytes32 contractId,
129+
string memory newVersion,
130+
string memory newSourceCode,
131+
string memory changeLog
132+
) external contractExists(contractId) onlyContractOwner(contractId) notPaused {
133+
require(bytes(newVersion).length > 0, "Version cannot be empty");
134+
require(bytes(newSourceCode).length > 0, "Source code cannot be empty");
135+
136+
Contract storage contractToUpdate = contracts[contractId];
137+
contractToUpdate.version = newVersion;
138+
contractToUpdate.sourceCode = newSourceCode;
139+
contractToUpdate.lastUpdateTime = block.timestamp;
140+
contractToUpdate.isVerified = false;
141+
142+
// Add new version
143+
ContractVersion memory newContractVersion = ContractVersion({
144+
version: newVersion,
145+
sourceCode: newSourceCode,
146+
deploymentTime: block.timestamp,
147+
changeLog: changeLog
148+
});
149+
contractVersions[contractId].push(newContractVersion);
150+
151+
emit ContractUpdated(contractId, newVersion);
152+
}
153+
154+
function changeContractStatus(
155+
bytes32 contractId,
156+
ContractStatus newStatus
157+
) external contractExists(contractId) onlyAdmin {
158+
contracts[contractId].status = newStatus;
159+
emit ContractStatusChanged(contractId, newStatus);
160+
}
161+
162+
function authorizeUser(
163+
bytes32 contractId,
164+
address user
165+
) external contractExists(contractId) onlyContractOwner(contractId) {
166+
require(user != address(0), "Invalid user address");
167+
require(!isUserAuthorized(contractId, user), "User already authorized");
168+
169+
contracts[contractId].authorizedUsers.push(user);
170+
emit UserAuthorized(contractId, user);
171+
}
172+
173+
function revokeUser(
174+
bytes32 contractId,
175+
address user
176+
) external contractExists(contractId) onlyContractOwner(contractId) {
177+
require(isUserAuthorized(contractId, user), "User not authorized");
178+
179+
Contract storage contractToUpdate = contracts[contractId];
180+
for (uint i = 0; i < contractToUpdate.authorizedUsers.length; i++) {
181+
if (contractToUpdate.authorizedUsers[i] == user) {
182+
// Remove user by replacing with last element and popping
183+
contractToUpdate.authorizedUsers[i] = contractToUpdate.authorizedUsers[contractToUpdate.authorizedUsers.length - 1];
184+
contractToUpdate.authorizedUsers.pop();
185+
break;
186+
}
187+
}
188+
189+
emit UserRevoked(contractId, user);
190+
}
191+
192+
// Admin functions
193+
function addAdministrator(address newAdmin) external onlyOwner {
194+
require(newAdmin != address(0), "Invalid administrator address");
195+
require(!administrators[newAdmin], "Already an administrator");
196+
197+
administrators[newAdmin] = true;
198+
emit AdministratorAdded(newAdmin);
199+
}
200+
201+
function removeAdministrator(address admin) external onlyOwner {
202+
require(admin != owner, "Cannot remove contract owner");
203+
require(administrators[admin], "Not an administrator");
204+
205+
administrators[admin] = false;
206+
emit AdministratorRemoved(admin);
207+
}
208+
209+
function togglePause() external onlyOwner {
210+
paused = !paused;
211+
}
212+
213+
// View functions
214+
function getContract(bytes32 contractId) external view returns (
215+
string memory name,
216+
string memory version,
217+
address owner,
218+
bool isVerified,
219+
uint256 creationTime,
220+
ContractStatus status,
221+
uint256 lastUpdateTime
222+
) {
223+
Contract storage contractData = contracts[contractId];
224+
require(contractData.owner != address(0), "Contract does not exist");
225+
226+
return (
227+
contractData.name,
228+
contractData.version,
229+
contractData.owner,
230+
contractData.isVerified,
231+
contractData.creationTime,
232+
contractData.status,
233+
contractData.lastUpdateTime
234+
);
235+
}
236+
237+
function getContractVersions(bytes32 contractId) external view returns (ContractVersion[] memory) {
238+
return contractVersions[contractId];
239+
}
240+
241+
function getUserContracts(address user) external view returns (bytes32[] memory) {
242+
return userContracts[user];
243+
}
244+
245+
function isUserAuthorized(bytes32 contractId, address user) public view returns (bool) {
246+
Contract storage contractData = contracts[contractId];
247+
if (contractData.owner == user) return true;
248+
249+
for (uint i = 0; i < contractData.authorizedUsers.length; i++) {
250+
if (contractData.authorizedUsers[i] == user) return true;
251+
}
252+
return false;
253+
}
254+
255+
function getContractCount() external view returns (uint256) {
256+
return totalContracts;
257+
}
258+
}

0 commit comments

Comments
 (0)