Skip to content

Commit dec07f3

Browse files
authored
Create SmartContractRegistry.sol
```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; contract SmartContractRegistry { struct Contract { string name; string version; address owner; string sourceCode; string documentation; bool isVerified; uint256 creationTime; ContractStatus status; address[] authorizedUsers; uint256 lastUpdateTime; } struct ContractVersion { string version; string sourceCode; uint256 deploymentTime; string changeLog; } enum ContractStatus { Draft, UnderReview, Active, Deprecated, Paused } // State variables mapping(bytes32 => Contract) public contracts; mapping(bytes32 => ContractVersion[]) public contractVersions; mapping(address => bytes32[]) public userContracts; mapping(address => bool) public administrators; uint256 public totalContracts; address public owner; bool public paused; // Events event ContractCreated(bytes32 indexed contractId, string name, address owner); event ContractUpdated(bytes32 indexed contractId, string version); event ContractStatusChanged(bytes32 indexed contractId, ContractStatus newStatus); event UserAuthorized(bytes32 indexed contractId, address user); event UserRevoked(bytes32 indexed contractId, address user); event AdministratorAdded(address administrator); event AdministratorRemoved(address administrator); // Modifiers modifier onlyOwner() { require(msg.sender == owner, "Only owner can call this function"); _; } modifier onlyAdmin() { require(administrators[msg.sender], "Only administrators can call this function"); _; } modifier contractExists(bytes32 contractId) { require(contracts[contractId].owner != address(0), "Contract does not exist"); _; } modifier notPaused() { require(!paused, "Contract is paused"); _; } modifier onlyContractOwner(bytes32 contractId) { require(contracts[contractId].owner == msg.sender, "Only contract owner can call this function"); _; } constructor() { owner = msg.sender; administrators[msg.sender] = true; paused = false; } // Core functions function createContract( string memory name, string memory version, string memory sourceCode, string memory documentation ) external notPaused returns (bytes32) { require(bytes(name).length > 0, "Name cannot be empty"); require(bytes(version).length > 0, "Version cannot be empty"); require(bytes(sourceCode).length > 0, "Source code cannot be empty"); bytes32 contractId = keccak256(abi.encodePacked(name, msg.sender, block.timestamp)); require(contracts[contractId].owner == address(0), "Contract ID already exists"); Contract storage newContract = contracts[contractId]; newContract.name = name; newContract.version = version; newContract.owner = msg.sender; newContract.sourceCode = sourceCode; newContract.documentation = documentation; newContract.isVerified = false; newContract.creationTime = block.timestamp; newContract.status = ContractStatus.Draft; newContract.lastUpdateTime = block.timestamp; // Add initial version ContractVersion memory initialVersion = ContractVersion({ version: version, sourceCode: sourceCode, deploymentTime: block.timestamp, changeLog: "Initial version" }); contractVersions[contractId].push(initialVersion); // Update user contracts userContracts[msg.sender].push(contractId); totalContracts++; emit ContractCreated(contractId, name, msg.sender); return contractId; } function updateContract( bytes32 contractId, string memory newVersion, string memory newSourceCode, string memory changeLog ) external contractExists(contractId) onlyContractOwner(contractId) notPaused { require(bytes(newVersion).length > 0, "Version cannot be empty"); require(bytes(newSourceCode).length > 0, "Source code cannot be empty"); Contract storage contractToUpdate = contracts[contractId]; contractToUpdate.version = newVersion; contractToUpdate.sourceCode = newSourceCode; contractToUpdate.lastUpdateTime = block.timestamp; contractToUpdate.isVerified = false; // Add new version ContractVersion memory newContractVersion = ContractVersion({ version: newVersion, sourceCode: newSourceCode, deploymentTime: block.timestamp, changeLog: changeLog }); contractVersions[contractId].push(newContractVersion); emit ContractUpdated(contractId, newVersion); } function changeContractStatus( bytes32 contractId, ContractStatus newStatus ) external contractExists(contractId) onlyAdmin { contracts[contractId].status = newStatus; emit ContractStatusChanged(contractId, newStatus); } function authorizeUser( bytes32 contractId, address user ) external contractExists(contractId) onlyContractOwner(contractId) { require(user != address(0), "Invalid user address"); require(!isUserAuthorized(contractId, user), "User already authorized"); contracts[contractId].authorizedUsers.push(user); emit UserAuthorized(contractId, user); } function revokeUser( bytes32 contractId, address user ) external contractExists(contractId) onlyContractOwner(contractId) { require(isUserAuthorized(contractId, user), "User not authorized"); Contract storage contractToUpdate = contracts[contractId]; for (uint i = 0; i < contractToUpdate.authorizedUsers.length; i++) { if (contractToUpdate.authorizedUsers[i] == user) { // Remove user by replacing with last element and popping contractToUpdate.authorizedUsers[i] = contractToUpdate.authorizedUsers[contractToUpdate.authorizedUsers.length - 1]; contractToUpdate.authorizedUsers.pop(); break; } } emit UserRevoked(contractId, user); } // Admin functions function addAdministrator(address newAdmin) external onlyOwner { require(newAdmin != address(0), "Invalid administrator address"); require(!administrators[newAdmin], "Already an administrator"); administrators[newAdmin] = true; emit AdministratorAdded(newAdmin); } function removeAdministrator(address admin) external onlyOwner { require(admin != owner, "Cannot remove contract owner"); require(administrators[admin], "Not an administrator"); administrators[admin] = false; emit AdministratorRemoved(admin); } function togglePause() external onlyOwner { paused = !paused; } // View functions function getContract(bytes32 contractId) external view returns ( string memory name, string memory version, address owner, bool isVerified, uint256 creationTime, ContractStatus status, uint256 lastUpdateTime ) { Contract storage contractData = contracts[contractId]; require(contractData.owner != address(0), "Contract does not exist"); return ( contractData.name, contractData.version, contractData.owner, contractData.isVerified, contractData.creationTime, contractData.status, contractData.lastUpdateTime ); } function getContractVersions(bytes32 contractId) external view returns (ContractVersion[] memory) { return contractVersions[contractId]; } function getUserContracts(address user) external view returns (bytes32[] memory) { return userContracts[user]; } function isUserAuthorized(bytes32 contractId, address user) public view returns (bool) { Contract storage contractData = contracts[contractId]; if (contractData.owner == user) return true; for (uint i = 0; i < contractData.authorizedUsers.length; i++) { if (contractData.authorizedUsers[i] == user) return true; } return false; } function getContractCount() external view returns (uint256) { return totalContracts; } } ```
1 parent d293d0e commit dec07f3

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)