pragma solidity ^0.4.0; contract JointAccountNetwork { // User structure to store user details struct User { uint userId; string userName; bool isRegistered; } // Joint Account structure struct JointAccount { uint user1Id; uint user2Id; uint user1Balance; uint user2Balance; bool isActive; } // Mapping to store users mapping(uint => User) public users; // Mapping to store joint accounts between users mapping(bytes32 => JointAccount) public jointAccounts; // Mapping to track user connections mapping(uint => uint[]) public userConnections; // Events for logging event UserRegistered(uint userId, string userName); event AccountCreated(uint user1Id, uint user2Id); event AmountSent(uint fromUserId, uint toUserId, uint amount); event AccountClosed(uint user1Id, uint user2Id); // Register a new user function registerUser(uint userId, string userName) public { require(!users[userId].isRegistered); users[userId] = User({ userId: userId, userName: userName, isRegistered: true }); UserRegistered(userId, userName); } // Generate unique key for joint account function _getJointAccountKey(uint user1Id, uint user2Id) internal constant returns (bytes32) { return keccak256(min(user1Id, user2Id), max(user1Id, user2Id)); } // Create a joint account between two users function createAcc(uint user1Id, uint user2Id, uint initialBalance) public { require(users[user1Id].isRegistered && users[user2Id].isRegistered); require(user1Id != user2Id); bytes32 accountKey = _getJointAccountKey(user1Id, user2Id); require(!jointAccounts[accountKey].isActive); jointAccounts[accountKey] = JointAccount({ user1Id: user1Id, user2Id: user2Id, user1Balance: initialBalance / 2, user2Balance: initialBalance / 2, isActive: true }); // Add connection for routing userConnections[user1Id].push(user2Id); userConnections[user2Id].push(user1Id); AccountCreated(user1Id, user2Id); } // Find shortest path between two users for routing function findPath(uint fromUserId, uint toUserId) public constant returns (uint[]) { uint[] memory path = new uint[](10); // Limit path length bool[] memory visited = new bool[](1000); // Assuming max 1000 users uint pathLength = 0; path[pathLength++] = fromUserId; visited[fromUserId] = true; uint currentUser = fromUserId; while (currentUser != toUserId && pathLength < 10) { bool foundNextHop = false; for (uint i = 0; i < userConnections[currentUser].length; i++) { uint nextUser = userConnections[currentUser][i]; if (!visited[nextUser]) { path[pathLength++] = nextUser; visited[nextUser] = true; currentUser = nextUser; foundNextHop = true; if (nextUser == toUserId) break; } } if (!foundNextHop) break; } if (path[pathLength - 1] != toUserId) { // No path found return new uint[](0); } // Trim path to actual length uint[] memory finalPath = new uint[](pathLength); for ( i = 0; i < pathLength; i++) { finalPath[i] = path[i]; } return finalPath; } // Send amount between users through network function sendAmount(uint fromUserId, uint toUserId, uint amount) public { uint[] memory path = findPath(fromUserId, toUserId); require(path.length > 1); uint remainingAmount = amount; for (uint i = 0; i < path.length - 1; i++) { uint currentUser = path[i]; uint nextUser = path[i + 1]; bytes32 accountKey = _getJointAccountKey(currentUser, nextUser); JointAccount storage account = jointAccounts[accountKey]; require(account.isActive); // Determine current and next user's balance in the joint account uint currentUserBalance = (currentUser == account.user1Id) ? account.user1Balance : account.user2Balance; require(currentUserBalance >= remainingAmount); // Update balances if (currentUser == account.user1Id) { account.user1Balance -= remainingAmount; account.user2Balance += remainingAmount; } else { account.user2Balance -= remainingAmount; account.user1Balance += remainingAmount; } } AmountSent(fromUserId, toUserId, amount); } // Close joint account between two users function closeAccount(uint user1Id, uint user2Id) public { bytes32 accountKey = _getJointAccountKey(user1Id, user2Id); require(jointAccounts[accountKey].isActive); // Remove connections _removeConnection(user1Id, user2Id); _removeConnection(user2Id, user1Id); // Mark account as inactive jointAccounts[accountKey].isActive = false; AccountClosed(user1Id, user2Id); } // Remove connection between users function _removeConnection(uint userId, uint connectionId) internal { for (uint i = 0; i < userConnections[userId].length; i++) { if (userConnections[userId][i] == connectionId) { userConnections[userId][i] = userConnections[userId][userConnections[userId].length - 1]; userConnections[userId].length--; break; } } } // Utility function to get minimum of two numbers function min(uint a, uint b) internal constant returns (uint) { return a < b ? a : b; } // Utility function to get maximum of two numbers function max(uint a, uint b) internal constant returns (uint) { return a > b ? a : b; } }
0.4.18