ваше сообщение коммита

This commit is contained in:
2025-08-15 22:36:50 +03:00
parent 5238e1ee55
commit 3765c65a18
29 changed files with 904 additions and 651 deletions

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../../../build-info/29c61b08eb590d8fc12c8139671115f4.json"
"buildInfo": "../../../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

View File

@@ -1,4 +1,4 @@
{
"_format": "hh-sol-dbg-1",
"buildInfo": "../../build-info/ae6e57b918547db576362d7ba12641eb.json"
"buildInfo": "../../build-info/ab387c71734b3d3e5e7817d328027586.json"
}

File diff suppressed because one or more lines are too long

View File

@@ -2,8 +2,8 @@
"_format": "hh-sol-cache-2",
"files": {
"/home/alex/Digital_Legal_Entity(DLE)/backend/contracts/DLE.sol": {
"lastModificationDate": 1755277189432,
"contentHash": "03b4ac83148b5b1246f64c54fa0e959c",
"lastModificationDate": 1755280436490,
"contentHash": "f676e9964a39b0fccdc62a9114266863",
"sourceName": "contracts/DLE.sol",
"solcConfig": {
"version": "0.8.20",
@@ -160,47 +160,6 @@
"ECDSA"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": {
"lastModificationDate": 1754306768254,
"contentHash": "51c2083b160453420aaa0a046c16d5ca",
"sourceName": "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../ERC20.sol",
"../../../governance/utils/Votes.sol",
"../../../utils/structs/Checkpoints.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"ERC20Votes"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol": {
"lastModificationDate": 1754306768254,
"contentHash": "b1a8fc63b83ce00408e0c9ed1230b717",
@@ -244,6 +203,47 @@
"ERC20Permit"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol": {
"lastModificationDate": 1754306768254,
"contentHash": "51c2083b160453420aaa0a046c16d5ca",
"sourceName": "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../ERC20.sol",
"../../../governance/utils/Votes.sol",
"../../../utils/structs/Checkpoints.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"ERC20Votes"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/Context.sol": {
"lastModificationDate": 1754306760451,
"contentHash": "67bfbc07588eb8683b3fd8f6f909563e",
@@ -396,91 +396,6 @@
"IERC20Metadata"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/governance/utils/Votes.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "95aceafdc639babdd22576e5e3774d64",
"sourceName": "@openzeppelin/contracts/governance/utils/Votes.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../../interfaces/IERC5805.sol",
"../../utils/Context.sol",
"../../utils/Nonces.sol",
"../../utils/cryptography/EIP712.sol",
"../../utils/structs/Checkpoints.sol",
"../../utils/math/SafeCast.sol",
"../../utils/cryptography/ECDSA.sol",
"../../utils/types/Time.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"Votes"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/structs/Checkpoints.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "657c6dfea3bae1af948de6113ba01cea",
"sourceName": "@openzeppelin/contracts/utils/structs/Checkpoints.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../math/Math.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"Checkpoints"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/Nonces.sol": {
"lastModificationDate": 1754306760451,
"contentHash": "c32d108058718efb9061b88e83a83f79",
@@ -518,46 +433,6 @@
"Nonces"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC5805.sol": {
"lastModificationDate": 1754306760460,
"contentHash": "65ba9f89b1057e2192e341b286d4e261",
"sourceName": "@openzeppelin/contracts/interfaces/IERC5805.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../governance/utils/IVotes.sol",
"./IERC6372.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IERC5805"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/EIP712.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "8dbb261c55f358342798c4d1803d4f8e",
@@ -599,10 +474,10 @@
"EIP712"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "2adca1150f58fc6f3d1f0a0f22ee7cca",
"sourceName": "@openzeppelin/contracts/utils/math/SafeCast.sol",
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
"lastModificationDate": 1754306768254,
"contentHash": "94ec15baf0d5df863f45b8f351937ec7",
"sourceName": "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
@@ -633,158 +508,7 @@
"^0.8.20"
],
"artifacts": [
"SafeCast"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/types/Time.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "d83e7814a059fc1287fd765f424ce004",
"sourceName": "@openzeppelin/contracts/utils/types/Time.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../math/Math.sol",
"../math/SafeCast.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"Time"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "905ffceb29869fee4b5a649abe7e2927",
"sourceName": "@openzeppelin/contracts/governance/utils/IVotes.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IVotes"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC6372.sol": {
"lastModificationDate": 1754306760460,
"contentHash": "414cd6acf090e4009cf016ff62ecbd88",
"sourceName": "@openzeppelin/contracts/interfaces/IERC6372.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IERC6372"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol": {
"lastModificationDate": 1754306760460,
"contentHash": "94364524cb1a39dcbc3d3afff6d8e53e",
"sourceName": "@openzeppelin/contracts/interfaces/IERC5267.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IERC5267"
"IERC20Permit"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/ShortStrings.sol": {
@@ -826,6 +550,43 @@
"ShortStrings"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC5267.sol": {
"lastModificationDate": 1754306760460,
"contentHash": "94364524cb1a39dcbc3d3afff6d8e53e",
"sourceName": "@openzeppelin/contracts/interfaces/IERC5267.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IERC5267"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol": {
"lastModificationDate": 1754306764465,
"contentHash": "86fd93657e4e27ff76c38699e9b9fcef",
@@ -983,6 +744,43 @@
"Math"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/math/SafeCast.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "2adca1150f58fc6f3d1f0a0f22ee7cca",
"sourceName": "@openzeppelin/contracts/utils/math/SafeCast.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"SafeCast"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/math/SignedMath.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "ae3528afb8bdb0a7dcfba5b115ee8074",
@@ -1059,10 +857,175 @@
"Panic"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": {
"lastModificationDate": 1754306768254,
"contentHash": "94ec15baf0d5df863f45b8f351937ec7",
"sourceName": "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol",
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/governance/utils/Votes.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "95aceafdc639babdd22576e5e3774d64",
"sourceName": "@openzeppelin/contracts/governance/utils/Votes.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../../interfaces/IERC5805.sol",
"../../utils/Context.sol",
"../../utils/Nonces.sol",
"../../utils/cryptography/EIP712.sol",
"../../utils/structs/Checkpoints.sol",
"../../utils/math/SafeCast.sol",
"../../utils/cryptography/ECDSA.sol",
"../../utils/types/Time.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"Votes"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/structs/Checkpoints.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "657c6dfea3bae1af948de6113ba01cea",
"sourceName": "@openzeppelin/contracts/utils/structs/Checkpoints.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../math/Math.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"Checkpoints"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC5805.sol": {
"lastModificationDate": 1754306760460,
"contentHash": "65ba9f89b1057e2192e341b286d4e261",
"sourceName": "@openzeppelin/contracts/interfaces/IERC5805.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../governance/utils/IVotes.sol",
"./IERC6372.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IERC5805"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/utils/types/Time.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "d83e7814a059fc1287fd765f424ce004",
"sourceName": "@openzeppelin/contracts/utils/types/Time.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [
"../math/Math.sol",
"../math/SafeCast.sol"
],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"Time"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/governance/utils/IVotes.sol": {
"lastModificationDate": 1754306764456,
"contentHash": "905ffceb29869fee4b5a649abe7e2927",
"sourceName": "@openzeppelin/contracts/governance/utils/IVotes.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
@@ -1093,7 +1056,44 @@
"^0.8.20"
],
"artifacts": [
"IERC20Permit"
"IVotes"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/node_modules/@openzeppelin/contracts/interfaces/IERC6372.sol": {
"lastModificationDate": 1754306760460,
"contentHash": "414cd6acf090e4009cf016ff62ecbd88",
"sourceName": "@openzeppelin/contracts/interfaces/IERC6372.sol",
"solcConfig": {
"version": "0.8.20",
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": true,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata"
],
"": [
"ast"
]
}
}
}
},
"imports": [],
"versionPragmas": [
"^0.8.20"
],
"artifacts": [
"IERC6372"
]
},
"/home/alex/Digital_Legal_Entity(DLE)/backend/contracts/FactoryDeployer.sol": {

View File

@@ -26,7 +26,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
struct DLEInfo {
string name;
string symbol;
string tokenImage; // Картинка токена (base64 или URL)
string location;
string coordinates;
uint256 jurisdiction;
@@ -39,7 +38,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
struct DLEConfig {
string name;
string symbol;
string tokenImage; // Картинка токена (base64 или URL)
string location;
string coordinates;
uint256 jurisdiction;
@@ -91,7 +89,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
event DLEInitialized(
string name,
string symbol,
string tokenImage,
string location,
string coordinates,
uint256 jurisdiction,
@@ -112,7 +109,7 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
event ProposalExecutionApprovedInChain(uint256 proposalId, uint256 chainId);
event ChainAdded(uint256 chainId);
event ChainRemoved(uint256 chainId);
event DLEInfoUpdated(string name, string symbol, string tokenImage, string location, string coordinates, uint256 jurisdiction, string[] okvedCodes, uint256 kpp);
event DLEInfoUpdated(string name, string symbol, string location, string coordinates, uint256 jurisdiction, string[] okvedCodes, uint256 kpp);
event QuorumPercentageUpdated(uint256 oldQuorumPercentage, uint256 newQuorumPercentage);
event CurrentChainIdUpdated(uint256 oldChainId, uint256 newChainId);
@@ -129,7 +126,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
dleInfo = DLEInfo({
name: config.name,
symbol: config.symbol,
tokenImage: config.tokenImage,
location: config.location,
coordinates: config.coordinates,
jurisdiction: config.jurisdiction,
@@ -166,7 +162,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
emit DLEInitialized(
config.name,
config.symbol,
config.tokenImage,
config.location,
config.coordinates,
config.jurisdiction,
@@ -509,11 +504,11 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
// Декодируем операцию
(bytes4 selector, bytes memory data) = abi.decode(_operation, (bytes4, bytes));
if (selector == bytes4(keccak256("updateDLEInfo(string,string,string,string,string,uint256,uint256,string[],uint256)"))) {
if (selector == bytes4(keccak256("updateDLEInfo(string,string,string,string,uint256,string[],uint256)"))) {
// Операция обновления информации DLE
(string memory name, string memory symbol, string memory tokenImage, string memory location, string memory coordinates,
uint256 jurisdiction, string[] memory okvedCodes, uint256 kpp) = abi.decode(data, (string, string, string, string, string, uint256, string[], uint256));
_updateDLEInfo(name, symbol, tokenImage, location, coordinates, jurisdiction, okvedCodes, kpp);
(string memory name, string memory symbol, string memory location, string memory coordinates,
uint256 jurisdiction, string[] memory okvedCodes, uint256 kpp) = abi.decode(data, (string, string, string, string, uint256, string[], uint256));
_updateDLEInfo(name, symbol, location, coordinates, jurisdiction, okvedCodes, kpp);
} else if (selector == bytes4(keccak256("updateQuorumPercentage(uint256)"))) {
// Операция обновления процента кворума
(uint256 newQuorumPercentage) = abi.decode(data, (uint256));
@@ -550,7 +545,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
* @dev Обновить информацию DLE
* @param _name Новое название
* @param _symbol Новый символ
* @param _tokenImage Новая картинка токена
* @param _location Новое местонахождение
* @param _coordinates Новые координаты
* @param _jurisdiction Новая юрисдикция
@@ -560,7 +554,6 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
function _updateDLEInfo(
string memory _name,
string memory _symbol,
string memory _tokenImage,
string memory _location,
string memory _coordinates,
uint256 _jurisdiction,
@@ -575,14 +568,13 @@ contract DLE is ERC20, ERC20Permit, ERC20Votes, ReentrancyGuard {
dleInfo.name = _name;
dleInfo.symbol = _symbol;
dleInfo.tokenImage = _tokenImage;
dleInfo.location = _location;
dleInfo.coordinates = _coordinates;
dleInfo.jurisdiction = _jurisdiction;
dleInfo.okvedCodes = _okvedCodes;
dleInfo.kpp = _kpp;
emit DLEInfoUpdated(_name, _symbol, _tokenImage, _location, _coordinates, _jurisdiction, _okvedCodes, _kpp);
emit DLEInfoUpdated(_name, _symbol, _location, _coordinates, _jurisdiction, _okvedCodes, _kpp);
}
/**

View File

@@ -195,8 +195,12 @@ router.post('/verify', async (req, res) => {
return res.status(401).json({ success: false, error: 'Invalid signature' });
}
// СРАЗУ проверяем наличие админских токенов
const adminStatus = await authService.checkAdminTokens(normalizedAddress);
logger.info(`[verify] Admin status for ${normalizedAddress}: ${adminStatus}`);
let userId;
let isAdmin = false;
let isAdmin = adminStatus;
// Проверяем, авторизован ли пользователь уже
if (req.session.authenticated && req.session.userId) {
@@ -214,11 +218,11 @@ router.post('/verify', async (req, res) => {
`[verify] Wallet ${normalizedAddress} linked to user ${userId}: already exists`
);
} else {
// Находим или создаем пользователя, если не авторизован
const result = await authService.findOrCreateUser(address);
// Находим или создаем пользователя с уже известной ролью
const result = await authService.findOrCreateUser(address, adminStatus);
userId = result.userId;
isAdmin = result.isAdmin;
logger.info(`[verify] Found or created user ${userId} for wallet ${normalizedAddress}`);
logger.info(`[verify] Found or created user ${userId} for wallet ${normalizedAddress} with admin status: ${isAdmin}`);
}
// Сохраняем идентификаторы гостевой сессии
@@ -230,14 +234,6 @@ router.post('/verify', async (req, res) => {
await identityService.saveIdentity(userId, 'guest', previousGuestId, true);
}
// Проверяем наличие админских токенов
const adminStatus = await authService.checkAdminTokens(normalizedAddress);
if (adminStatus) {
await db.getQuery()('UPDATE users SET role = $1 WHERE id = $2', ['admin', userId]);
isAdmin = true;
}
// Обновляем сессию
req.session.userId = userId;
req.session.authenticated = true;

View File

@@ -217,10 +217,11 @@ router.post('/get-proposals', async (req, res) => {
const provider = new ethers.JsonRpcProvider(rpcUrl);
// ABI для чтения предложений (только читаемые поля)
// ABI для чтения предложений (используем правильные функции из смарт-контракта)
const dleAbi = [
"function proposals(uint256) external view returns (uint256 id, string description, uint256 forVotes, uint256 againstVotes, bool executed, uint256 deadline, address initiator, bytes operation)",
"function checkProposalResult(uint256 _proposalId) external view returns (bool)",
"function getProposalSummary(uint256 _proposalId) external view returns (uint256 id, string memory description, uint256 forVotes, uint256 againstVotes, bool executed, bool canceled, uint256 deadline, address initiator, uint256 governanceChainId, uint256 snapshotTimepoint, uint256[] memory targets)",
"function checkProposalResult(uint256 _proposalId) external view returns (bool passed, bool quorumReached)",
"function getProposalState(uint256 _proposalId) external view returns (uint8 state)",
"event ProposalCreated(uint256 proposalId, address initiator, string description)"
];
@@ -250,8 +251,9 @@ router.post('/get-proposals', async (req, res) => {
while (retryCount < maxRetries) {
try {
proposal = await dle.proposals(proposalId);
isPassed = await dle.checkProposalResult(proposalId);
proposal = await dle.getProposalSummary(proposalId);
const result = await dle.checkProposalResult(proposalId);
isPassed = result.passed;
break; // Успешно прочитали
} catch (error) {
retryCount++;
@@ -264,19 +266,18 @@ router.post('/get-proposals', async (req, res) => {
}
}
// governanceChainId не сохраняется в предложении, используем текущую цепочку
const governanceChainId = 11155111; // Sepolia chain ID
console.log(`[Blockchain] Данные предложения ${proposalId}:`, {
id: Number(proposal.id),
description: proposal.description,
forVotes: Number(proposal.forVotes),
againstVotes: Number(proposal.againstVotes),
executed: proposal.executed,
canceled: proposal.canceled,
deadline: Number(proposal.deadline),
initiator: proposal.initiator,
operation: proposal.operation,
governanceChainId: Number(governanceChainId)
governanceChainId: Number(proposal.governanceChainId),
snapshotTimepoint: Number(proposal.snapshotTimepoint),
targets: proposal.targets
});
const proposalInfo = {
@@ -285,10 +286,12 @@ router.post('/get-proposals', async (req, res) => {
forVotes: Number(proposal.forVotes),
againstVotes: Number(proposal.againstVotes),
executed: proposal.executed,
canceled: proposal.canceled,
deadline: Number(proposal.deadline),
initiator: proposal.initiator,
operation: proposal.operation,
governanceChainId: Number(governanceChainId),
governanceChainId: Number(proposal.governanceChainId),
snapshotTimepoint: Number(proposal.snapshotTimepoint),
targetChains: proposal.targets.map(chainId => Number(chainId)),
isPassed: isPassed,
blockNumber: events[i].blockNumber
};

View File

@@ -39,7 +39,6 @@ async function main() {
const dleConfig = {
name: params.name,
symbol: params.symbol,
tokenImage: params.tokenImage || '',
location: params.location,
coordinates: params.coordinates,
jurisdiction: params.jurisdiction,

View File

@@ -58,9 +58,10 @@ class AuthService {
/**
* Находит или создает пользователя по адресу кошелька
* @param {string} address - Адрес кошелька
* @param {boolean} isAdmin - Предварительно проверенный статус админа
* @returns {Promise<{userId: number, isAdmin: boolean}>}
*/
async findOrCreateUser(address) {
async findOrCreateUser(address, isAdmin = null) {
try {
// Нормализуем адрес - всегда приводим к нижнему регистру
const normalizedAddress = ethers.getAddress(address).toLowerCase();
@@ -78,15 +79,15 @@ class AuthService {
}
const userData = user[0];
// Проверяем роль администратора при каждой аутентификации
const isAdmin = await checkAdminRole(normalizedAddress);
// Используем предварительно проверенный статус админа или проверяем заново
const adminStatus = isAdmin !== null ? isAdmin : await checkAdminRole(normalizedAddress);
// Если статус админа изменился, обновляем роль в базе данных
if (userData.role === 'admin' && !isAdmin) {
if (userData.role === 'admin' && !adminStatus) {
await db.getQuery()('UPDATE users SET role = $1 WHERE id = $2', ['user', userData.id]);
logger.info(`Updated user ${userData.id} role to user (admin tokens no longer present)`);
return { userId: userData.id, isAdmin: false };
} else if (userData.role !== 'admin' && isAdmin) {
} else if (userData.role !== 'admin' && adminStatus) {
await db.getQuery()('UPDATE users SET role = $1 WHERE id = $2', ['admin', userData.id]);
logger.info(`Updated user ${userData.id} role to admin (admin tokens found)`);
return { userId: userData.id, isAdmin: true };
@@ -98,8 +99,11 @@ class AuthService {
};
}
// Если пользователь не найден, создаем нового
const newUserResult = await db.getQuery()('INSERT INTO users (role) VALUES ($1) RETURNING id', ['user']);
// Если пользователь не найден, создаем нового с правильной ролью
const adminStatus = isAdmin !== null ? isAdmin : await checkAdminRole(normalizedAddress);
const initialRole = adminStatus ? 'admin' : 'user';
const newUserResult = await db.getQuery()('INSERT INTO users (role) VALUES ($1) RETURNING id', [initialRole]);
const userId = newUserResult.rows[0].id;
// Добавляем идентификатор кошелька (всегда в нижнем регистре)
@@ -109,21 +113,11 @@ class AuthService {
provider_id: normalizedAddress
});
// Проверяем, есть ли у пользователя роль админа
const isAdmin = await checkAdminRole(normalizedAddress);
logger.info(`New user ${userId} role check result: ${isAdmin ? 'admin' : 'user'}`);
// Если у пользователя есть админские токены, обновляем его роль
if (isAdmin) {
await db.getQuery()('UPDATE users SET role = $1 WHERE id = $2', ['admin', userId]);
logger.info(
`New user ${userId} with wallet ${normalizedAddress} automatically granted admin role`
);
}
logger.info(`New user ${userId} created with role: ${initialRole} for wallet ${normalizedAddress}`);
broadcastContactsUpdate();
return { userId, isAdmin };
return { userId, isAdmin: adminStatus };
} catch (error) {
logger.error('Error finding or creating user:', error);
throw error;

View File

@@ -225,18 +225,7 @@ class DLEV2Service {
throw new Error('Должна быть выбрана хотя бы одна сеть для деплоя');
}
// Проверяем размер картинки токена (если передана)
if (params.tokenImage && params.tokenImage.trim() !== '') {
const base64Size = params.tokenImage.length;
if (base64Size > 350) {
throw new Error(`Размер картинки токена превышает лимит: ${base64Size} байт. Максимальный размер: 350 байт`);
}
// Проверяем, что это валидный base64
if (!params.tokenImage.startsWith('data:image/')) {
throw new Error('Картинка токена должна быть в формате base64 data URL');
}
}
}
/**

View File

@@ -11,6 +11,7 @@
*/
const WebSocket = require('ws');
const authService = require('./services/auth-service');
let wss = null;
// Храним клиентов по userId для персонализированных уведомлений
@@ -57,6 +58,11 @@ function initWSS(server) {
timestamp: data.timestamp
}));
}
if (data.type === 'request_token_balances' && data.address) {
// Запрос балансов токенов
handleTokenBalancesRequest(ws, data.address, data.userId);
}
} catch (error) {
// console.error('❌ [WebSocket] Ошибка парсинга сообщения:', error);
}
@@ -402,6 +408,49 @@ function broadcastAuthTokenUpdated(tokenData) {
broadcastToAllClients(message);
}
// Функции для балансов токенов
function broadcastTokenBalancesUpdate(userId, balances) {
const message = JSON.stringify({
type: 'token_balances_updated',
data: {
balances: balances,
timestamp: Date.now()
}
});
// Отправляем конкретному пользователю
const userClients = wsClients.get(userId.toString());
if (userClients) {
for (const ws of userClients) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(message);
}
}
}
}
function broadcastTokenBalanceChanged(userId, tokenAddress, newBalance, network) {
const message = JSON.stringify({
type: 'token_balance_changed',
data: {
tokenAddress: tokenAddress,
balance: newBalance,
network: network,
timestamp: Date.now()
}
});
// Отправляем конкретному пользователю
const userClients = wsClients.get(userId.toString());
if (userClients) {
for (const ws of userClients) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(message);
}
}
}
}
module.exports = {
initWSS,
broadcastContactsUpdate,
@@ -418,6 +467,42 @@ module.exports = {
broadcastAuthTokenAdded,
broadcastAuthTokenDeleted,
broadcastAuthTokenUpdated,
broadcastTokenBalancesUpdate,
broadcastTokenBalanceChanged,
getConnectedUsers,
getStats
};
};
// Обработчик запроса балансов токенов
async function handleTokenBalancesRequest(ws, address, userId) {
try {
console.log(`[WebSocket] Запрос балансов для адреса: ${address}`);
// Получаем балансы через authService
const balances = await authService.getUserTokenBalances(address);
// Отправляем ответ клиенту
ws.send(JSON.stringify({
type: 'token_balances_response',
data: {
address: address,
balances: balances,
timestamp: Date.now()
}
}));
console.log(`[WebSocket] Отправлены балансы для ${address}:`, balances.length, 'токенов');
} catch (error) {
console.error('[WebSocket] Ошибка при получении балансов:', error);
// Отправляем ошибку клиенту
ws.send(JSON.stringify({
type: 'token_balances_error',
data: {
address: address,
error: error.message,
timestamp: Date.now()
}
}));
}
}