UNPKG

sorted-doubly-ll

Version:
867 lines (866 loc) 1.22 MB
{ "contractName": "SortedDoublyLL", "abi": [], "bytecode": "0x604c602c600b82828239805160001a60731460008114601c57601e565bfe5b5030600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea165627a7a7230582075b77b32caddbed2be9bdbf1d846559d5c78e6a6e5c85890092cfc27da2a32d20029", "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea165627a7a7230582075b77b32caddbed2be9bdbf1d846559d5c78e6a6e5c85890092cfc27da2a32d20029", "sourceMap": "1251:12905:1:-;;132:2:-1;166:7;155:9;146:7;137:37;252:7;246:14;243:1;238:23;232:4;229:33;270:1;265:20;;;;222:63;;265:20;274:9;222:63;;298:9;295:1;288:20;328:4;319:7;311:22;352:7;343;336:24", "deployedSourceMap": "1251:12905:1:-;;;;;;;;", "source": "pragma solidity 0.5.0;\n\nimport \"openzeppelin-solidity/contracts/math/SafeMath.sol\";\n\n\n/*\n * @title A sorted doubly linked list with nodes sorted in descending order. Optionally accepts insert position hints\n *\n * Given a new node with a `key`, a hint is of the form `(prevId, nextId)` s.t. `prevId` and `nextId` are adjacent in the list.\n * `prevId` is a node with a key >= `key` and `nextId` is a node with a key <= `key`. If the sender provides a hint that is a valid insert position\n * the insert operation is a constant time storage write. However, the provided hint in a given transaction might be a valid insert position, but if other transactions are included first, when\n * the given transaction is executed the provided hint may no longer be a valid insert position. For example, one of the nodes referenced might be removed or their keys may\n * be updated such that the the pair of nodes in the hint no longer represent a valid insert position. If one of the nodes in the hint becomes invalid, we still try to use the other\n * valid node as a starting point for finding the appropriate insert position. If both nodes in the hint become invalid, we use the head of the list as a starting point\n * to find the appropriate insert position.\n */\nlibrary SortedDoublyLL {\n using SafeMath for uint256;\n\n // Information for a node in the list\n struct Node {\n uint256 key; // Node's key used for sorting\n address nextId; // Id of next node (smaller key) in the list\n address prevId; // Id of previous node (larger key) in the list\n }\n\n // Information for the list\n struct Data {\n address head; // Head of the list. Also the node in the list with the largest key\n address tail; // Tail of the list. Also the node in the list with the smallest key\n uint256 maxSize; // Maximum size of the list\n uint256 size; // Current size of the list\n mapping (address => Node) nodes; // Track the corresponding ids for each node in the list\n }\n\n /*\n * @dev Set the maximum size of the list\n * @param _size Maximum size\n */\n function setMaxSize(Data storage self, uint256 _size) internal {\n // New max size must be greater than old max size\n require(\n _size > self.maxSize,\n \"new max size must be greater than old max size\"\n );\n\n self.maxSize = _size;\n }\n\n /*\n * @dev Add a node to the list\n * @param _id Node's id\n * @param _key Node's key\n * @param _prevId Id of previous node for the insert position\n * @param _nextId Id of next node for the insert position\n */\n function insert(Data storage self, address _id, uint256 _key, address _prevId, address _nextId) internal {\n // List must not be full\n require(\n !isFull(self),\n \"cannot insert into a full list\"\n );\n // List must not already contain node\n require(\n !contains(self, _id),\n \"cannot insert node that already exists\"\n );\n // Node id must not be null\n require(\n _id != address(0),\n \"cannot insert node with a null id\"\n );\n // Key must be non-zero\n require(\n _key > 0,\n \"cannot insert node with zero key\"\n );\n\n address prevId = _prevId;\n address nextId = _nextId;\n\n if (!validInsertPosition(self, _key, prevId, nextId)) {\n // Sender's hint was not a valid insert position\n // Use sender's hint to find a valid insert position\n (prevId, nextId) = findInsertPosition(self, _key, prevId, nextId);\n }\n\n self.nodes[_id].key = _key;\n\n if (prevId == address(0) && nextId == address(0)) {\n // Insert as head and tail\n self.head = _id;\n self.tail = _id;\n } else if (prevId == address(0)) {\n // Insert before `prevId` as the head\n self.nodes[_id].nextId = self.head;\n self.nodes[self.head].prevId = _id;\n self.head = _id;\n } else if (nextId == address(0)) {\n // Insert after `nextId` as the tail\n self.nodes[_id].prevId = self.tail;\n self.nodes[self.tail].nextId = _id;\n self.tail = _id;\n } else {\n // Insert at insert position between `prevId` and `nextId`\n self.nodes[_id].nextId = nextId;\n self.nodes[_id].prevId = prevId;\n self.nodes[prevId].nextId = _id;\n self.nodes[nextId].prevId = _id;\n }\n\n self.size = self.size.add(1);\n }\n\n /*\n * @dev Remove a node from the list\n * @param _id Node's id\n */\n function remove(Data storage self, address _id) internal {\n // List must contain the node\n require(\n contains(self, _id),\n \"cannot remote node that does not exist\"\n );\n\n if (self.size > 1) {\n // List contains more than a single node\n if (_id == self.head) {\n // The removed node is the head\n // Set head to next node\n self.head = self.nodes[_id].nextId;\n // Set prev pointer of new head to null\n self.nodes[self.head].prevId = address(0);\n } else if (_id == self.tail) {\n // The removed node is the tail\n // Set tail to previous node\n self.tail = self.nodes[_id].prevId;\n // Set next pointer of new tail to null\n self.nodes[self.tail].nextId = address(0);\n } else {\n // The removed node is neither the head nor the tail\n // Set next pointer of previous node to the next node\n self.nodes[self.nodes[_id].prevId].nextId = self.nodes[_id].nextId;\n // Set prev pointer of next node to the previous node\n self.nodes[self.nodes[_id].nextId].prevId = self.nodes[_id].prevId;\n }\n } else {\n // List contains a single node\n // Set the head and tail to null\n self.head = address(0);\n self.tail = address(0);\n }\n\n delete self.nodes[_id];\n self.size = self.size.sub(1);\n }\n\n /*\n * @dev Update the key of a node in the list\n * @param _id Node's id\n * @param _newKey Node's new key\n * @param _prevId Id of previous node for the new insert position\n * @param _nextId Id of next node for the new insert position\n */\n function updateKey(Data storage self, address _id, uint256 _newKey, address _prevId, address _nextId) internal {\n // List must contain the node\n require(\n contains(self, _id),\n \"cannot update node that does not exist\"\n );\n\n // Remove node from the list\n remove(self, _id);\n\n if (_newKey > 0) {\n // Insert node if it has a non-zero key\n insert(self, _id, _newKey, _prevId, _nextId);\n }\n }\n\n /*\n * @dev Checks if the list contains a node\n * @param _transcoder Address of transcoder\n */\n function contains(Data storage self, address _id) internal view returns (bool) {\n // List only contains non-zero keys, so if key is non-zero the node exists\n return self.nodes[_id].key > 0;\n }\n\n /*\n * @dev Checks if the list is full\n */\n function isFull(Data storage self) internal view returns (bool) {\n return self.size == self.maxSize;\n }\n\n /*\n * @dev Checks if the list is empty\n */\n function isEmpty(Data storage self) internal view returns (bool) {\n return self.size == 0;\n }\n\n /*\n * @dev Returns the current size of the list\n */\n function getSize(Data storage self) internal view returns (uint256) {\n return self.size;\n }\n\n /*\n * @dev Returns the maximum size of the list\n */\n function getMaxSize(Data storage self) internal view returns (uint256) {\n return self.maxSize;\n }\n\n /*\n * @dev Returns the key of a node in the list\n * @param _id Node's id\n */\n function getKey(Data storage self, address _id) internal view returns (uint256) {\n return self.nodes[_id].key;\n }\n\n /*\n * @dev Returns the first node in the list (node with the largest key)\n */\n function getFirst(Data storage self) internal view returns (address) {\n return self.head;\n }\n\n /*\n * @dev Returns the last node in the list (node with the smallest key)\n */\n function getLast(Data storage self) internal view returns (address) {\n return self.tail;\n }\n\n /*\n * @dev Returns the next node (with a smaller key) in the list for a given node\n * @param _id Node's id\n */\n function getNext(Data storage self, address _id) internal view returns (address) {\n return self.nodes[_id].nextId;\n }\n\n /*\n * @dev Returns the previous node (with a larger key) in the list for a given node\n * @param _id Node's id\n */\n function getPrev(Data storage self, address _id) internal view returns (address) {\n return self.nodes[_id].prevId;\n }\n\n /*\n * @dev Check if a pair of nodes is a valid insertion point for a new node with the given key\n * @param _key Node's key\n * @param _prevId Id of previous node for the insert position\n * @param _nextId Id of next node for the insert position\n */\n function validInsertPosition(Data storage self, uint256 _key, address _prevId, address _nextId) internal view returns (bool) {\n if (_prevId == address(0) && _nextId == address(0)) {\n // `(null, null)` is a valid insert position if the list is empty\n return isEmpty(self);\n } else if (_prevId == address(0)) {\n // `(null, _nextId)` is a valid insert position if `_nextId` is the head of the list\n return self.head == _nextId && _key >= self.nodes[_nextId].key;\n } else if (_nextId == address(0)) {\n // `(_prevId, null)` is a valid insert position if `_prevId` is the tail of the list\n return self.tail == _prevId && _key <= self.nodes[_prevId].key;\n } else {\n // `(_prevId, _nextId)` is a valid insert position if they are adjacent nodes and `_key` falls between the two nodes' keys\n return self.nodes[_prevId].nextId == _nextId && self.nodes[_prevId].key >= _key && _key >= self.nodes[_nextId].key;\n }\n }\n\n /*\n * @dev Descend the list (larger keys to smaller keys) to find a valid insert position\n * @param _key Node's key\n * @param _startId Id of node to start ascending the list from\n */\n function descendList(Data storage self, uint256 _key, address _startId) internal view returns (address, address) {\n // If `_startId` is the head, check if the insert position is before the head\n if (self.head == _startId && _key >= self.nodes[_startId].key) {\n return (address(0), _startId);\n }\n\n address prevId = _startId;\n address nextId = self.nodes[prevId].nextId;\n\n // Descend the list until we reach the end or until we find a valid insert position\n while (prevId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) {\n prevId = self.nodes[prevId].nextId;\n nextId = self.nodes[prevId].nextId;\n }\n\n return (prevId, nextId);\n }\n\n /*\n * @dev Ascend the list (smaller keys to larger keys) to find a valid insert position\n * @param _key Node's key\n * @param _startId Id of node to start descending the list from\n */\n function ascendList(Data storage self, uint256 _key, address _startId) internal view returns (address, address) {\n // If `_startId` is the tail, check if the insert position is after the tail\n if (self.tail == _startId && _key <= self.nodes[_startId].key) {\n return (_startId, address(0));\n }\n\n address nextId = _startId;\n address prevId = self.nodes[nextId].prevId;\n\n // Ascend the list until we reach the end or until we find a valid insertion point\n while (nextId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) {\n nextId = self.nodes[nextId].prevId;\n prevId = self.nodes[nextId].prevId;\n }\n\n return (prevId, nextId);\n }\n\n /*\n * @dev Find the insert position for a new node with the given key\n * @param _key Node's key\n * @param _prevId Id of previous node for the insert position\n * @param _nextId Id of next node for the insert position\n */\n function findInsertPosition(Data storage self, uint256 _key, address _prevId, address _nextId) internal view returns (address, address) {\n address prevId = _prevId;\n address nextId = _nextId;\n\n if (prevId != address(0)) {\n if (!contains(self, prevId) || _key > self.nodes[prevId].key) {\n // `prevId` does not exist anymore or now has a smaller key than the given key\n prevId = address(0);\n }\n }\n\n if (nextId != address(0)) {\n if (!contains(self, nextId) || _key < self.nodes[nextId].key) {\n // `nextId` does not exist anymore or now has a larger key than the given key\n nextId = address(0);\n }\n }\n\n if (prevId == address(0) && nextId == address(0)) {\n // No hint - descend list starting from head\n return descendList(self, _key, self.head);\n } else if (prevId == address(0)) {\n // No `prevId` for hint - ascend list starting from `nextId`\n return ascendList(self, _key, nextId);\n } else if (nextId == address(0)) {\n // No `nextId` for hint - descend list starting from `prevId`\n return descendList(self, _key, prevId);\n } else {\n // Descend list starting from `prevId`\n return descendList(self, _key, prevId);\n }\n }\n}", "sourcePath": "/Users/yondonfu/Development/livepeer/sorted-doubly-ll/packages/sorted-doubly-ll/contracts/SortedDoublyLL.sol", "ast": { "absolutePath": "/Users/yondonfu/Development/livepeer/sorted-doubly-ll/packages/sorted-doubly-ll/contracts/SortedDoublyLL.sol", "exportedSymbols": { "SortedDoublyLL": [ 1207 ] }, "id": 1208, "nodeType": "SourceUnit", "nodes": [ { "id": 224, "literals": [ "solidity", "0.5", ".0" ], "nodeType": "PragmaDirective", "src": "0:22:1" }, { "absolutePath": "openzeppelin-solidity/contracts/math/SafeMath.sol", "file": "openzeppelin-solidity/contracts/math/SafeMath.sol", "id": 225, "nodeType": "ImportDirective", "scope": 1208, "sourceUnit": 1336, "src": "24:59:1", "symbolAliases": [], "unitAlias": "" }, { "baseContracts": [], "contractDependencies": [], "contractKind": "library", "documentation": null, "fullyImplemented": true, "id": 1207, "linearizedBaseContracts": [ 1207 ], "name": "SortedDoublyLL", "nodeType": "ContractDefinition", "nodes": [ { "id": 228, "libraryName": { "contractScope": null, "id": 226, "name": "SafeMath", "nodeType": "UserDefinedTypeName", "referencedDeclaration": 1335, "src": "1286:8:1", "typeDescriptions": { "typeIdentifier": "t_contract$_SafeMath_$1335", "typeString": "library SafeMath" } }, "nodeType": "UsingForDirective", "src": "1280:27:1", "typeName": { "id": 227, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "1299:7:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } } }, { "canonicalName": "SortedDoublyLL.Node", "id": 235, "members": [ { "constant": false, "id": 230, "name": "key", "nodeType": "VariableDeclaration", "scope": 235, "src": "1377:11:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 229, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "1377:7:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 232, "name": "nextId", "nodeType": "VariableDeclaration", "scope": 235, "src": "1449:14:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, "typeName": { "id": 231, "name": "address", "nodeType": "ElementaryTypeName", "src": "1449:7:1", "stateMutability": "nonpayable", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 234, "name": "prevId", "nodeType": "VariableDeclaration", "scope": 235, "src": "1535:14:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, "typeName": { "id": 233, "name": "address", "nodeType": "ElementaryTypeName", "src": "1535:7:1", "stateMutability": "nonpayable", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "value": null, "visibility": "internal" } ], "name": "Node", "nodeType": "StructDefinition", "scope": 1207, "src": "1355:266:1", "visibility": "public" }, { "canonicalName": "SortedDoublyLL.Data", "id": 248, "members": [ { "constant": false, "id": 237, "name": "head", "nodeType": "VariableDeclaration", "scope": 248, "src": "1681:12:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, "typeName": { "id": 236, "name": "address", "nodeType": "ElementaryTypeName", "src": "1681:7:1", "stateMutability": "nonpayable", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 239, "name": "tail", "nodeType": "VariableDeclaration", "scope": 248, "src": "1794:12:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" }, "typeName": { "id": 238, "name": "address", "nodeType": "ElementaryTypeName", "src": "1794:7:1", "stateMutability": "nonpayable", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 241, "name": "maxSize", "nodeType": "VariableDeclaration", "scope": 248, "src": "1908:15:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 240, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "1908:7:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 243, "name": "size", "nodeType": "VariableDeclaration", "scope": 248, "src": "1981:12:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 242, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "1981:7:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 247, "name": "nodes", "nodeType": "VariableDeclaration", "scope": 248, "src": "2054:31:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_struct$_Node_$235_storage_$", "typeString": "mapping(address => struct SortedDoublyLL.Node)" }, "typeName": { "id": 246, "keyType": { "id": 244, "name": "address", "nodeType": "ElementaryTypeName", "src": "2063:7:1", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } }, "nodeType": "Mapping", "src": "2054:25:1", "typeDescriptions": { "typeIdentifier": "t_mapping$_t_address_$_t_struct$_Node_$235_storage_$", "typeString": "mapping(address => struct SortedDoublyLL.Node)" }, "valueType": { "contractScope": null, "id": 245, "name": "Node", "nodeType": "UserDefinedTypeName", "referencedDeclaration": 235, "src": "2074:4:1", "typeDescriptions": { "typeIdentifier": "t_struct$_Node_$235_storage_ptr", "typeString": "struct SortedDoublyLL.Node" } } }, "value": null, "visibility": "internal" } ], "name": "Data", "nodeType": "StructDefinition", "scope": 1207, "src": "1659:494:1", "visibility": "public" }, { "body": { "id": 269, "nodeType": "Block", "src": "2315:219:1", "statements": [ { "expression": { "argumentTypes": null, "arguments": [ { "argumentTypes": null, "commonType": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "id": 259, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftExpression": { "argumentTypes": null, "id": 256, "name": "_size", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 252, "src": "2404:5:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "BinaryOperation", "operator": ">", "rightExpression": { "argumentTypes": null, "expression": { "argumentTypes": null, "id": 257, "name": "self", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 250, "src": "2412:4:1", "typeDescriptions": { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data storage pointer" } }, "id": 258, "isConstant": false, "isLValue": true, "isPure": false, "lValueRequested": false, "memberName": "maxSize", "nodeType": "MemberAccess", "referencedDeclaration": 241, "src": "2412:12:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "src": "2404:20:1", "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, { "argumentTypes": null, "hexValue": "6e6577206d61782073697a65206d7573742062652067726561746572207468616e206f6c64206d61782073697a65", "id": 260, "isConstant": false, "isLValue": false, "isPure": true, "kind": "string", "lValueRequested": false, "nodeType": "Literal", "src": "2438:48:1", "subdenomination": null, "typeDescriptions": { "typeIdentifier": "t_stringliteral_30180cb1a055b4f426da570ff72eaa2227ac83f4e78a0723078bb5e5c76e86a9", "typeString": "literal_string \"new max size must be greater than old max size\"" }, "value": "new max size must be greater than old max size" } ], "expression": { "argumentTypes": [ { "typeIdentifier": "t_bool", "typeString": "bool" }, { "typeIdentifier": "t_stringliteral_30180cb1a055b4f426da570ff72eaa2227ac83f4e78a0723078bb5e5c76e86a9", "typeString": "literal_string \"new max size must be greater than old max size\"" } ], "id": 255, "name": "require", "nodeType": "Identifier", "overloadedDeclarations": [ 1409, 1410 ], "referencedDeclaration": 1410, "src": "2383:7:1", "typeDescriptions": { "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", "typeString": "function (bool,string memory) pure" } }, "id": 261, "isConstant": false, "isLValue": false, "isPure": false, "kind": "functionCall", "lValueRequested": false, "names": [], "nodeType": "FunctionCall", "src": "2383:113:1", "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } }, "id": 262, "nodeType": "ExpressionStatement", "src": "2383:113:1" }, { "expression": { "argumentTypes": null, "id": 267, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "leftHandSide": { "argumentTypes": null, "expression": { "argumentTypes": null, "id": 263, "name": "self", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 250, "src": "2507:4:1", "typeDescriptions": { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data storage pointer" } }, "id": 265, "isConstant": false, "isLValue": true, "isPure": false, "lValueRequested": true, "memberName": "maxSize", "nodeType": "MemberAccess", "referencedDeclaration": 241, "src": "2507:12:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "nodeType": "Assignment", "operator": "=", "rightHandSide": { "argumentTypes": null, "id": 266, "name": "_size", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 252, "src": "2522:5:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "src": "2507:20:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "id": 268, "nodeType": "ExpressionStatement", "src": "2507:20:1" } ] }, "documentation": null, "id": 270, "implemented": true, "kind": "function", "modifiers": [], "name": "setMaxSize", "nodeType": "FunctionDefinition", "parameters": { "id": 253, "nodeType": "ParameterList", "parameters": [ { "constant": false, "id": 250, "name": "self", "nodeType": "VariableDeclaration", "scope": 270, "src": "2272:17:1", "stateVariable": false, "storageLocation": "storage", "typeDescriptions": { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data" }, "typeName": { "contractScope": null, "id": 249, "name": "Data", "nodeType": "UserDefinedTypeName", "referencedDeclaration": 248, "src": "2272:4:1", "typeDescriptions": { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data" } }, "value": null, "visibility": "internal" }, { "constant": false, "id": 252, "name": "_size", "nodeType": "VariableDeclaration", "scope": 270, "src": "2291:13:1", "stateVariable": false, "storageLocation": "default", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" }, "typeName": { "id": 251, "name": "uint256", "nodeType": "ElementaryTypeName", "src": "2291:7:1", "typeDescriptions": { "typeIdentifier": "t_uint256", "typeString": "uint256" } }, "value": null, "visibility": "internal" } ], "src": "2271:34:1" }, "returnParameters": { "id": 254, "nodeType": "ParameterList", "parameters": [], "src": "2315:0:1" }, "scope": 1207, "src": "2252:282:1", "stateMutability": "nonpayable", "superFunction": null, "visibility": "internal" }, { "body": { "id": 491, "nodeType": "Block", "src": "2881:1869:1", "statements": [ { "expression": { "argumentTypes": null, "arguments": [ { "argumentTypes": null, "id": 287, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "nodeType": "UnaryOperation", "operator": "!", "prefix": true, "src": "2945:13:1", "subExpression": { "argumentTypes": null, "arguments": [ { "argumentTypes": null, "id": 285, "name": "self", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 272, "src": "2953:4:1", "typeDescriptions": { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data storage pointer" } } ], "expression": { "argumentTypes": [ { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data storage pointer" } ], "id": 284, "name": "isFull", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 710, "src": "2946:6:1", "typeDescriptions": { "typeIdentifier": "t_function_internal_view$_t_struct$_Data_$248_storage_ptr_$returns$_t_bool_$", "typeString": "function (struct SortedDoublyLL.Data storage pointer) view returns (bool)" } }, "id": 286, "isConstant": false, "isLValue": false, "isPure": false, "kind": "functionCall", "lValueRequested": false, "names": [], "nodeType": "FunctionCall", "src": "2946:12:1", "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, { "argumentTypes": null, "hexValue": "63616e6e6f7420696e7365727420696e746f20612066756c6c206c697374", "id": 288, "isConstant": false, "isLValue": false, "isPure": true, "kind": "string", "lValueRequested": false, "nodeType": "Literal", "src": "2972:32:1", "subdenomination": null, "typeDescriptions": { "typeIdentifier": "t_stringliteral_c717684577a451051cd65ab3f9ba5a50cc9ef38655a6cc00364245ec33eaec6e", "typeString": "literal_string \"cannot insert into a full list\"" }, "value": "cannot insert into a full list" } ], "expression": { "argumentTypes": [ { "typeIdentifier": "t_bool", "typeString": "bool" }, { "typeIdentifier": "t_stringliteral_c717684577a451051cd65ab3f9ba5a50cc9ef38655a6cc00364245ec33eaec6e", "typeString": "literal_string \"cannot insert into a full list\"" } ], "id": 283, "name": "require", "nodeType": "Identifier", "overloadedDeclarations": [ 1409, 1410 ], "referencedDeclaration": 1410, "src": "2924:7:1", "typeDescriptions": { "typeIdentifier": "t_function_require_pure$_t_bool_$_t_string_memory_ptr_$returns$__$", "typeString": "function (bool,string memory) pure" } }, "id": 289, "isConstant": false, "isLValue": false, "isPure": false, "kind": "functionCall", "lValueRequested": false, "names": [], "nodeType": "FunctionCall", "src": "2924:90:1", "typeDescriptions": { "typeIdentifier": "t_tuple$__$", "typeString": "tuple()" } }, "id": 290, "nodeType": "ExpressionStatement", "src": "2924:90:1" }, { "expression": { "argumentTypes": null, "arguments": [ { "argumentTypes": null, "id": 296, "isConstant": false, "isLValue": false, "isPure": false, "lValueRequested": false, "nodeType": "UnaryOperation", "operator": "!", "prefix": true, "src": "3091:20:1", "subExpression": { "argumentTypes": null, "arguments": [ { "argumentTypes": null, "id": 293, "name": "self", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 272, "src": "3101:4:1", "typeDescriptions": { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data storage pointer" } }, { "argumentTypes": null, "id": 294, "name": "_id", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 274, "src": "3107:3:1", "typeDescriptions": { "typeIdentifier": "t_address", "typeString": "address" } } ], "expression": { "argumentTypes": [ { "typeIdentifier": "t_struct$_Data_$248_storage_ptr", "typeString": "struct SortedDoublyLL.Data storage pointer" }, { "typeIdentifier": "t_address", "typeString": "address" } ], "id": 292, "name": "contains", "nodeType": "Identifier", "overloadedDeclarations": [], "referencedDeclaration": 696, "src": "3092:8:1", "typeDescriptions": { "typeIdentifier": "t_function_internal_view$_t_struct$_Data_$248_storage_ptr_$_t_address_$returns$_t_bool_$", "typeString": "function (struct SortedDoublyLL.Data storage pointer,address) view returns (bool)" } }, "id": 295, "isConstant": false, "isLValue": false, "isPure": false, "kind": "functionCall", "lValueRequested": false, "names": [], "nodeType": "FunctionCall", "src": "3092:19:1", "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, "typeDescriptions": { "typeIdentifier": "t_bool", "typeString": "bool" } }, { "argumentTypes": null, "hexValue": "63616e6e6f7420696e73657274206e6f6465207468617420616c726561647920657869737473", "id": 297, "isConstant": false, "isLValue": false, "isPure": true, "kind": "string", "lValueRequested": false, "nodeType": "Literal", "src": "3125:40:1", "subdenomination": null, "typeDescriptions": { "typeIdentifier": "t_stringliteral_ffcfe52afc7805b93498508456cf152482630a9e40c85ebae9fa3fdf5dc6849f", "typeString": "literal_string \"cannot insert node that already exists\"" }, "value": "cannot insert node that already exists" } ], "expression": { "argumentTypes": [ { "typeIdentifier": "t_bool", "typeString": "bool" }, { "typeIdentifier": "t_stringliteral_ffcfe52afc7805b93498508456cf152482630a9e40c85ebae9fa3fdf5dc6849f", "typeString": "literal_string \"cannot insert node that already exists\"" } ], "id": 291,