├── .gitattributes ├── README.md ├── contracts ├── HitchensOrderStatisticsTree.sol ├── HitchensOrderStatisticsTreeLib.sol ├── Migrations.sol ├── Owned.sol └── artifacts │ ├── HitchensOrderStatisticsTree.json │ ├── HitchensOrderStatisticsTreeLib.json │ ├── HitchensOrderStatisticsTreeLib_metadata.json │ └── HitchensOrderStatisticsTree_metadata.json ├── migrations ├── 1_initial_migration.js └── 2_deployContracts.js ├── test ├── .gitkeep ├── Results.md ├── count.js ├── ost.js ├── steps_1.json ├── steps_2.json └── steps_3.json └── truffle-config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Hitchens Order Statistics Tree 2 | 3 | [https://github.com/rob-Hitchens/OrderStatisticsTree](https://github.com/rob-Hitchens/OrderStatisticsTree) 4 | 5 | Solidity Library that implements a self-balancing binary search tree (BST) with [Order Statistics Tree](https://en.wikipedia.org/wiki/Order_statistic_tree) extensions. The Library implements [Bokky Poobah's Red Black Tree](https://github.com/bokkypoobah/BokkyPooBahsRedBlackTreeLibrary) with additional properties. 6 | 7 | Adds order statistics to each node and the tree itself: 8 | 9 | - report a value position in sorted list. 10 | - report the count of values above and below a certain value. 11 | - report percentile, median, rank, etc. 12 | - find the value with a given percentile rank. 13 | 14 | Provides a method of ensuring such statistics can be gathered and the structure maintained at a fixed maximum cost at any scale: `O(1)` 15 | 16 | ### Red Black Tree Organization 17 | 18 | A BST maintains an ordered list. A BST aims for O(log n) performance for insertions and removals but only if the tree remains balanced. Balancing is accomplished through local reorganizations (rotations). 19 | 20 | [Ideally balanced trees](https://en.wikipedia.org/wiki/AVL_tree) optimize read operations by ensuring optimal balance as sorted data is inserted and removed. This method invests considerable energy (meaning gas) keeping the list perfectly balanced. 21 | 22 | Ethereum's `mapping` largely negates the need for crawling a tree to find a particular node. This implementation completes most read operations, including reporting statistics, in one operation. On the other hand, write operations in Ethereum are exceptionally expensive relative to reads. Therefore, we should prioritize update efficiency over read efficiency. This is roughly the opposite of most database systems that are optimized for read-back efficiency. 23 | 24 | A [Red Black Tree](https://en.wikipedia.org/wiki/Red%E2%80%93black_tree) optimizes the cost of insertion and removal by tolerating limited imbalance. Tolerating limited imbalance reduces the frequency and extent of tree reorganizations which reduces update cost. 25 | 26 | This implementation relies on the iterative approach to functions that seem recursive in nature, to avoid problems with stack depth. 27 | 28 | ### Inserts and Deletes Take a Key and a Value 29 | 30 | - `value`: The value to sort, such as price, amount, rating, etc.. These are unsigned integers. `0` is prohibited. 31 | - `key`: (Optional). A unique identifier for the entry. This should be meaningful at the application layer, such as ticketID, transactionID or UserID. These are `bytes32`. If there is no reason to point back to application-level records, it's safe to use `0x0` for all entries, provided there are no duplicate key/value pairs. 32 | 33 | Client's can store any of the scaler types in `key` after converting to the native `bytes32` type. The same principle applies to `value`. Note that value `0` is reserved for performance reasons. In the case that `0` has meaning within the application, apply an offset to ensure a `0` is never submitted for sorting. 34 | 35 | Since multiple users or transactions could have the same `value`, this is permitted. Consider a case of "students" with "test scores" to sort. User addresses would be re-cast as `bytes32` and the scores offset by `1` unless a score of `0` is not possible. Conversion and offset are client-side responsibilities. 36 | 37 | - (Alice) key: `0x123...`, (score) value: `80` 38 | - (Bob) key: `0x456...`, (score) value: `80` 39 | 40 | These two entries will both be organized on the node representing `value: 80`. The node contains a dynamic array of all unique `key` that "live" in node `80`. The interface provides read-access to the key count and the keys stored there. 41 | 42 | Roughly: 43 | ``` 44 | Node: 80 45 | _key: ['0x123...','0x456...'] 46 | ``` 47 | 48 | Delete activities require the `value` and the `key`. This means the tree always contains an ordered list of the sorted values, and the unique identifiers of application-level details related to them. The `key` list for entries with *identical* `value` is in *no particular order* for performance reasons. 49 | 50 | **WARN:** The tree enforces uniqueness for key/value pairs but it does not enforce uniqueness for keys alone throughout the tree. If such a duplication is non-sensical (e.g. any given transaction ID can only have one price), then this uniqueness check should be enforced at the application level. 51 | 52 | ### Functions 53 | 54 | - `insert(bytes32 key, uint value)`: Inserts a sorted value and related key. The pair must not exist. Reverts if it does. If the sorted value already exists in the tree, then the key is appended to the list of keys in an existing node. 55 | - `remove(bytes32 key, uint value)`: Removes a sorted value and related key. The pair must exist. Reverts if it doesn't. If multiple keys exist for the given sorted value, then the key is removed from the list of keys for the given value. If it is the last key for the given value, then the node is removed from the tree. 56 | 57 | Insertions and deletions always: 58 | - recurse toward the tree root to update the counters. 59 | 60 | and may: 61 | - trigger rebalancing if a node is added or removed. If rebalancing is necessary it follows the Red Black Tree algorithm. 62 | 63 | #### View functions: 64 | 65 | - `valueExists(uint value)`: bool. True if at least one key has the inputed sort value. 66 | - `keyValueExists(bytes32 key, uint value)`: bool. True if the key is a member of the set of keys with the given sort value. - 67 | - `count()`: uint. The number of unique key/value pairs in the system. 68 | - `first()`: uint. The lowest sorted value. 69 | - `last()`: uint. The highest sorted value. 70 | - `median()`: uint. The median sorted value. 71 | - `prev(uint value)`: uint. Sort value before the inputed sort value. `0` if no such record exists. 72 | - `next(uint value)`: uint. Sort value after the inputed sort value. `0` if no such record exists. 73 | - `above(uint value)`: uint. Count of entries above the inputed sort value. Equal entries are included. 74 | - `below(uint value)`: uint. Count of entries below the inputed sort value. Equal entries are excluded. 75 | - `percentile(uint value)`: uint. Percentile rank of the inputed sort value. All key entries at the given sorted value are considered equivalent and have the same percentile rank. Returns the nearest hit (where if would be) if no such value exists in the tree. 76 | - `permil(uint value)`: uint. Like percentile, with an extra digit of precision. 77 | - `atPercentile(uint _percentile):`: uint. Returns the sorted value at a percentile rank. The returned sorted value applies equally all key entries collated in the node in no particular order. Returns the nearest sorted value if no sorted value precisely matches the requested percentile. 78 | - `atPermil(uint _permil)`: uint. Like atPercentile, with an extra digit of precision. 79 | - `getNode(uint value)`: Returns the tree node details enumerated below. 80 | 81 | #### getNode 82 | 83 | `getNode(uint value)`: Returns tree data for one node. There must be at least one key/value pair with this value for the node to exist in the tree. Reverts if the node doesn't exist. 84 | 85 | ``` 86 | Node { 87 | parent: uint, 88 | left: uint, 89 | right: uint, 90 | red: bool, 91 | keyCount: uint, 92 | count: uint 93 | } 94 | ``` 95 | 96 | For applications, the only values that would be generally useful to an application are: 97 | 98 | - `keyCount `: This is the number of key entries with the same sorted value. For example, identical test scores from multiple students. This informs a client that wishes to iterate the key list of a given value using: 99 | 100 | - `valueKeyAtIndex(uint value, row)`: bytes32. The key associated with the sort value at a given row. 101 | 102 | The remaining values in the `getNode` response expose the internal structure of the tree. This is expected to be useful only for study of the internal structure or constructing other methods of tree exploration. 103 | 104 | `parent`, `left` and `right` describe tree organization. `count` (do not confuse with `keyCount`) is the sum of `keyCount` for all nodes in the subtree of this node, inclusive. This is not expected to be useful for an application. 105 | 106 | #### root() 107 | 108 | - `root()`: This is the root of the Order Statistics Tree. It is not expected to be useful at an application level. It is the only node with no parent. 109 | 110 | #### Owner() and changeOwner() 111 | 112 | Simple access control for write operations in the example contract. 113 | 114 | ### Reorganization 115 | 116 | The root node and node left, right, parent values are subject to change with each insertion or removal transaction. The tree uses the Red Black Tree algorithm to maintain acceptable tree balance. 117 | 118 | ### Finite Tree Growth 119 | 120 | While it is not a strict requirement, it is recommended to devise a strategy to ensure a finite number of nodes. This would usually imply limiting precision in the sorted values, limiting the age of the entries or a purpose-built strategy that reliably limits the number of unique sorted values that can exist. In other words, you should be able to show that the maximum number of nodes *possible* will never exceed an acceptable limit. 121 | 122 | For example, consider a data set of integers with a possible range of `51-100`. The tree size will be limited to 50 nodes. The nodes will accept unlimited records and it will be possible to estimate a worst-case insertion/deletion cost *at any scale* for a tree with worst-case imbalance at a fixed maximum size. 123 | 124 | As a reminder, all entries collated in a particular node are organized *in no particular order*. That is, there would be no ordering assurance for all records stored in the same node, e.g. `53`. *This property makes the maximum insertion/deletion cost manageable*. 125 | 126 | If higher statistical resolution is required, then the same data set could be scaled as set of values in the range of `501-1000`. In effect, `50.1-100.0`. In this case the ordering and statistical analysis will yield an extra decimal of precision. Doing so will result in a maximum possible tree size of 500 nodes and a corresponding increase in the maximum gas cost for insertion and removal operations owing to increased tree depth. 127 | 128 | Other tree growth limiting strategies are possible. For example, a reputation system might expire votes on a FIFO basis, simply discarding the oldest vote when the tree size exceeds a set limit. The growth-limiting strategy is an application-level concern. 129 | 130 | Bokky has informally tested the basic tree up to 10,000 nodes. Do NOT expect the same performance here. This implementation adds additional data (`count`) and recursive logic (implemented as iterative processes) that maintain them, so a gas cost increase is unavoidable. *The gas cost for these processes scales with tree depth.* 131 | 132 | ## Code Example 133 | 134 | The example Solidity file contains an example contract that uses the library. This exposes the Library functions for a single Tree (`...Tree`). 135 | 136 | ## Experimental Reverse Ranking 137 | 138 | The sample contract includes experimental functions that reverse some order information and suggest how other ranking information could be reversed. 139 | 140 | ``` 141 | function valueAtRankReverse(uint _rank) public view returns(uint _value) { 142 | _value = tree.atRank(tree.count() - (_rank - 1)); 143 | } 144 | function valueRankReverse(uint value) public view returns(uint _rank) { 145 | _rank = tree.count() - (tree.rank(value) - 1); 146 | } 147 | ``` 148 | 149 | ## Test 150 | 151 | Two Truffle tests insert and delete from the tree and enumerate sorted elements and the tress structure. 152 | 153 | ## Getting Started 154 | 155 | If you have trouble getting started, use the singular implementation and: 156 | 157 | - `insert: ("0xaa",1)` 158 | - `insert: ("0xab",2)` 159 | 160 | Then explore the stats. 161 | 162 | You cannot: 163 | 164 | - `insert: ("0xab",2)` again, because that entry already exists. 165 | 166 | You can: 167 | 168 | `remove: ("0xaa",1)` because it does exist. 169 | 170 | If you do that, you will see that `2` has become the `root()` (was `1`) because of automatic tree reorganization. To further experiment with rebalancing, insert values in ascending order. This is the worst-case scenario for a self-balancing binary tree and it will force extensive rebalancing. 171 | 172 | ``` 173 | contract HitchensOrderStatisticsTree is Owned { 174 | using HitchensOrderStatisticsTreeLibrary for HitchensOrderStatisticsTreeLibrary.Tree; 175 | 176 | HitchensOrderStatisticsTreeLibrary.Tree tree; 177 | 178 | event Log(string action, bytes32 key, uint value); 179 | 180 | constructor() public { 181 | } 182 | function treeRootNode() public view returns (uint _value) { 183 | _value = tree.root; 184 | } 185 | function firstValue() public view returns (uint _value) { 186 | _value = tree.first(); 187 | } 188 | function lastValue() public view returns (uint _value) { 189 | _value = tree.last(); 190 | } 191 | function nextValue(uint value) public view returns (uint _value) { 192 | _value = tree.next(value); 193 | } 194 | function prevValue(uint value) public view returns (uint _value) { 195 | _value = tree.prev(value); 196 | } 197 | function valueExists(uint value) public view returns (bool _exists) { 198 | _exists = tree.exists(value); 199 | } 200 | function keyValueExists(bytes32 key, uint value) public view returns(bool _exists) { 201 | _exists = tree.keyExists(key, value); 202 | } 203 | function getNode(uint value) public view returns (uint _parent, uint _left, uint _right, bool _red, uint _keyCount, uint _count) { 204 | (_parent, _left, _right, _red, _keyCount, _count) = tree.getNode(value); 205 | } 206 | function getValueKey(uint value, uint row) public view returns(bytes32 _key) { 207 | _key = tree.valueKeyAtIndex(value,row); 208 | } 209 | function valueKeyCount() public view returns(uint _count) { 210 | _count = tree.count(); 211 | } 212 | function valuePercentile(uint value) public view returns(uint _percentile) { 213 | _percentile = tree.percentile(value); 214 | } 215 | function valuePermil(uint value) public view returns(uint _permil) { 216 | _permil = tree.permil(value); 217 | } 218 | function valueAtPercentile(uint _percentile) public view returns(uint _value) { 219 | _value = tree.atPercentile(_percentile); 220 | } 221 | function valueAtPermil(uint value) public view returns(uint _value) { 222 | _value = tree.atPermil(value); 223 | } 224 | function medianValue() public view returns(uint _value) { 225 | return tree.median(); 226 | } 227 | function valueRank(uint value) public view returns(uint _rank) { 228 | _rank = tree.rank(value); 229 | } 230 | function valuesBelow(uint value) public view returns(uint _below) { 231 | _below = tree.below(value); 232 | } 233 | function valuesAbove(uint value) public view returns(uint _above) { 234 | _above = tree.above(value); 235 | } 236 | function valueAtRank(uint _rank) public view returns(uint _value) { 237 | _value = tree.atRank(_rank); 238 | } 239 | function insertKeyValue(bytes32 key, uint value) public onlyOwner { 240 | emit Log("insert", key, value); 241 | tree.insert(key, value); 242 | } 243 | function removeKeyValue(bytes32 key, uint value) public onlyOwner { 244 | emit Log("delete", key, value); 245 | tree.remove(key, value); 246 | } 247 | } 248 | ``` 249 | 250 | ## Motivation 251 | 252 | Although I'm a strong believer that the sorting concern can (and should) nearly almost always be externalized from Solidity contracts, this is a generalized approach for those cases when it must be done. The focus is on gas cost optimization. In particular, developer control of the desired statistical and sort-order resolution so that ordered lists of arbitrary size don't necessarily carry unnecessary and unacceptable cost. It allows for the idea of "good enough" sorting, "good enough" tree balance and "close enough" statistics that are suitable for many cases where contract logic depends on a sorted list and *there is expected to be a large number of entries*. 253 | 254 | "Good enough" sorting means able to find the *median* (or percentile, etc.) value and all instances that share a value, with known precision. Since the Order Tree holds the keys for the sorted entries, applications would normally consult authoratative records (without rounding) to find the exact values if any rounding was performed before inserting into the tree. 255 | 256 | This system gives developers fine-grained control over precision and performance/gas cost. 257 | 258 | ## Tests 259 | 260 | NO TESTING OF ANY KIND HAS BEEN PERFORMED AND YOU USE THIS LIBRARY AT YOUR OWN EXCLUSIVE RISK. 261 | 262 | ## Contributors 263 | 264 | Optimization and clean-up is ongoing. 265 | 266 | The author welcomes pull requests, feature requests, testing assistance and feedback. Contact the author if you would like assistance with customization or calibrating the code for a specific application or gathering of different statistics. 267 | 268 | ## License 269 | 270 | Copyright (c), 2019, Rob Hitchens. The MIT License 271 | 272 | Permission is hereby granted, free of charge, to any person obtaining a copy 273 | of this software and associated documentation files (the "Software"), to deal 274 | in the Software without restriction, including without limitation the rights 275 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 276 | copies of the Software, and to permit persons to whom the Software is 277 | furnished to do so, subject to the following conditions: 278 | 279 | The above copyright notice and this permission notice shall be included in all 280 | copies or substantial portions of the Software. 281 | 282 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 283 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 284 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 285 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 286 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 287 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 288 | SOFTWARE. 289 | 290 | Portions based on BokkyPooBahsRedBlackTreeLibrary, 291 | https://github.com/bokkypoobah/BokkyPooBahsRedBlackTreeLibrary 292 | 293 | Hope it helps. 294 | -------------------------------------------------------------------------------- /contracts/HitchensOrderStatisticsTree.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.1; 2 | 3 | /* 4 | Hitchens Order Statistics Tree v0.99 5 | 6 | A Solidity Red-Black Tree library to store and maintain a sorted data 7 | structure in a Red-Black binary search tree, with O(log 2n) insert, remove 8 | and search time (and gas, approximately) 9 | 10 | https://github.com/rob-Hitchens/OrderStatisticsTree 11 | 12 | Copyright (c) Rob Hitchens. the MIT License 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | Significant portions from BokkyPooBahsRedBlackTreeLibrary, 33 | https://github.com/bokkypoobah/BokkyPooBahsRedBlackTreeLibrary 34 | 35 | THIS SOFTWARE IS NOT TESTED OR AUDITED. DO NOT USE FOR PRODUCTION. 36 | */ 37 | 38 | import "./Owned.sol"; 39 | import "./HitchensOrderStatisticsTreeLib.sol"; 40 | 41 | 42 | /* 43 | Hitchens Order Statistics Tree v0.99 44 | 45 | A Solidity Red-Black Tree library to store and maintain a sorted data 46 | structure in a Red-Black binary search tree, with O(log 2n) insert, remove 47 | and search time (and gas, approximately) 48 | 49 | https://github.com/rob-Hitchens/OrderStatisticsTree 50 | 51 | Copyright (c) Rob Hitchens. the MIT License 52 | 53 | Permission is hereby granted, free of charge, to any person obtaining a copy 54 | of this software and associated documentation files (the "Software"), to deal 55 | in the Software without restriction, including without limitation the rights 56 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 57 | copies of the Software, and to permit persons to whom the Software is 58 | furnished to do so, subject to the following conditions: 59 | 60 | The above copyright notice and this permission notice shall be included in all 61 | copies or substantial portions of the Software. 62 | 63 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 64 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 65 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 66 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 67 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 68 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 69 | SOFTWARE. 70 | 71 | Portions from BokkyPooBahsRedBlackTreeLibrary, 72 | https://github.com/bokkypoobah/BokkyPooBahsRedBlackTreeLibrary 73 | 74 | THIS SOFTWARE IS NOT TESTED OR AUDITED. DO NOT USE FOR PRODUCTION. 75 | */ 76 | 77 | contract HitchensOrderStatisticsTree is Owned { 78 | using HitchensOrderStatisticsTreeLib for HitchensOrderStatisticsTreeLib.Tree; 79 | 80 | HitchensOrderStatisticsTreeLib.Tree tree; 81 | 82 | event Log(string action, bytes32 key, uint value); 83 | 84 | constructor() public { 85 | } 86 | function treeRootNode() public view returns (uint _value) { 87 | _value = tree.root; 88 | } 89 | function firstValue() public view returns (uint _value) { 90 | _value = tree.first(); 91 | } 92 | function lastValue() public view returns (uint _value) { 93 | _value = tree.last(); 94 | } 95 | function nextValue(uint value) public view returns (uint _value) { 96 | _value = tree.next(value); 97 | } 98 | function prevValue(uint value) public view returns (uint _value) { 99 | _value = tree.prev(value); 100 | } 101 | function valueExists(uint value) public view returns (bool _exists) { 102 | _exists = tree.exists(value); 103 | } 104 | function keyValueExists(bytes32 key, uint value) public view returns(bool _exists) { 105 | _exists = tree.keyExists(key, value); 106 | } 107 | function getNode(uint value) public view returns (uint _parent, uint _left, uint _right, bool _red, uint _keyCount, uint _count) { 108 | (_parent, _left, _right, _red, _keyCount, _count) = tree.getNode(value); 109 | } 110 | function getValueKey(uint value, uint row) public view returns(bytes32 _key) { 111 | _key = tree.valueKeyAtIndex(value,row); 112 | } 113 | function valueKeyCount() public view returns(uint _count) { 114 | _count = tree.count(); 115 | } 116 | function valuePercentile(uint value) public view returns(uint _percentile) { 117 | _percentile = tree.percentile(value); 118 | } 119 | function valuePermil(uint value) public view returns(uint _permil) { 120 | _permil = tree.permil(value); 121 | } 122 | function valueAtPercentile(uint _percentile) public view returns(uint _value) { 123 | _value = tree.atPercentile(_percentile); 124 | } 125 | function valueAtPermil(uint value) public view returns(uint _value) { 126 | _value = tree.atPermil(value); 127 | } 128 | function medianValue() public view returns(uint _value) { 129 | return tree.median(); 130 | } 131 | function valueRank(uint value) public view returns(uint _rank) { 132 | _rank = tree.rank(value); 133 | } 134 | function valuesBelow(uint value) public view returns(uint _below) { 135 | _below = tree.below(value); 136 | } 137 | function valuesAbove(uint value) public view returns(uint _above) { 138 | _above = tree.above(value); 139 | } 140 | function valueAtRank(uint _rank) public view returns(uint _value) { 141 | _value = tree.atRank(_rank); 142 | } 143 | function valueAtRankReverse(uint _rank) public view returns(uint _value) { 144 | _value = tree.atRank(tree.count() - (_rank - 1)); 145 | } 146 | function valueRankReverse(uint value) public view returns(uint _rank) { 147 | _rank = tree.count() - (tree.rank(value) - 1); 148 | } 149 | function insertKeyValue(bytes32 key, uint value) public onlyOwner { 150 | emit Log("insert", key, value); 151 | tree.insert(key, value); 152 | } 153 | function removeKeyValue(bytes32 key, uint value) public onlyOwner { 154 | emit Log("delete", key, value); 155 | tree.remove(key, value); 156 | } 157 | } 158 | 159 | -------------------------------------------------------------------------------- /contracts/HitchensOrderStatisticsTreeLib.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.1; 2 | 3 | /* 4 | Hitchens Order Statistics Tree v0.99 5 | 6 | A Solidity Red-Black Tree library to store and maintain a sorted data 7 | structure in a Red-Black binary search tree, with O(log 2n) insert, remove 8 | and search time (and gas, approximately) 9 | 10 | https://github.com/rob-Hitchens/OrderStatisticsTree 11 | 12 | Copyright (c) Rob Hitchens. the MIT License 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | Significant portions from BokkyPooBahsRedBlackTreeLibrary, 33 | https://github.com/bokkypoobah/BokkyPooBahsRedBlackTreeLibrary 34 | 35 | THIS SOFTWARE IS NOT TESTED OR AUDITED. DO NOT USE FOR PRODUCTION. 36 | */ 37 | 38 | import "./Owned.sol"; 39 | 40 | library HitchensOrderStatisticsTreeLib { 41 | uint private constant EMPTY = 0; 42 | struct Node { 43 | uint parent; 44 | uint left; 45 | uint right; 46 | bool red; 47 | bytes32[] keys; 48 | mapping(bytes32 => uint) keyMap; 49 | uint count; 50 | } 51 | struct Tree { 52 | uint root; 53 | mapping(uint => Node) nodes; 54 | } 55 | function first(Tree storage self) internal view returns (uint _value) { 56 | _value = self.root; 57 | if(_value == EMPTY) return 0; 58 | while (self.nodes[_value].left != EMPTY) { 59 | _value = self.nodes[_value].left; 60 | } 61 | } 62 | function last(Tree storage self) internal view returns (uint _value) { 63 | _value = self.root; 64 | if(_value == EMPTY) return 0; 65 | while (self.nodes[_value].right != EMPTY) { 66 | _value = self.nodes[_value].right; 67 | } 68 | } 69 | function next(Tree storage self, uint value) internal view returns (uint _cursor) { 70 | require(value != EMPTY, "OrderStatisticsTree(401) - Starting value cannot be zero"); 71 | if (self.nodes[value].right != EMPTY) { 72 | _cursor = treeMinimum(self, self.nodes[value].right); 73 | } else { 74 | _cursor = self.nodes[value].parent; 75 | while (_cursor != EMPTY && value == self.nodes[_cursor].right) { 76 | value = _cursor; 77 | _cursor = self.nodes[_cursor].parent; 78 | } 79 | } 80 | } 81 | function prev(Tree storage self, uint value) internal view returns (uint _cursor) { 82 | require(value != EMPTY, "OrderStatisticsTree(402) - Starting value cannot be zero"); 83 | if (self.nodes[value].left != EMPTY) { 84 | _cursor = treeMaximum(self, self.nodes[value].left); 85 | } else { 86 | _cursor = self.nodes[value].parent; 87 | while (_cursor != EMPTY && value == self.nodes[_cursor].left) { 88 | value = _cursor; 89 | _cursor = self.nodes[_cursor].parent; 90 | } 91 | } 92 | } 93 | function exists(Tree storage self, uint value) internal view returns (bool _exists) { 94 | if(value == EMPTY) return false; 95 | if(value == self.root) return true; 96 | if(self.nodes[value].parent != EMPTY) return true; 97 | return false; 98 | } 99 | function keyExists(Tree storage self, bytes32 key, uint value) internal view returns (bool _exists) { 100 | if(!exists(self, value)) return false; 101 | return self.nodes[value].keys[self.nodes[value].keyMap[key]] == key; 102 | } 103 | function getNode(Tree storage self, uint value) internal view returns (uint _parent, uint _left, uint _right, bool _red, uint keyCount, uint count) { 104 | require(exists(self,value), "OrderStatisticsTree(403) - Value does not exist."); 105 | Node storage gn = self.nodes[value]; 106 | return(gn.parent, gn.left, gn.right, gn.red, gn.keys.length, gn.keys.length+gn.count); 107 | } 108 | function getNodeCount(Tree storage self, uint value) internal view returns(uint count) { 109 | Node storage gn = self.nodes[value]; 110 | return gn.keys.length+gn.count; 111 | } 112 | function valueKeyAtIndex(Tree storage self, uint value, uint index) internal view returns(bytes32 _key) { 113 | require(exists(self,value), "OrderStatisticsTree(404) - Value does not exist."); 114 | return self.nodes[value].keys[index]; 115 | } 116 | function count(Tree storage self) internal view returns(uint _count) { 117 | return getNodeCount(self,self.root); 118 | } 119 | function percentile(Tree storage self, uint value) internal view returns(uint _percentile) { 120 | uint denominator = count(self); 121 | uint numerator = rank(self, value); 122 | _percentile = ((uint(1000) * numerator)/denominator+(uint(5)))/uint(10); 123 | } 124 | function permil(Tree storage self, uint value) internal view returns(uint _permil) { 125 | uint denominator = count(self); 126 | uint numerator = rank(self, value); 127 | _permil = ((uint(10000) * numerator)/denominator+(uint(5)))/uint(10); 128 | } 129 | function atPercentile(Tree storage self, uint _percentile) internal view returns(uint _value) { 130 | uint findRank = (((_percentile * count(self))/uint(10)) + uint(5)) / uint(10); 131 | return atRank(self,findRank); 132 | } 133 | function atPermil(Tree storage self, uint _permil) internal view returns(uint _value) { 134 | uint findRank = (((_permil * count(self))/uint(100)) + uint(5)) / uint(10); 135 | return atRank(self,findRank); 136 | } 137 | function median(Tree storage self) internal view returns(uint value) { 138 | return atPercentile(self,50); 139 | } 140 | function below(Tree storage self, uint value) public view returns(uint _below) { 141 | if(count(self) > 0 && value > 0) _below = rank(self,value)-uint(1); 142 | } 143 | function above(Tree storage self, uint value) public view returns(uint _above) { 144 | if(count(self) > 0) _above = count(self)-rank(self,value); 145 | } 146 | function rank(Tree storage self, uint value) internal view returns(uint _rank) { 147 | if(count(self) > 0) { 148 | bool finished; 149 | uint cursor = self.root; 150 | Node storage c = self.nodes[cursor]; 151 | uint smaller = getNodeCount(self,c.left); 152 | while (!finished) { 153 | uint keyCount = c.keys.length; 154 | if(cursor == value) { 155 | finished = true; 156 | } else { 157 | if(cursor < value) { 158 | cursor = c.right; 159 | c = self.nodes[cursor]; 160 | smaller += keyCount + getNodeCount(self,c.left); 161 | } else { 162 | cursor = c.left; 163 | c = self.nodes[cursor]; 164 | smaller -= (keyCount + getNodeCount(self,c.right)); 165 | } 166 | } 167 | if (!exists(self,cursor)) { 168 | finished = true; 169 | } 170 | } 171 | return smaller + 1; 172 | } 173 | } 174 | function atRank(Tree storage self, uint _rank) internal view returns(uint _value) { 175 | bool finished; 176 | uint cursor = self.root; 177 | Node storage c = self.nodes[cursor]; 178 | uint smaller = getNodeCount(self,c.left); 179 | while (!finished) { 180 | _value = cursor; 181 | c = self.nodes[cursor]; 182 | uint keyCount = c.keys.length; 183 | if(smaller + 1 >= _rank && smaller + keyCount <= _rank) { 184 | _value = cursor; 185 | finished = true; 186 | } else { 187 | if(smaller + keyCount <= _rank) { 188 | cursor = c.right; 189 | c = self.nodes[cursor]; 190 | smaller += keyCount + getNodeCount(self,c.left); 191 | } else { 192 | cursor = c.left; 193 | c = self.nodes[cursor]; 194 | smaller -= (keyCount + getNodeCount(self,c.right)); 195 | } 196 | } 197 | if (!exists(self,cursor)) { 198 | finished = true; 199 | } 200 | } 201 | } 202 | function insert(Tree storage self, bytes32 key, uint value) internal { 203 | require(value != EMPTY, "OrderStatisticsTree(405) - Value to insert cannot be zero"); 204 | require(!keyExists(self,key,value), "OrderStatisticsTree(406) - Value and Key pair exists. Cannot be inserted again."); 205 | uint cursor; 206 | uint probe = self.root; 207 | while (probe != EMPTY) { 208 | cursor = probe; 209 | if (value < probe) { 210 | probe = self.nodes[probe].left; 211 | } else if (value > probe) { 212 | probe = self.nodes[probe].right; 213 | } else if (value == probe) { 214 | self.nodes[probe].keyMap[key] = self.nodes[probe].keys.push(key) - uint(1); 215 | return; 216 | } 217 | self.nodes[cursor].count++; 218 | } 219 | Node storage nValue = self.nodes[value]; 220 | nValue.parent = cursor; 221 | nValue.left = EMPTY; 222 | nValue.right = EMPTY; 223 | nValue.red = true; 224 | nValue.keyMap[key] = nValue.keys.push(key) - uint(1); 225 | if (cursor == EMPTY) { 226 | self.root = value; 227 | } else if (value < cursor) { 228 | self.nodes[cursor].left = value; 229 | } else { 230 | self.nodes[cursor].right = value; 231 | } 232 | insertFixup(self, value); 233 | } 234 | function remove(Tree storage self, bytes32 key, uint value) internal { 235 | require(value != EMPTY, "OrderStatisticsTree(407) - Value to delete cannot be zero"); 236 | require(keyExists(self,key,value), "OrderStatisticsTree(408) - Value to delete does not exist."); 237 | Node storage nValue = self.nodes[value]; 238 | uint rowToDelete = nValue.keyMap[key]; 239 | nValue.keys[rowToDelete] = nValue.keys[nValue.keys.length - uint(1)]; 240 | nValue.keyMap[key]=rowToDelete; 241 | nValue.keys.length--; 242 | uint probe; 243 | uint cursor; 244 | if(nValue.keys.length == 0) { 245 | if (self.nodes[value].left == EMPTY || self.nodes[value].right == EMPTY) { 246 | cursor = value; 247 | } else { 248 | cursor = self.nodes[value].right; 249 | while (self.nodes[cursor].left != EMPTY) { 250 | cursor = self.nodes[cursor].left; 251 | } 252 | } 253 | if (self.nodes[cursor].left != EMPTY) { 254 | probe = self.nodes[cursor].left; 255 | } else { 256 | probe = self.nodes[cursor].right; 257 | } 258 | uint cursorParent = self.nodes[cursor].parent; 259 | self.nodes[probe].parent = cursorParent; 260 | if (cursorParent != EMPTY) { 261 | if (cursor == self.nodes[cursorParent].left) { 262 | self.nodes[cursorParent].left = probe; 263 | } else { 264 | self.nodes[cursorParent].right = probe; 265 | } 266 | } else { 267 | self.root = probe; 268 | } 269 | bool doFixup = !self.nodes[cursor].red; 270 | if (cursor != value) { 271 | replaceParent(self, cursor, value); 272 | self.nodes[cursor].left = self.nodes[value].left; 273 | self.nodes[self.nodes[cursor].left].parent = cursor; 274 | self.nodes[cursor].right = self.nodes[value].right; 275 | self.nodes[self.nodes[cursor].right].parent = cursor; 276 | self.nodes[cursor].red = self.nodes[value].red; 277 | (cursor, value) = (value, cursor); 278 | fixCountRecurse(self, value); 279 | } 280 | if (doFixup) { 281 | removeFixup(self, probe); 282 | } 283 | fixCountRecurse(self, cursorParent); 284 | delete self.nodes[cursor]; 285 | } 286 | } 287 | function fixCountRecurse(Tree storage self, uint value) private { 288 | while (value != EMPTY) { 289 | self.nodes[value].count = getNodeCount(self,self.nodes[value].left) + getNodeCount(self,self.nodes[value].right); 290 | value = self.nodes[value].parent; 291 | } 292 | } 293 | function treeMinimum(Tree storage self, uint value) private view returns (uint) { 294 | while (self.nodes[value].left != EMPTY) { 295 | value = self.nodes[value].left; 296 | } 297 | return value; 298 | } 299 | function treeMaximum(Tree storage self, uint value) private view returns (uint) { 300 | while (self.nodes[value].right != EMPTY) { 301 | value = self.nodes[value].right; 302 | } 303 | return value; 304 | } 305 | function rotateLeft(Tree storage self, uint value) private { 306 | uint cursor = self.nodes[value].right; 307 | uint parent = self.nodes[value].parent; 308 | uint cursorLeft = self.nodes[cursor].left; 309 | self.nodes[value].right = cursorLeft; 310 | if (cursorLeft != EMPTY) { 311 | self.nodes[cursorLeft].parent = value; 312 | } 313 | self.nodes[cursor].parent = parent; 314 | if (parent == EMPTY) { 315 | self.root = cursor; 316 | } else if (value == self.nodes[parent].left) { 317 | self.nodes[parent].left = cursor; 318 | } else { 319 | self.nodes[parent].right = cursor; 320 | } 321 | self.nodes[cursor].left = value; 322 | self.nodes[value].parent = cursor; 323 | self.nodes[value].count = getNodeCount(self,self.nodes[value].left) + getNodeCount(self,self.nodes[value].right); 324 | self.nodes[cursor].count = getNodeCount(self,self.nodes[cursor].left) + getNodeCount(self,self.nodes[cursor].right); 325 | } 326 | function rotateRight(Tree storage self, uint value) private { 327 | uint cursor = self.nodes[value].left; 328 | uint parent = self.nodes[value].parent; 329 | uint cursorRight = self.nodes[cursor].right; 330 | self.nodes[value].left = cursorRight; 331 | if (cursorRight != EMPTY) { 332 | self.nodes[cursorRight].parent = value; 333 | } 334 | self.nodes[cursor].parent = parent; 335 | if (parent == EMPTY) { 336 | self.root = cursor; 337 | } else if (value == self.nodes[parent].right) { 338 | self.nodes[parent].right = cursor; 339 | } else { 340 | self.nodes[parent].left = cursor; 341 | } 342 | self.nodes[cursor].right = value; 343 | self.nodes[value].parent = cursor; 344 | self.nodes[value].count = getNodeCount(self,self.nodes[value].left) + getNodeCount(self,self.nodes[value].right); 345 | self.nodes[cursor].count = getNodeCount(self,self.nodes[cursor].left) + getNodeCount(self,self.nodes[cursor].right); 346 | } 347 | function insertFixup(Tree storage self, uint value) private { 348 | uint cursor; 349 | while (value != self.root && self.nodes[self.nodes[value].parent].red) { 350 | uint valueParent = self.nodes[value].parent; 351 | if (valueParent == self.nodes[self.nodes[valueParent].parent].left) { 352 | cursor = self.nodes[self.nodes[valueParent].parent].right; 353 | if (self.nodes[cursor].red) { 354 | self.nodes[valueParent].red = false; 355 | self.nodes[cursor].red = false; 356 | self.nodes[self.nodes[valueParent].parent].red = true; 357 | value = self.nodes[valueParent].parent; 358 | } else { 359 | if (value == self.nodes[valueParent].right) { 360 | value = valueParent; 361 | rotateLeft(self, value); 362 | } 363 | valueParent = self.nodes[value].parent; 364 | self.nodes[valueParent].red = false; 365 | self.nodes[self.nodes[valueParent].parent].red = true; 366 | rotateRight(self, self.nodes[valueParent].parent); 367 | } 368 | } else { 369 | cursor = self.nodes[self.nodes[valueParent].parent].left; 370 | if (self.nodes[cursor].red) { 371 | self.nodes[valueParent].red = false; 372 | self.nodes[cursor].red = false; 373 | self.nodes[self.nodes[valueParent].parent].red = true; 374 | value = self.nodes[valueParent].parent; 375 | } else { 376 | if (value == self.nodes[valueParent].left) { 377 | value = valueParent; 378 | rotateRight(self, value); 379 | } 380 | valueParent = self.nodes[value].parent; 381 | self.nodes[valueParent].red = false; 382 | self.nodes[self.nodes[valueParent].parent].red = true; 383 | rotateLeft(self, self.nodes[valueParent].parent); 384 | } 385 | } 386 | } 387 | self.nodes[self.root].red = false; 388 | } 389 | function replaceParent(Tree storage self, uint a, uint b) private { 390 | uint bParent = self.nodes[b].parent; 391 | self.nodes[a].parent = bParent; 392 | if (bParent == EMPTY) { 393 | self.root = a; 394 | } else { 395 | if (b == self.nodes[bParent].left) { 396 | self.nodes[bParent].left = a; 397 | } else { 398 | self.nodes[bParent].right = a; 399 | } 400 | } 401 | } 402 | function removeFixup(Tree storage self, uint value) private { 403 | uint cursor; 404 | while (value != self.root && !self.nodes[value].red) { 405 | uint valueParent = self.nodes[value].parent; 406 | if (value == self.nodes[valueParent].left) { 407 | cursor = self.nodes[valueParent].right; 408 | if (self.nodes[cursor].red) { 409 | self.nodes[cursor].red = false; 410 | self.nodes[valueParent].red = true; 411 | rotateLeft(self, valueParent); 412 | cursor = self.nodes[valueParent].right; 413 | } 414 | if (!self.nodes[self.nodes[cursor].left].red && !self.nodes[self.nodes[cursor].right].red) { 415 | self.nodes[cursor].red = true; 416 | value = valueParent; 417 | } else { 418 | if (!self.nodes[self.nodes[cursor].right].red) { 419 | self.nodes[self.nodes[cursor].left].red = false; 420 | self.nodes[cursor].red = true; 421 | rotateRight(self, cursor); 422 | cursor = self.nodes[valueParent].right; 423 | } 424 | self.nodes[cursor].red = self.nodes[valueParent].red; 425 | self.nodes[valueParent].red = false; 426 | self.nodes[self.nodes[cursor].right].red = false; 427 | rotateLeft(self, valueParent); 428 | value = self.root; 429 | } 430 | } else { 431 | cursor = self.nodes[valueParent].left; 432 | if (self.nodes[cursor].red) { 433 | self.nodes[cursor].red = false; 434 | self.nodes[valueParent].red = true; 435 | rotateRight(self, valueParent); 436 | cursor = self.nodes[valueParent].left; 437 | } 438 | if (!self.nodes[self.nodes[cursor].right].red && !self.nodes[self.nodes[cursor].left].red) { 439 | self.nodes[cursor].red = true; 440 | value = valueParent; 441 | } else { 442 | if (!self.nodes[self.nodes[cursor].left].red) { 443 | self.nodes[self.nodes[cursor].right].red = false; 444 | self.nodes[cursor].red = true; 445 | rotateLeft(self, cursor); 446 | cursor = self.nodes[valueParent].left; 447 | } 448 | self.nodes[cursor].red = self.nodes[valueParent].red; 449 | self.nodes[valueParent].red = false; 450 | self.nodes[self.nodes[cursor].left].red = false; 451 | rotateRight(self, valueParent); 452 | value = self.root; 453 | } 454 | } 455 | } 456 | self.nodes[value].red = false; 457 | } 458 | } 459 | -------------------------------------------------------------------------------- /contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | pragma solidity >=0.4.21 <0.7.0; 2 | 3 | contract Migrations { 4 | address public owner; 5 | uint public last_completed_migration; 6 | 7 | constructor() public { 8 | owner = msg.sender; 9 | } 10 | 11 | modifier restricted() { 12 | if (msg.sender == owner) _; 13 | } 14 | 15 | function setCompleted(uint completed) public restricted { 16 | last_completed_migration = completed; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /contracts/Owned.sol: -------------------------------------------------------------------------------- 1 | pragma solidity 0.5.1; 2 | 3 | interface OwnedInterface { 4 | function getOwner() external view returns(address owner); 5 | function changeOwner(address newOwner) external returns (bool success); 6 | } 7 | 8 | contract Owned is OwnedInterface { 9 | 10 | address private contractOwner; 11 | 12 | event LogOwnerChanged( 13 | address newOwner); 14 | 15 | modifier onlyOwner { 16 | require(msg.sender == contractOwner); 17 | _; 18 | } 19 | 20 | constructor() public { 21 | contractOwner = msg.sender; 22 | } 23 | 24 | function getOwner() public view returns(address owner) { 25 | return contractOwner; 26 | } 27 | 28 | function changeOwner(address newOwner) 29 | public 30 | onlyOwner 31 | returns(bool success) 32 | { 33 | require(newOwner != address(0)); 34 | emit LogOwnerChanged(newOwner); 35 | contractOwner = newOwner; 36 | return true; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /contracts/artifacts/HitchensOrderStatisticsTreeLib.json: -------------------------------------------------------------------------------- 1 | { 2 | "deploy": { 3 | "VM:-": { 4 | "linkReferences": {}, 5 | "autoDeployLib": true 6 | }, 7 | "main:1": { 8 | "linkReferences": {}, 9 | "autoDeployLib": true 10 | }, 11 | "ropsten:3": { 12 | "linkReferences": {}, 13 | "autoDeployLib": true 14 | }, 15 | "rinkeby:4": { 16 | "linkReferences": {}, 17 | "autoDeployLib": true 18 | }, 19 | "kovan:42": { 20 | "linkReferences": {}, 21 | "autoDeployLib": true 22 | }, 23 | "görli:5": { 24 | "linkReferences": {}, 25 | "autoDeployLib": true 26 | }, 27 | "Custom": { 28 | "linkReferences": {}, 29 | "autoDeployLib": true 30 | } 31 | }, 32 | "data": { 33 | "bytecode": { 34 | "linkReferences": {}, 35 | "object": "61033f610030600b82828239805160001a6073146000811461002057610022565bfe5b5030600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061005d576000357c0100000000000000000000000000000000000000000000000000000000900480637a1b1bb91461006257806382d26d93146100ae575b600080fd5b6100986004803603604081101561007857600080fd5b8101908080359060200190929190803590602001909291905050506100fa565b6040518082815260200191505060405180910390f35b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061012e565b6040518082815260200191505060405180910390f35b6000806101068461015d565b1180156101135750600082115b156101285760016101248484610174565b0390505b92915050565b60008061013a8461015d565b11156101575761014a8383610174565b6101538461015d565b0390505b92915050565b600061016d828360000154610284565b9050919050565b6000806101808461015d565b111561027d57600080846000015490506000856001016000838152602001908152602001600020905060006101b9878360010154610284565b90505b83151561026e57600082600401805490509050868414156101e05760019450610253565b8684101561021f57826002015493508760010160008581526020019081526020016000209250610214888460010154610284565b810182019150610252565b82600101549350876001016000858152602001908152602001600020925061024b888460020154610284565b8101820391505b5b61025d88856102b5565b151561026857600194505b506101bc565b6001810194505050505061027e565b5b92915050565b6000808360010160008481526020019081526020016000209050806006015481600401805490500191505092915050565b6000808214156102c8576000905061030d565b82600001548214156102dd576001905061030d565b600083600101600084815260200190815260200160002060000154141515610308576001905061030d565b600090505b9291505056fea165627a7a723058202ef68b72d9327d8b26dcd764458e5881afd403fde777943c1833a0b18396430a0029", 36 | "opcodes": "PUSH2 0x33F PUSH2 0x30 PUSH1 0xB DUP3 DUP3 DUP3 CODECOPY DUP1 MLOAD PUSH1 0x0 BYTE PUSH1 0x73 EQ PUSH1 0x0 DUP2 EQ PUSH2 0x20 JUMPI PUSH2 0x22 JUMP JUMPDEST INVALID JUMPDEST POP ADDRESS PUSH1 0x0 MSTORE PUSH1 0x73 DUP2 MSTORE8 DUP3 DUP2 RETURN INVALID PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x5D JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x7A1B1BB9 EQ PUSH2 0x62 JUMPI DUP1 PUSH4 0x82D26D93 EQ PUSH2 0xAE JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x98 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x78 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0xFA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0xE4 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0xC4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x12E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x106 DUP5 PUSH2 0x15D JUMP JUMPDEST GT DUP1 ISZERO PUSH2 0x113 JUMPI POP PUSH1 0x0 DUP3 GT JUMPDEST ISZERO PUSH2 0x128 JUMPI PUSH1 0x1 PUSH2 0x124 DUP5 DUP5 PUSH2 0x174 JUMP JUMPDEST SUB SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x13A DUP5 PUSH2 0x15D JUMP JUMPDEST GT ISZERO PUSH2 0x157 JUMPI PUSH2 0x14A DUP4 DUP4 PUSH2 0x174 JUMP JUMPDEST PUSH2 0x153 DUP5 PUSH2 0x15D JUMP JUMPDEST SUB SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x16D DUP3 DUP4 PUSH1 0x0 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x180 DUP5 PUSH2 0x15D JUMP JUMPDEST GT ISZERO PUSH2 0x27D JUMPI PUSH1 0x0 DUP1 DUP5 PUSH1 0x0 ADD SLOAD SWAP1 POP PUSH1 0x0 DUP6 PUSH1 0x1 ADD PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP PUSH1 0x0 PUSH2 0x1B9 DUP8 DUP4 PUSH1 0x1 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST SWAP1 POP JUMPDEST DUP4 ISZERO ISZERO PUSH2 0x26E JUMPI PUSH1 0x0 DUP3 PUSH1 0x4 ADD DUP1 SLOAD SWAP1 POP SWAP1 POP DUP7 DUP5 EQ ISZERO PUSH2 0x1E0 JUMPI PUSH1 0x1 SWAP5 POP PUSH2 0x253 JUMP JUMPDEST DUP7 DUP5 LT ISZERO PUSH2 0x21F JUMPI DUP3 PUSH1 0x2 ADD SLOAD SWAP4 POP DUP8 PUSH1 0x1 ADD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP3 POP PUSH2 0x214 DUP9 DUP5 PUSH1 0x1 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST DUP2 ADD DUP3 ADD SWAP2 POP PUSH2 0x252 JUMP JUMPDEST DUP3 PUSH1 0x1 ADD SLOAD SWAP4 POP DUP8 PUSH1 0x1 ADD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP3 POP PUSH2 0x24B DUP9 DUP5 PUSH1 0x2 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST DUP2 ADD DUP3 SUB SWAP2 POP JUMPDEST JUMPDEST PUSH2 0x25D DUP9 DUP6 PUSH2 0x2B5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x268 JUMPI PUSH1 0x1 SWAP5 POP JUMPDEST POP PUSH2 0x1BC JUMP JUMPDEST PUSH1 0x1 DUP2 ADD SWAP5 POP POP POP POP POP PUSH2 0x27E JUMP JUMPDEST JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP4 PUSH1 0x1 ADD PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x6 ADD SLOAD DUP2 PUSH1 0x4 ADD DUP1 SLOAD SWAP1 POP ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 EQ ISZERO PUSH2 0x2C8 JUMPI PUSH1 0x0 SWAP1 POP PUSH2 0x30D JUMP JUMPDEST DUP3 PUSH1 0x0 ADD SLOAD DUP3 EQ ISZERO PUSH2 0x2DD JUMPI PUSH1 0x1 SWAP1 POP PUSH2 0x30D JUMP JUMPDEST PUSH1 0x0 DUP4 PUSH1 0x1 ADD PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 ADD SLOAD EQ ISZERO ISZERO PUSH2 0x308 JUMPI PUSH1 0x1 SWAP1 POP PUSH2 0x30D JUMP JUMPDEST PUSH1 0x0 SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 0x2e 0xf6 DUP12 PUSH19 0xD9327D8B26DCD764458E5881AFD403FDE77794 EXTCODECOPY XOR CALLER LOG0 0xb1 DUP4 SWAP7 NUMBER EXP STOP 0x29 ", 37 | "sourceMap": "1593:18503:0:-;;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" 38 | }, 39 | "deployedBytecode": { 40 | "linkReferences": {}, 41 | "object": "730000000000000000000000000000000000000000301460806040526004361061005d576000357c0100000000000000000000000000000000000000000000000000000000900480637a1b1bb91461006257806382d26d93146100ae575b600080fd5b6100986004803603604081101561007857600080fd5b8101908080359060200190929190803590602001909291905050506100fa565b6040518082815260200191505060405180910390f35b6100e4600480360360408110156100c457600080fd5b81019080803590602001909291908035906020019092919050505061012e565b6040518082815260200191505060405180910390f35b6000806101068461015d565b1180156101135750600082115b156101285760016101248484610174565b0390505b92915050565b60008061013a8461015d565b11156101575761014a8383610174565b6101538461015d565b0390505b92915050565b600061016d828360000154610284565b9050919050565b6000806101808461015d565b111561027d57600080846000015490506000856001016000838152602001908152602001600020905060006101b9878360010154610284565b90505b83151561026e57600082600401805490509050868414156101e05760019450610253565b8684101561021f57826002015493508760010160008581526020019081526020016000209250610214888460010154610284565b810182019150610252565b82600101549350876001016000858152602001908152602001600020925061024b888460020154610284565b8101820391505b5b61025d88856102b5565b151561026857600194505b506101bc565b6001810194505050505061027e565b5b92915050565b6000808360010160008481526020019081526020016000209050806006015481600401805490500191505092915050565b6000808214156102c8576000905061030d565b82600001548214156102dd576001905061030d565b600083600101600084815260200190815260200160002060000154141515610308576001905061030d565b600090505b9291505056fea165627a7a723058202ef68b72d9327d8b26dcd764458e5881afd403fde777943c1833a0b18396430a0029", 42 | "opcodes": "PUSH20 0x0 ADDRESS EQ PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH2 0x5D JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV DUP1 PUSH4 0x7A1B1BB9 EQ PUSH2 0x62 JUMPI DUP1 PUSH4 0x82D26D93 EQ PUSH2 0xAE JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH2 0x98 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0x78 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0xFA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH2 0xE4 PUSH1 0x4 DUP1 CALLDATASIZE SUB PUSH1 0x40 DUP2 LT ISZERO PUSH2 0xC4 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH2 0x12E JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x106 DUP5 PUSH2 0x15D JUMP JUMPDEST GT DUP1 ISZERO PUSH2 0x113 JUMPI POP PUSH1 0x0 DUP3 GT JUMPDEST ISZERO PUSH2 0x128 JUMPI PUSH1 0x1 PUSH2 0x124 DUP5 DUP5 PUSH2 0x174 JUMP JUMPDEST SUB SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x13A DUP5 PUSH2 0x15D JUMP JUMPDEST GT ISZERO PUSH2 0x157 JUMPI PUSH2 0x14A DUP4 DUP4 PUSH2 0x174 JUMP JUMPDEST PUSH2 0x153 DUP5 PUSH2 0x15D JUMP JUMPDEST SUB SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 PUSH2 0x16D DUP3 DUP4 PUSH1 0x0 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST SWAP1 POP SWAP2 SWAP1 POP JUMP JUMPDEST PUSH1 0x0 DUP1 PUSH2 0x180 DUP5 PUSH2 0x15D JUMP JUMPDEST GT ISZERO PUSH2 0x27D JUMPI PUSH1 0x0 DUP1 DUP5 PUSH1 0x0 ADD SLOAD SWAP1 POP PUSH1 0x0 DUP6 PUSH1 0x1 ADD PUSH1 0x0 DUP4 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP PUSH1 0x0 PUSH2 0x1B9 DUP8 DUP4 PUSH1 0x1 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST SWAP1 POP JUMPDEST DUP4 ISZERO ISZERO PUSH2 0x26E JUMPI PUSH1 0x0 DUP3 PUSH1 0x4 ADD DUP1 SLOAD SWAP1 POP SWAP1 POP DUP7 DUP5 EQ ISZERO PUSH2 0x1E0 JUMPI PUSH1 0x1 SWAP5 POP PUSH2 0x253 JUMP JUMPDEST DUP7 DUP5 LT ISZERO PUSH2 0x21F JUMPI DUP3 PUSH1 0x2 ADD SLOAD SWAP4 POP DUP8 PUSH1 0x1 ADD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP3 POP PUSH2 0x214 DUP9 DUP5 PUSH1 0x1 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST DUP2 ADD DUP3 ADD SWAP2 POP PUSH2 0x252 JUMP JUMPDEST DUP3 PUSH1 0x1 ADD SLOAD SWAP4 POP DUP8 PUSH1 0x1 ADD PUSH1 0x0 DUP6 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP3 POP PUSH2 0x24B DUP9 DUP5 PUSH1 0x2 ADD SLOAD PUSH2 0x284 JUMP JUMPDEST DUP2 ADD DUP3 SUB SWAP2 POP JUMPDEST JUMPDEST PUSH2 0x25D DUP9 DUP6 PUSH2 0x2B5 JUMP JUMPDEST ISZERO ISZERO PUSH2 0x268 JUMPI PUSH1 0x1 SWAP5 POP JUMPDEST POP PUSH2 0x1BC JUMP JUMPDEST PUSH1 0x1 DUP2 ADD SWAP5 POP POP POP POP POP PUSH2 0x27E JUMP JUMPDEST JUMPDEST SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP4 PUSH1 0x1 ADD PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 SWAP1 POP DUP1 PUSH1 0x6 ADD SLOAD DUP2 PUSH1 0x4 ADD DUP1 SLOAD SWAP1 POP ADD SWAP2 POP POP SWAP3 SWAP2 POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 DUP3 EQ ISZERO PUSH2 0x2C8 JUMPI PUSH1 0x0 SWAP1 POP PUSH2 0x30D JUMP JUMPDEST DUP3 PUSH1 0x0 ADD SLOAD DUP3 EQ ISZERO PUSH2 0x2DD JUMPI PUSH1 0x1 SWAP1 POP PUSH2 0x30D JUMP JUMPDEST PUSH1 0x0 DUP4 PUSH1 0x1 ADD PUSH1 0x0 DUP5 DUP2 MSTORE PUSH1 0x20 ADD SWAP1 DUP2 MSTORE PUSH1 0x20 ADD PUSH1 0x0 KECCAK256 PUSH1 0x0 ADD SLOAD EQ ISZERO ISZERO PUSH2 0x308 JUMPI PUSH1 0x1 SWAP1 POP PUSH2 0x30D JUMP JUMPDEST PUSH1 0x0 SWAP1 POP JUMPDEST SWAP3 SWAP2 POP POP JUMP INVALID LOG1 PUSH6 0x627A7A723058 KECCAK256 0x2e 0xf6 DUP12 PUSH19 0xD9327D8B26DCD764458E5881AFD403FDE77794 EXTCODECOPY XOR CALLER LOG0 0xb1 DUP4 SWAP7 NUMBER EXP STOP 0x29 ", 43 | "sourceMap": "1593:18503:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6113:162;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6113:162:0;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;6280:153;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;6280:153:0;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;6113:162;6179:11;6219:1;6205:11;6211:4;6205:5;:11::i;:::-;:15;:28;;;;;6232:1;6224:5;:9;6205:28;6202:66;;;6266:1;6244:16;6249:4;6254:5;6244:4;:16::i;:::-;:24;6235:33;;6202:66;6113:162;;;;:::o;6280:153::-;6346:11;6386:1;6372:11;6378:4;6372:5;:11::i;:::-;:15;6369:57;;;6410:16;6415:4;6420:5;6410:4;:16::i;:::-;6398:11;6404:4;6398:5;:11::i;:::-;:28;6389:37;;6369:57;6280:153;;;;:::o;4888:121::-;4944:11;4974:28;4987:4;4992;:9;;;4974:12;:28::i;:::-;4967:35;;4888:121;;;:::o;6439:1055::-;6506:10;6545:1;6531:11;6537:4;6531:5;:11::i;:::-;:15;6528:960;;;6562:13;6589:11;6603:4;:9;;;6589:23;;6626:14;6643:4;:10;;:18;6654:6;6643:18;;;;;;;;;;;6626:35;;6675:12;6690:25;6703:4;6708:1;:6;;;6690:12;:25::i;:::-;6675:40;;6729:717;6737:8;6736:9;6729:717;;;6765:13;6781:1;:6;;:13;;;;6765:29;;6825:5;6815:6;:15;6812:521;;;6865:4;6854:15;;6812:521;;;6928:5;6919:6;:14;6916:399;;;6970:1;:7;;;6961:16;;7007:4;:10;;:18;7018:6;7007:18;;;;;;;;;;;7003:22;;7073:25;7086:4;7091:1;:6;;;7073:12;:25::i;:::-;7062:8;:36;7051:47;;;;6916:399;;;7162:1;:6;;;7153:15;;7198:4;:10;;:18;7209:6;7198:18;;;;;;;;;;;7194:22;;7265:26;7278:4;7283:1;:7;;;7265:12;:26::i;:::-;7254:8;:37;7242:50;;;;6916:399;6812:521;7355:19;7362:4;7367:6;7355;:19::i;:::-;7354:20;7350:82;;;7409:4;7398:15;;7350:82;6729:717;;;;7476:1;7466:7;:11;7459:18;;;;;;;;6528:960;6439:1055;;;;;:::o;4453:179::-;4528:10;4550:15;4568:4;:10;;:17;4579:5;4568:17;;;;;;;;;;;4550:35;;4617:2;:8;;;4602:2;:7;;:14;;;;:23;4595:30;;;4453:179;;;;:::o;3558:264::-;3628:12;1668:1;3655:5;:14;3652:31;;;3678:5;3671:12;;;;3652:31;3705:4;:9;;;3696:5;:18;3693:34;;;3723:4;3716:11;;;;3693:34;1668:1;3740:4;:10;;:17;3751:5;3740:17;;;;;;;;;;;:24;;;:33;;3737:49;;;3782:4;3775:11;;;;3737:49;3803:5;3796:12;;3558:264;;;;;:::o" 44 | }, 45 | "gasEstimates": { 46 | "creation": { 47 | "codeDepositCost": "166200", 48 | "executionCost": "258", 49 | "totalCost": "166458" 50 | }, 51 | "external": { 52 | "above(HitchensOrderStatisticsTreeLib.Tree storage,uint256)": "infinite", 53 | "below(HitchensOrderStatisticsTreeLib.Tree storage,uint256)": "infinite" 54 | }, 55 | "internal": { 56 | "atPercentile(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 57 | "atPermil(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 58 | "atRank(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 59 | "count(struct HitchensOrderStatisticsTreeLib.Tree storage pointer)": "811", 60 | "exists(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "624", 61 | "first(struct HitchensOrderStatisticsTreeLib.Tree storage pointer)": "infinite", 62 | "fixCountRecurse(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 63 | "getNode(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 64 | "getNodeCount(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "559", 65 | "insert(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,bytes32,uint256)": "infinite", 66 | "insertFixup(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 67 | "keyExists(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,bytes32,uint256)": "infinite", 68 | "last(struct HitchensOrderStatisticsTreeLib.Tree storage pointer)": "infinite", 69 | "median(struct HitchensOrderStatisticsTreeLib.Tree storage pointer)": "infinite", 70 | "next(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 71 | "percentile(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 72 | "permil(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 73 | "prev(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 74 | "rank(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 75 | "remove(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,bytes32,uint256)": "infinite", 76 | "removeFixup(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 77 | "replaceParent(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256,uint256)": "infinite", 78 | "rotateLeft(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 79 | "rotateRight(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 80 | "treeMaximum(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 81 | "treeMinimum(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256)": "infinite", 82 | "valueKeyAtIndex(struct HitchensOrderStatisticsTreeLib.Tree storage pointer,uint256,uint256)": "infinite" 83 | } 84 | }, 85 | "methodIdentifiers": { 86 | "above(HitchensOrderStatisticsTreeLib.Tree storage,uint256)": "82d26d93", 87 | "below(HitchensOrderStatisticsTreeLib.Tree storage,uint256)": "7a1b1bb9" 88 | } 89 | }, 90 | "abi": [ 91 | { 92 | "constant": true, 93 | "inputs": [ 94 | { 95 | "name": "self", 96 | "type": "HitchensOrderStatisticsTreeLib.Tree storage" 97 | }, 98 | { 99 | "name": "value", 100 | "type": "uint256" 101 | } 102 | ], 103 | "name": "below", 104 | "outputs": [ 105 | { 106 | "name": "_below", 107 | "type": "uint256" 108 | } 109 | ], 110 | "payable": false, 111 | "stateMutability": "view", 112 | "type": "function" 113 | }, 114 | { 115 | "constant": true, 116 | "inputs": [ 117 | { 118 | "name": "self", 119 | "type": "HitchensOrderStatisticsTreeLib.Tree storage" 120 | }, 121 | { 122 | "name": "value", 123 | "type": "uint256" 124 | } 125 | ], 126 | "name": "above", 127 | "outputs": [ 128 | { 129 | "name": "_above", 130 | "type": "uint256" 131 | } 132 | ], 133 | "payable": false, 134 | "stateMutability": "view", 135 | "type": "function" 136 | } 137 | ] 138 | } -------------------------------------------------------------------------------- /contracts/artifacts/HitchensOrderStatisticsTreeLib_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "compiler": { 3 | "version": "0.5.1+commit.c8a2cb62" 4 | }, 5 | "language": "Solidity", 6 | "output": { 7 | "abi": [ 8 | { 9 | "constant": true, 10 | "inputs": [ 11 | { 12 | "name": "self", 13 | "type": "HitchensOrderStatisticsTreeLib.Tree storage" 14 | }, 15 | { 16 | "name": "value", 17 | "type": "uint256" 18 | } 19 | ], 20 | "name": "below", 21 | "outputs": [ 22 | { 23 | "name": "_below", 24 | "type": "uint256" 25 | } 26 | ], 27 | "payable": false, 28 | "stateMutability": "view", 29 | "type": "function" 30 | }, 31 | { 32 | "constant": true, 33 | "inputs": [ 34 | { 35 | "name": "self", 36 | "type": "HitchensOrderStatisticsTreeLib.Tree storage" 37 | }, 38 | { 39 | "name": "value", 40 | "type": "uint256" 41 | } 42 | ], 43 | "name": "above", 44 | "outputs": [ 45 | { 46 | "name": "_above", 47 | "type": "uint256" 48 | } 49 | ], 50 | "payable": false, 51 | "stateMutability": "view", 52 | "type": "function" 53 | } 54 | ], 55 | "devdoc": { 56 | "methods": {} 57 | }, 58 | "userdoc": { 59 | "methods": {} 60 | } 61 | }, 62 | "settings": { 63 | "compilationTarget": { 64 | "localhost/contracts/HitchensOrderStatisticsTree.sol": "HitchensOrderStatisticsTreeLib" 65 | }, 66 | "evmVersion": "byzantium", 67 | "libraries": {}, 68 | "optimizer": { 69 | "enabled": false, 70 | "runs": 200 71 | }, 72 | "remappings": [] 73 | }, 74 | "sources": { 75 | "localhost/contracts/HitchensOrderStatisticsTree.sol": { 76 | "keccak256": "0xfb7656d8410937fcbb97bd3e5ca7dbd9fdb2f0a71e64f453951fd8ca36225614", 77 | "urls": [ 78 | "bzzr://31f91f96a242b92e4d5e2a5db93de6faab17c7cf3370089c4c60c38979cf6b76" 79 | ] 80 | }, 81 | "localhost/contracts/Owned.sol": { 82 | "keccak256": "0x7e33ac18d51897110d75d33808f6db9bca46133a839f093f22014fccc3754e0c", 83 | "urls": [ 84 | "bzzr://63ecf788bbe9ed2de96a434fdc4ce104ac6526530acc2e33dfe9667be3da7a30" 85 | ] 86 | } 87 | }, 88 | "version": 1 89 | } -------------------------------------------------------------------------------- /contracts/artifacts/HitchensOrderStatisticsTree_metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "compiler": { 3 | "version": "0.5.1+commit.c8a2cb62" 4 | }, 5 | "language": "Solidity", 6 | "output": { 7 | "abi": [ 8 | { 9 | "constant": true, 10 | "inputs": [ 11 | { 12 | "name": "value", 13 | "type": "uint256" 14 | } 15 | ], 16 | "name": "prevValue", 17 | "outputs": [ 18 | { 19 | "name": "_value", 20 | "type": "uint256" 21 | } 22 | ], 23 | "payable": false, 24 | "stateMutability": "view", 25 | "type": "function" 26 | }, 27 | { 28 | "constant": true, 29 | "inputs": [ 30 | { 31 | "name": "value", 32 | "type": "uint256" 33 | } 34 | ], 35 | "name": "valueRank", 36 | "outputs": [ 37 | { 38 | "name": "_rank", 39 | "type": "uint256" 40 | } 41 | ], 42 | "payable": false, 43 | "stateMutability": "view", 44 | "type": "function" 45 | }, 46 | { 47 | "constant": true, 48 | "inputs": [ 49 | { 50 | "name": "value", 51 | "type": "uint256" 52 | } 53 | ], 54 | "name": "nextValue", 55 | "outputs": [ 56 | { 57 | "name": "_value", 58 | "type": "uint256" 59 | } 60 | ], 61 | "payable": false, 62 | "stateMutability": "view", 63 | "type": "function" 64 | }, 65 | { 66 | "constant": true, 67 | "inputs": [ 68 | { 69 | "name": "value", 70 | "type": "uint256" 71 | } 72 | ], 73 | "name": "valueExists", 74 | "outputs": [ 75 | { 76 | "name": "_exists", 77 | "type": "bool" 78 | } 79 | ], 80 | "payable": false, 81 | "stateMutability": "view", 82 | "type": "function" 83 | }, 84 | { 85 | "constant": true, 86 | "inputs": [ 87 | { 88 | "name": "value", 89 | "type": "uint256" 90 | } 91 | ], 92 | "name": "valuePermil", 93 | "outputs": [ 94 | { 95 | "name": "_permil", 96 | "type": "uint256" 97 | } 98 | ], 99 | "payable": false, 100 | "stateMutability": "view", 101 | "type": "function" 102 | }, 103 | { 104 | "constant": true, 105 | "inputs": [], 106 | "name": "lastValue", 107 | "outputs": [ 108 | { 109 | "name": "_value", 110 | "type": "uint256" 111 | } 112 | ], 113 | "payable": false, 114 | "stateMutability": "view", 115 | "type": "function" 116 | }, 117 | { 118 | "constant": true, 119 | "inputs": [ 120 | { 121 | "name": "value", 122 | "type": "uint256" 123 | } 124 | ], 125 | "name": "getNode", 126 | "outputs": [ 127 | { 128 | "name": "_parent", 129 | "type": "uint256" 130 | }, 131 | { 132 | "name": "_left", 133 | "type": "uint256" 134 | }, 135 | { 136 | "name": "_right", 137 | "type": "uint256" 138 | }, 139 | { 140 | "name": "_red", 141 | "type": "bool" 142 | }, 143 | { 144 | "name": "_keyCount", 145 | "type": "uint256" 146 | }, 147 | { 148 | "name": "_count", 149 | "type": "uint256" 150 | } 151 | ], 152 | "payable": false, 153 | "stateMutability": "view", 154 | "type": "function" 155 | }, 156 | { 157 | "constant": true, 158 | "inputs": [], 159 | "name": "medianValue", 160 | "outputs": [ 161 | { 162 | "name": "_value", 163 | "type": "uint256" 164 | } 165 | ], 166 | "payable": false, 167 | "stateMutability": "view", 168 | "type": "function" 169 | }, 170 | { 171 | "constant": true, 172 | "inputs": [ 173 | { 174 | "name": "key", 175 | "type": "bytes32" 176 | }, 177 | { 178 | "name": "value", 179 | "type": "uint256" 180 | } 181 | ], 182 | "name": "keyValueExists", 183 | "outputs": [ 184 | { 185 | "name": "_exists", 186 | "type": "bool" 187 | } 188 | ], 189 | "payable": false, 190 | "stateMutability": "view", 191 | "type": "function" 192 | }, 193 | { 194 | "constant": false, 195 | "inputs": [ 196 | { 197 | "name": "key", 198 | "type": "bytes32" 199 | }, 200 | { 201 | "name": "value", 202 | "type": "uint256" 203 | } 204 | ], 205 | "name": "removeKeyValue", 206 | "outputs": [], 207 | "payable": false, 208 | "stateMutability": "nonpayable", 209 | "type": "function" 210 | }, 211 | { 212 | "constant": true, 213 | "inputs": [ 214 | { 215 | "name": "value", 216 | "type": "uint256" 217 | }, 218 | { 219 | "name": "row", 220 | "type": "uint256" 221 | } 222 | ], 223 | "name": "getValueKey", 224 | "outputs": [ 225 | { 226 | "name": "_key", 227 | "type": "bytes32" 228 | } 229 | ], 230 | "payable": false, 231 | "stateMutability": "view", 232 | "type": "function" 233 | }, 234 | { 235 | "constant": false, 236 | "inputs": [ 237 | { 238 | "name": "key", 239 | "type": "bytes32" 240 | }, 241 | { 242 | "name": "value", 243 | "type": "uint256" 244 | } 245 | ], 246 | "name": "insertKeyValue", 247 | "outputs": [], 248 | "payable": false, 249 | "stateMutability": "nonpayable", 250 | "type": "function" 251 | }, 252 | { 253 | "constant": true, 254 | "inputs": [], 255 | "name": "firstValue", 256 | "outputs": [ 257 | { 258 | "name": "_value", 259 | "type": "uint256" 260 | } 261 | ], 262 | "payable": false, 263 | "stateMutability": "view", 264 | "type": "function" 265 | }, 266 | { 267 | "constant": true, 268 | "inputs": [], 269 | "name": "treeRootNode", 270 | "outputs": [ 271 | { 272 | "name": "_value", 273 | "type": "uint256" 274 | } 275 | ], 276 | "payable": false, 277 | "stateMutability": "view", 278 | "type": "function" 279 | }, 280 | { 281 | "constant": true, 282 | "inputs": [], 283 | "name": "getOwner", 284 | "outputs": [ 285 | { 286 | "name": "owner", 287 | "type": "address" 288 | } 289 | ], 290 | "payable": false, 291 | "stateMutability": "view", 292 | "type": "function" 293 | }, 294 | { 295 | "constant": true, 296 | "inputs": [ 297 | { 298 | "name": "_rank", 299 | "type": "uint256" 300 | } 301 | ], 302 | "name": "valueAtRank", 303 | "outputs": [ 304 | { 305 | "name": "_value", 306 | "type": "uint256" 307 | } 308 | ], 309 | "payable": false, 310 | "stateMutability": "view", 311 | "type": "function" 312 | }, 313 | { 314 | "constant": true, 315 | "inputs": [ 316 | { 317 | "name": "value", 318 | "type": "uint256" 319 | } 320 | ], 321 | "name": "valuesBelow", 322 | "outputs": [ 323 | { 324 | "name": "_below", 325 | "type": "uint256" 326 | } 327 | ], 328 | "payable": false, 329 | "stateMutability": "view", 330 | "type": "function" 331 | }, 332 | { 333 | "constant": true, 334 | "inputs": [], 335 | "name": "valueKeyCount", 336 | "outputs": [ 337 | { 338 | "name": "_count", 339 | "type": "uint256" 340 | } 341 | ], 342 | "payable": false, 343 | "stateMutability": "view", 344 | "type": "function" 345 | }, 346 | { 347 | "constant": false, 348 | "inputs": [ 349 | { 350 | "name": "newOwner", 351 | "type": "address" 352 | } 353 | ], 354 | "name": "changeOwner", 355 | "outputs": [ 356 | { 357 | "name": "success", 358 | "type": "bool" 359 | } 360 | ], 361 | "payable": false, 362 | "stateMutability": "nonpayable", 363 | "type": "function" 364 | }, 365 | { 366 | "constant": true, 367 | "inputs": [ 368 | { 369 | "name": "value", 370 | "type": "uint256" 371 | } 372 | ], 373 | "name": "valuesAbove", 374 | "outputs": [ 375 | { 376 | "name": "_above", 377 | "type": "uint256" 378 | } 379 | ], 380 | "payable": false, 381 | "stateMutability": "view", 382 | "type": "function" 383 | }, 384 | { 385 | "constant": true, 386 | "inputs": [ 387 | { 388 | "name": "value", 389 | "type": "uint256" 390 | } 391 | ], 392 | "name": "valueAtPermil", 393 | "outputs": [ 394 | { 395 | "name": "_value", 396 | "type": "uint256" 397 | } 398 | ], 399 | "payable": false, 400 | "stateMutability": "view", 401 | "type": "function" 402 | }, 403 | { 404 | "constant": true, 405 | "inputs": [ 406 | { 407 | "name": "_percentile", 408 | "type": "uint256" 409 | } 410 | ], 411 | "name": "valueAtPercentile", 412 | "outputs": [ 413 | { 414 | "name": "_value", 415 | "type": "uint256" 416 | } 417 | ], 418 | "payable": false, 419 | "stateMutability": "view", 420 | "type": "function" 421 | }, 422 | { 423 | "constant": true, 424 | "inputs": [ 425 | { 426 | "name": "value", 427 | "type": "uint256" 428 | } 429 | ], 430 | "name": "valuePercentile", 431 | "outputs": [ 432 | { 433 | "name": "_percentile", 434 | "type": "uint256" 435 | } 436 | ], 437 | "payable": false, 438 | "stateMutability": "view", 439 | "type": "function" 440 | }, 441 | { 442 | "inputs": [], 443 | "payable": false, 444 | "stateMutability": "nonpayable", 445 | "type": "constructor" 446 | }, 447 | { 448 | "anonymous": false, 449 | "inputs": [ 450 | { 451 | "indexed": false, 452 | "name": "action", 453 | "type": "string" 454 | }, 455 | { 456 | "indexed": false, 457 | "name": "key", 458 | "type": "bytes32" 459 | }, 460 | { 461 | "indexed": false, 462 | "name": "value", 463 | "type": "uint256" 464 | } 465 | ], 466 | "name": "Log", 467 | "type": "event" 468 | }, 469 | { 470 | "anonymous": false, 471 | "inputs": [ 472 | { 473 | "indexed": false, 474 | "name": "newOwner", 475 | "type": "address" 476 | } 477 | ], 478 | "name": "LogOwnerChanged", 479 | "type": "event" 480 | } 481 | ], 482 | "devdoc": { 483 | "methods": {} 484 | }, 485 | "userdoc": { 486 | "methods": {} 487 | } 488 | }, 489 | "settings": { 490 | "compilationTarget": { 491 | "localhost/contracts/HitchensOrderStatisticsTree.sol": "HitchensOrderStatisticsTree" 492 | }, 493 | "evmVersion": "byzantium", 494 | "libraries": {}, 495 | "optimizer": { 496 | "enabled": false, 497 | "runs": 200 498 | }, 499 | "remappings": [] 500 | }, 501 | "sources": { 502 | "localhost/contracts/HitchensOrderStatisticsTree.sol": { 503 | "keccak256": "0xfb7656d8410937fcbb97bd3e5ca7dbd9fdb2f0a71e64f453951fd8ca36225614", 504 | "urls": [ 505 | "bzzr://31f91f96a242b92e4d5e2a5db93de6faab17c7cf3370089c4c60c38979cf6b76" 506 | ] 507 | }, 508 | "localhost/contracts/Owned.sol": { 509 | "keccak256": "0x7e33ac18d51897110d75d33808f6db9bca46133a839f093f22014fccc3754e0c", 510 | "urls": [ 511 | "bzzr://63ecf788bbe9ed2de96a434fdc4ce104ac6526530acc2e33dfe9667be3da7a30" 512 | ] 513 | } 514 | }, 515 | "version": 1 516 | } -------------------------------------------------------------------------------- /migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | const Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function (deployer) { 4 | deployer.deploy(Migrations); 5 | }; 6 | -------------------------------------------------------------------------------- /migrations/2_deployContracts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Deploy and link libraries and contracts 3 | */ 4 | 5 | const OrderStatisticsTreeLib = artifacts.require("HitchensOrderStatisticsTreeLib"); 6 | const OrderStatisticsTree = artifacts.require("HitchensOrderStatisticsTree"); 7 | 8 | module.exports = async function (deployer) { 9 | await deployer.deploy(OrderStatisticsTreeLib); 10 | await deployer.link(OrderStatisticsTreeLib, OrderStatisticsTree); 11 | await deployer.deploy(OrderStatisticsTree); 12 | } 13 | -------------------------------------------------------------------------------- /test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rob-Hitchens/OrderStatisticsTree/2b3abe6c6dfa7849987cb1794067e466af7ddc19/test/.gitkeep -------------------------------------------------------------------------------- /test/Results.md: -------------------------------------------------------------------------------- 1 | ## steps_1.json 2 | 3 | 4 | Notice 5 | valueRank(276) returns 5 6 | valueRank(290) returns 5 7 | valueKeyCount() returns 43 8 | 9 | ``` 10 | element, rank, rankReal, keycount 11 | 32 1 1986 43 44 12 | 52 2 1946 43 43 13 | 121 3 1885 43 42 14 | 170 4 1839 43 41 15 | 276 5 1836 43 40 16 | 290 5 1836 43 39 17 | 312 6 1823 43 38 18 | 379 7 1822 43 37 19 | 415 8 1800 43 36 20 | 505 9 1719 43 35 21 | 538 10 1701 43 34 22 | 567 11 1632 43 33 23 | 589 12 1580 43 32 24 | 628 13 1574 43 31 25 | 631 14 1462 43 30 26 | 739 15 1323 43 29 27 | 766 16 1276 43 28 28 | 824 17 1229 43 27 29 | 859 18 1174 43 26 30 | 885 19 1112 43 25 31 | 896 20 1014 43 24 32 | 973 21 1005 43 23 33 | 980 22 980 43 22 34 | 1005 23 973 43 21 35 | 1014 24 896 43 20 36 | 1112 25 885 43 19 37 | 1174 26 859 43 18 38 | 1229 27 824 43 17 39 | 1276 28 766 43 16 40 | 1323 29 739 43 15 41 | 1462 30 631 43 14 42 | 1574 31 628 43 13 43 | 1580 32 589 43 12 44 | 1632 33 567 43 11 45 | 1701 34 538 43 10 46 | 1719 35 505 43 9 47 | 1800 36 415 43 8 48 | 1822 37 379 43 7 49 | 1823 38 312 43 6 50 | 1836 39 290 43 5 51 | 1839 40 170 43 4 52 | 1885 41 121 43 3 53 | 1946 42 52 43 2 54 | 1986 43 32 43 1 55 | ``` 56 | 57 | ``` 58 | Tree Properties 59 | Count 43 60 | First 32 61 | Last 1986 62 | Root Value 1276 63 | ``` 64 | 65 | valueAtRank(4) returns 170 66 | valueAtRank(5) returns 290 67 | 68 | ``` 69 | ValueAtRank 70 | element, value, real 71 | 1 32 1986 72 | 2 52 1946 73 | 3 121 1885 74 | 4 170 1839 75 | 5 290 1836 76 | 6 312 1823 77 | ``` 78 | 79 | Notice value 276 is in the tree 80 | 81 | ``` 82 | Node Details, (crawled in order), value, parent, left, right, red, keyCount, count 83 | 32 52 0 0 true 1 1 84 | 52 121 32 0 false 1 2 85 | 121 290 52 276 false 1 4 86 | 170 276 0 0 true 1 1 87 | 276 121 170 0 false 1 1 88 | 290 739 121 415 true 1 14 89 | 312 379 0 0 true 1 1 90 | 379 415 312 0 false 1 2 91 | ``` 92 | 93 | ## steps_2.json 94 | This simply removes the 276 value as the last step 95 | Notic the Count in Tree Properties does not change 96 | 97 | ``` 98 | Tree Properties 99 | Count 43 100 | First 32 101 | Last 1986 102 | Root Value 1276 103 | ``` 104 | 105 | ## steps_3.json 106 | This inserts 276 after the delete which was done in `steps_2.json` 107 | 108 | Tree works as expected 109 | 110 | ``` 111 | Tree Properties 112 | Count 44 113 | First 32 114 | Last 1986 115 | Root Value 1276 116 | ``` 117 | 118 | `valueRank()` works as expected 119 | 120 | ``` 121 | element, rank, rankReal, keycount 122 | 32 1 1986 44 45 123 | 52 2 1946 44 44 124 | 121 3 1885 44 43 125 | 170 4 1839 44 42 126 | 276 5 1836 44 41 127 | 290 6 1823 44 40 128 | 312 7 1822 44 39 129 | 379 8 1800 44 38 130 | ``` 131 | 132 | `valueAtRank()` works as expected 133 | 134 | ``` 135 | ValueAtRank 136 | element, value, real 137 | 1 32 1986 138 | 2 52 1946 139 | 3 121 1885 140 | 4 170 1839 141 | 5 276 1836 142 | 6 290 1823 143 | 7 312 1822 144 | 8 379 1800 145 | ``` 146 | 147 | 148 | -------------------------------------------------------------------------------- /test/count.js: -------------------------------------------------------------------------------- 1 | //const BigNumber = require('big-number'); 2 | const OrderStatisticsTree = artifacts.require("HitchensOrderStatisticsTree.sol"); 3 | const fs = require('fs'); 4 | const scenario1 = 'test/steps_1.json'; 5 | const scenario2 = 'test/steps_2.json'; 6 | const scenario3 = 'test/steps_3.json'; 7 | const showProgress = false; // show steps as the test proceeds 8 | const verbose = false; // output tree state after each step - takes a long time 9 | 10 | contract("OrderStatisticsTree - count", accounts => { 11 | 12 | beforeEach(async () => {; 13 | ost = await OrderStatisticsTree.new(); 14 | }); 15 | 16 | it("should be ready to test", async () => { 17 | assert.strictEqual(true, true, "something is wrong"); 18 | }); 19 | 20 | it("should maintain a correct count at all times - steps_1", async () => { 21 | await testScenario(scenario1); 22 | }); 23 | 24 | it("should maintain a correct count at all times - steps_2", async () => { 25 | await testScenario(scenario2); 26 | }); 27 | 28 | it("should maintain a correct count at all times - steps_3", async () => { 29 | await testScenario(scenario3); 30 | }); 31 | }); 32 | 33 | async function testScenario(testFile) { 34 | let i; 35 | let step; 36 | let isDelete; 37 | let readableAction; 38 | let count = 0; 39 | let treeCount; 40 | let sorted = []; 41 | let before; 42 | let element; 43 | let rank; 44 | let percentile; 45 | let steps = await loadSteps(testFile); 46 | 47 | if(showProgress) console.log(); 48 | if(showProgress) console.log("Scenario:", testFile); 49 | if(showProgress) console.log("Number of steps: "+steps.length); 50 | if(showProgress) console.log("Steps:"); 51 | 52 | for (i=0; i 0) { 126 | node = await ost.getNode(n); 127 | console.log( 128 | n, 129 | node[0].toString(10), 130 | node[1].toString(10), 131 | node[2].toString(10), 132 | node[3], 133 | node[4].toString(10), 134 | node[5].toString(10) 135 | ) 136 | n = await ost.nextValue(n); 137 | n = n.toString(10); 138 | } 139 | return; 140 | } 141 | 142 | async function applyStep(sorted, step) { 143 | let account; 144 | let element; 145 | let removeIndex; 146 | 147 | if(showProgress) console.log(); 148 | if(showProgress) console.log("APPLY STEP", step, '***********************************************************'); 149 | 150 | element = steps[step]["amount"]; 151 | account = steps[step]["address"]; 152 | 153 | if (element > 0) { 154 | if(showProgress) console.log("INSERT:", account, element); 155 | sorted.push(element); 156 | await ost.insertKeyValue(account, element); 157 | } else { 158 | if(showProgress) console.log("DELETE:", account, element); 159 | removeIndex = sorted.indexOf(element*-1); 160 | sorted.splice(removeIndex,1); 161 | await ost.removeKeyValue(account, element*-1); 162 | } 163 | sorted.sort(numeric); 164 | return sorted; 165 | } 166 | 167 | async function loadSteps(scenario) { 168 | let rawdata = fs.readFileSync(scenario); 169 | steps = JSON.parse(rawdata); 170 | return steps 171 | } 172 | 173 | function numeric(a, b) { 174 | return a - b; 175 | } -------------------------------------------------------------------------------- /test/ost.js: -------------------------------------------------------------------------------- 1 | //const BigNumber = require('big-number'); 2 | const OrderStatisticsTree = artifacts.require("HitchensOrderStatisticsTree.sol"); 3 | const fs = require('fs'); 4 | let ost; 5 | let scenarios = []; 6 | 7 | contract("OrderStatisticsTree - sort and rank", accounts => { 8 | 9 | beforeEach(async () => {; 10 | // assert.isAtLeast(accounts.length, 20, "should have at least 20 unlocked, funded accounts"); 11 | ost = await OrderStatisticsTree.new(); 12 | }); 13 | 14 | it("should be ready to test", async () => { 15 | assert.strictEqual(true, true, "something is wrong"); 16 | }); 17 | 18 | it("should process scenario 3", async () => { 19 | let element; 20 | let rank; 21 | let percentile; 22 | let steps = await loadSteps(); 23 | console.log("Number of steps: "+steps.length); 24 | let s = await loadScenario2(steps); 25 | await printScenario(s); 26 | await printExists(steps); 27 | await printComparisonsAt(s); 28 | }); 29 | 30 | }); 31 | 32 | async function loadSteps() { 33 | let rawdata = fs.readFileSync('test/steps_3.json'); 34 | steps = JSON.parse(rawdata); 35 | return steps 36 | } 37 | 38 | async function printExists(s) { 39 | console.log(); 40 | console.log("See if values exists"); 41 | console.log("value, exists"); 42 | for(i=0; i < s.length; i++) { 43 | element = s[i]["amount"]; 44 | if (element > 0){ 45 | exists = await ost.valueExists(element); 46 | console.log(element, exists); 47 | } 48 | } 49 | } 50 | 51 | async function printComparisonsAt(s) { 52 | console.log(); 53 | console.log("ValueAtRank"); 54 | console.log("element, value at rank, value at rank reverse") 55 | for(i=1; i <= s.length; i++) { 56 | value = await ost.valueAtRank(i); 57 | valueR = await ost.valueAtRankReverse(i); 58 | console.log(i, value.toString(), valueR.toString()); 59 | } 60 | } 61 | 62 | /* 63 | async function printComparisons(s) { 64 | let first; 65 | let last; 66 | let rank; 67 | let rankReal; 68 | let percentile; 69 | let i; 70 | let element; 71 | 72 | // print stats for elements not in the set 73 | last = await ost.lastValue(); 74 | last = last.toString(10); 75 | console.log(); 76 | console.log("Explore values not in the set"); 77 | console.log("value, rank, rankReal, percentile, is above last value") 78 | for(i=start; i < stop; i += increment) { 79 | rank = await ost.valueRank(i); 80 | rankReal = await ost.valueAtRankReverse(i); 81 | percentile = await ost.valuePercentile(i); 82 | rank = rank.toString(10); 83 | percentile = percentile.toString(10); 84 | overMax = i > parseInt(last); 85 | console.log(i, rank, rankReal.toString(), percentile, overMax); 86 | } 87 | 88 | } 89 | */ 90 | 91 | async function printScenario(s) { 92 | let count; 93 | let first; 94 | let last; 95 | let rootVal; 96 | let n; 97 | let node; 98 | let keyCount; 99 | let inside; 100 | 101 | // enumerate the sorted list and stats 102 | console.log("element, rank, rankReal, keycount") 103 | for(i=0; i < s.length; i++) { 104 | element = s[i]; 105 | rank = await ost.valueRank(element); 106 | rank = rank.toString(10); 107 | rankReal = await ost.valueAtRankReverse(rank); 108 | rankReal = rankReal.toString(10); 109 | // percentile = await ost.valuePercentile(element); 110 | // percentile = percentile.toString(10); 111 | keyCount = await ost.valueKeyCount(); 112 | inside = keyCount - (i - 1); 113 | console.log(element, rank, rankReal, keyCount.toString(10),inside.toString(10)); 114 | } 115 | 116 | // tree structure summary 117 | console.log(); 118 | console.log("Tree Properties"); 119 | count = await ost.valueKeyCount(); 120 | first = await ost.firstValue(); 121 | last = await ost.lastValue(); 122 | rootVal = await ost.treeRootNode(); 123 | 124 | count = count.toString(10); 125 | first = first.toString(10); 126 | last = last.toString(10); 127 | rootVal = rootVal.toString(10); 128 | 129 | console.log("Count", count); 130 | console.log("First", first); 131 | console.log("Last", last); 132 | console.log("Root Value", rootVal); 133 | 134 | // enumerate the node contents 135 | console.log(); 136 | console.log("Node Details, (crawled in order), value, parent, left, right, red, keyCount, count"); 137 | 138 | n = first; 139 | while(parseInt(n) > 0) { 140 | node = await ost.getNode(n); 141 | console.log( 142 | n, 143 | node[0].toString(10), 144 | node[1].toString(10), 145 | node[2].toString(10), 146 | node[3], 147 | node[4].toString(10), 148 | node[5].toString(10) 149 | ) 150 | n = await ost.nextValue(n); 151 | n = n.toString(10); 152 | } 153 | } 154 | 155 | async function loadScenario(index, accounts) { 156 | const s = scenarios[0]; 157 | let sorted = []; 158 | let account = accounts[0]; // we don't think we're concerned with unique users/keys (yet) so everything will be user 0 159 | let element; 160 | let removeIndex; 161 | 162 | // inserts 163 | for(i=0; i < s.ins.length; i++) { 164 | element = s.ins[i]; 165 | sorted.push(element); 166 | await ost.insertKeyValue(account, element); 167 | } 168 | 169 | // deletes 170 | for(i=0; i < s.del.length; i++) { 171 | element = s.del[i]; 172 | removeIndex = sorted.indexOf(element); 173 | sorted.splice(removeIndex, 1); 174 | await ost.removeKeyValue(account, element); 175 | } 176 | //sort it and return 177 | sorted.sort(numeric); 178 | return sorted; 179 | } 180 | 181 | async function loadScenario1(index, accounts) { 182 | let account = accounts[0]; 183 | let element; 184 | let sorted = []; 185 | let removeIndex; 186 | 187 | for(i=0; i < scenario1.length; i++) { 188 | element = scenario1[i]; 189 | account = accounts[accountMap[i]]; 190 | if (element > 0) { 191 | sorted.push(element); 192 | console.log(account,element); 193 | await ost.insertKeyValue(account, element); 194 | } else { 195 | removeIndex = sorted.indexOf(element*-1); 196 | sorted.splice(removeIndex,1); 197 | console.log(account, element); 198 | await ost.removeKeyValue(account, element*-1); 199 | } 200 | } 201 | sorted.sort(numeric); 202 | return sorted; 203 | } 204 | 205 | async function loadScenario2(steps) { 206 | let account; 207 | let element; 208 | let sorted = []; 209 | let removeIndex; 210 | 211 | for(i=0; i < steps.length; i++) { 212 | element = steps[i]["amount"]; 213 | account = steps[i]["address"]; 214 | if (element > 0) { 215 | sorted.push(element); 216 | await ost.insertKeyValue(account, element); 217 | } else { 218 | removeIndex = sorted.indexOf(element*-1); 219 | sorted.splice(removeIndex,1); 220 | await ost.removeKeyValue(account, element*-1); 221 | } 222 | } 223 | sorted.sort(numeric); 224 | return sorted; 225 | } 226 | 227 | function numeric(a, b) { 228 | return a - b; 229 | } -------------------------------------------------------------------------------- /test/steps_1.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 4 | "blockNumber": 22070574, 5 | "action": "insert", 6 | "amount": 4000000000000, 7 | "pid": 0 8 | }, 9 | { 10 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 11 | "blockNumber": 22071253, 12 | "action": "insert", 13 | "amount": 100, 14 | "pid": 0 15 | }, 16 | { 17 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 18 | "blockNumber": 22071270, 19 | "action": "insert", 20 | "amount": 622, 21 | "pid": 0 22 | }, 23 | { 24 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 25 | "blockNumber": 22071279, 26 | "action": "insert", 27 | "amount": 725, 28 | "pid": 0 29 | }, 30 | { 31 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 32 | "blockNumber": 22071283, 33 | "action": "insert", 34 | "amount": 1477, 35 | "pid": 0 36 | }, 37 | { 38 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 39 | "blockNumber": 22071286, 40 | "action": "insert", 41 | "amount": 616, 42 | "pid": 0 43 | }, 44 | { 45 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 46 | "blockNumber": 22071289, 47 | "action": "insert", 48 | "amount": 1465, 49 | "pid": 0 50 | }, 51 | { 52 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 53 | "blockNumber": 22071294, 54 | "action": "insert", 55 | "amount": 1799, 56 | "pid": 0 57 | }, 58 | { 59 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 60 | "blockNumber": 22071301, 61 | "action": "insert", 62 | "amount": 1243, 63 | "pid": 0 64 | }, 65 | { 66 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 67 | "blockNumber": 22071308, 68 | "action": "insert", 69 | "amount": 1797, 70 | "pid": 0 71 | }, 72 | { 73 | "address": "0xa626Aef7c0dD74c825b786166b00929388c568e9", 74 | "blockNumber": 22071318, 75 | "action": "insert", 76 | "amount": 739, 77 | "pid": 0 78 | }, 79 | { 80 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 81 | "blockNumber": 22071326, 82 | "action": "insert", 83 | "amount": 1803, 84 | "pid": 0 85 | }, 86 | { 87 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 88 | "blockNumber": 22071335, 89 | "action": "insert", 90 | "amount": 1515, 91 | "pid": 0 92 | }, 93 | { 94 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 95 | "blockNumber": 22071342, 96 | "action": "insert", 97 | "amount": 250, 98 | "pid": 0 99 | }, 100 | { 101 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 102 | "blockNumber": 22071344, 103 | "action": "insert", 104 | "amount": 724, 105 | "pid": 0 106 | }, 107 | { 108 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 109 | "blockNumber": 22071350, 110 | "action": "insert", 111 | "amount": 355, 112 | "pid": 0 113 | }, 114 | { 115 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 116 | "blockNumber": 22071353, 117 | "action": "insert", 118 | "amount": 759, 119 | "pid": 0 120 | }, 121 | { 122 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 123 | "blockNumber": 22071362, 124 | "action": "insert", 125 | "amount": 585, 126 | "pid": 0 127 | }, 128 | { 129 | "address": "0x1814EE97caA322D7aeAdCF419f47B31FA03A4fc6", 130 | "blockNumber": 22071368, 131 | "action": "insert", 132 | "amount": 1276, 133 | "pid": 0 134 | }, 135 | { 136 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 137 | "blockNumber": 22071375, 138 | "action": "insert", 139 | "amount": 1399, 140 | "pid": 0 141 | }, 142 | { 143 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 144 | "blockNumber": 22071377, 145 | "action": "insert", 146 | "amount": 547, 147 | "pid": 0 148 | }, 149 | { 150 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 151 | "blockNumber": 22071382, 152 | "action": "insert", 153 | "amount": 865, 154 | "pid": 0 155 | }, 156 | { 157 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 158 | "blockNumber": 22071387, 159 | "action": "delete", 160 | "amount": -1477, 161 | "pid": 0 162 | }, 163 | { 164 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 165 | "blockNumber": 22071388, 166 | "action": "insert", 167 | "amount": 486, 168 | "pid": 0 169 | }, 170 | { 171 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 172 | "blockNumber": 22071394, 173 | "action": "delete", 174 | "amount": -622, 175 | "pid": 0 176 | }, 177 | { 178 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 179 | "blockNumber": 22071395, 180 | "action": "insert", 181 | "amount": 1261, 182 | "pid": 0 183 | }, 184 | { 185 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 186 | "blockNumber": 22071402, 187 | "action": "delete", 188 | "amount": -759, 189 | "pid": 0 190 | }, 191 | { 192 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 193 | "blockNumber": 22071403, 194 | "action": "insert", 195 | "amount": 337, 196 | "pid": 0 197 | }, 198 | { 199 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 200 | "blockNumber": 22071408, 201 | "action": "delete", 202 | "amount": -1799, 203 | "pid": 0 204 | }, 205 | { 206 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 207 | "blockNumber": 22071409, 208 | "action": "insert", 209 | "amount": 1823, 210 | "pid": 0 211 | }, 212 | { 213 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 214 | "blockNumber": 22071411, 215 | "action": "insert", 216 | "amount": 1784, 217 | "pid": 0 218 | }, 219 | { 220 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 221 | "blockNumber": 22071415, 222 | "action": "delete", 223 | "amount": -355, 224 | "pid": 0 225 | }, 226 | { 227 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 228 | "blockNumber": 22071416, 229 | "action": "insert", 230 | "amount": 1604, 231 | "pid": 0 232 | }, 233 | { 234 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 235 | "blockNumber": 22071417, 236 | "action": "delete", 237 | "amount": -1797, 238 | "pid": 0 239 | }, 240 | { 241 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 242 | "blockNumber": 22071419, 243 | "action": "insert", 244 | "amount": 1469, 245 | "pid": 0 246 | }, 247 | { 248 | "address": "0xaB7c029B605A79c95067D31A5eac5037DE867Ab4", 249 | "blockNumber": 22071421, 250 | "action": "insert", 251 | "amount": 1719, 252 | "pid": 0 253 | }, 254 | { 255 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 256 | "blockNumber": 22071428, 257 | "action": "insert", 258 | "amount": 804, 259 | "pid": 0 260 | }, 261 | { 262 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 263 | "blockNumber": 22071433, 264 | "action": "insert", 265 | "amount": 47, 266 | "pid": 0 267 | }, 268 | { 269 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 270 | "blockNumber": 22071441, 271 | "action": "delete", 272 | "amount": -547, 273 | "pid": 0 274 | }, 275 | { 276 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 277 | "blockNumber": 22071443, 278 | "action": "insert", 279 | "amount": 272, 280 | "pid": 0 281 | }, 282 | { 283 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 284 | "blockNumber": 22071450, 285 | "action": "delete", 286 | "amount": -585, 287 | "pid": 0 288 | }, 289 | { 290 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 291 | "blockNumber": 22071451, 292 | "action": "insert", 293 | "amount": 1505, 294 | "pid": 0 295 | }, 296 | { 297 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 298 | "blockNumber": 22071453, 299 | "action": "delete", 300 | "amount": -337, 301 | "pid": 0 302 | }, 303 | { 304 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 305 | "blockNumber": 22071454, 306 | "action": "insert", 307 | "amount": 143, 308 | "pid": 0 309 | }, 310 | { 311 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 312 | "blockNumber": 22071456, 313 | "action": "delete", 314 | "amount": -1243, 315 | "pid": 0 316 | }, 317 | { 318 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 319 | "blockNumber": 22071458, 320 | "action": "insert", 321 | "amount": 705, 322 | "pid": 0 323 | }, 324 | { 325 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 326 | "blockNumber": 22071464, 327 | "action": "delete", 328 | "amount": -250, 329 | "pid": 0 330 | }, 331 | { 332 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 333 | "blockNumber": 22071465, 334 | "action": "insert", 335 | "amount": 290, 336 | "pid": 0 337 | }, 338 | { 339 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 340 | "blockNumber": 22071469, 341 | "action": "insert", 342 | "amount": 1298, 343 | "pid": 0 344 | }, 345 | { 346 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 347 | "blockNumber": 22071476, 348 | "action": "delete", 349 | "amount": -865, 350 | "pid": 0 351 | }, 352 | { 353 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 354 | "blockNumber": 22071477, 355 | "action": "insert", 356 | "amount": 1836, 357 | "pid": 0 358 | }, 359 | { 360 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 361 | "blockNumber": 22071481, 362 | "action": "delete", 363 | "amount": -1604, 364 | "pid": 0 365 | }, 366 | { 367 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 368 | "blockNumber": 22071482, 369 | "action": "insert", 370 | "amount": 1080, 371 | "pid": 0 372 | }, 373 | { 374 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 375 | "blockNumber": 22071483, 376 | "action": "delete", 377 | "amount": -100, 378 | "pid": 0 379 | }, 380 | { 381 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 382 | "blockNumber": 22071483, 383 | "action": "insert", 384 | "amount": 1837, 385 | "pid": 0 386 | }, 387 | { 388 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 389 | "blockNumber": 22071483, 390 | "action": "delete", 391 | "amount": -47, 392 | "pid": 0 393 | }, 394 | { 395 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 396 | "blockNumber": 22071484, 397 | "action": "insert", 398 | "amount": 587, 399 | "pid": 0 400 | }, 401 | { 402 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 403 | "blockNumber": 22071488, 404 | "action": "delete", 405 | "amount": -1505, 406 | "pid": 0 407 | }, 408 | { 409 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 410 | "blockNumber": 22071489, 411 | "action": "insert", 412 | "amount": 410, 413 | "pid": 0 414 | }, 415 | { 416 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 417 | "blockNumber": 22071493, 418 | "action": "delete", 419 | "amount": -1837, 420 | "pid": 0 421 | }, 422 | { 423 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 424 | "blockNumber": 22071493, 425 | "action": "insert", 426 | "amount": 1838, 427 | "pid": 0 428 | }, 429 | { 430 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 431 | "blockNumber": 22071493, 432 | "action": "delete", 433 | "amount": -804, 434 | "pid": 0 435 | }, 436 | { 437 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 438 | "blockNumber": 22071494, 439 | "action": "insert", 440 | "amount": 499, 441 | "pid": 0 442 | }, 443 | { 444 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 445 | "blockNumber": 22071498, 446 | "action": "delete", 447 | "amount": -705, 448 | "pid": 0 449 | }, 450 | { 451 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 452 | "blockNumber": 22071499, 453 | "action": "insert", 454 | "amount": 1195, 455 | "pid": 0 456 | }, 457 | { 458 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 459 | "blockNumber": 22071501, 460 | "action": "delete", 461 | "amount": -1261, 462 | "pid": 0 463 | }, 464 | { 465 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 466 | "blockNumber": 22071502, 467 | "action": "insert", 468 | "amount": 1016, 469 | "pid": 0 470 | }, 471 | { 472 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 473 | "blockNumber": 22071503, 474 | "action": "delete", 475 | "amount": -1838, 476 | "pid": 0 477 | }, 478 | { 479 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 480 | "blockNumber": 22071503, 481 | "action": "insert", 482 | "amount": 1839, 483 | "pid": 0 484 | }, 485 | { 486 | "address": "0xa28Ea741aE38476172a5D8DcB4AA564f2b14c385", 487 | "blockNumber": 22071509, 488 | "action": "insert", 489 | "amount": 1005, 490 | "pid": 0 491 | }, 492 | { 493 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 494 | "blockNumber": 22071512, 495 | "action": "delete", 496 | "amount": -587, 497 | "pid": 0 498 | }, 499 | { 500 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 501 | "blockNumber": 22071513, 502 | "action": "insert", 503 | "amount": 1974, 504 | "pid": 0 505 | }, 506 | { 507 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 508 | "blockNumber": 22071517, 509 | "action": "insert", 510 | "amount": 1221, 511 | "pid": 0 512 | }, 513 | { 514 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 515 | "blockNumber": 22071518, 516 | "action": "delete", 517 | "amount": -1195, 518 | "pid": 0 519 | }, 520 | { 521 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 522 | "blockNumber": 22071519, 523 | "action": "insert", 524 | "amount": 805, 525 | "pid": 0 526 | }, 527 | { 528 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 529 | "blockNumber": 22071526, 530 | "action": "delete", 531 | "amount": -1221, 532 | "pid": 0 533 | }, 534 | { 535 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 536 | "blockNumber": 22071527, 537 | "action": "insert", 538 | "amount": 726, 539 | "pid": 0 540 | }, 541 | { 542 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 543 | "blockNumber": 22071535, 544 | "action": "delete", 545 | "amount": -486, 546 | "pid": 0 547 | }, 548 | { 549 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 550 | "blockNumber": 22071536, 551 | "action": "insert", 552 | "amount": 2000, 553 | "pid": 0 554 | }, 555 | { 556 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 557 | "blockNumber": 22071540, 558 | "action": "delete", 559 | "amount": -805, 560 | "pid": 0 561 | }, 562 | { 563 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 564 | "blockNumber": 22071541, 565 | "action": "insert", 566 | "amount": 218, 567 | "pid": 0 568 | }, 569 | { 570 | "address": "0x84e2067FEd32F9172168593621b03D5E2Fdb9EDF", 571 | "blockNumber": 22071550, 572 | "action": "insert", 573 | "amount": 766, 574 | "pid": 0 575 | }, 576 | { 577 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 578 | "blockNumber": 22071555, 579 | "action": "delete", 580 | "amount": -616, 581 | "pid": 0 582 | }, 583 | { 584 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 585 | "blockNumber": 22071556, 586 | "action": "insert", 587 | "amount": 1946, 588 | "pid": 0 589 | }, 590 | { 591 | "address": "0x0908e7bcb1534e327724E302D468976fe83bB1E5", 592 | "blockNumber": 22071564, 593 | "action": "insert", 594 | "amount": 32, 595 | "pid": 0 596 | }, 597 | { 598 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 599 | "blockNumber": 22071573, 600 | "action": "delete", 601 | "amount": -1469, 602 | "pid": 0 603 | }, 604 | { 605 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 606 | "blockNumber": 22071575, 607 | "action": "insert", 608 | "amount": 892, 609 | "pid": 0 610 | }, 611 | { 612 | "address": "0x01FA4BFfec396C336d1574c4c22d0B9cb5671647", 613 | "blockNumber": 22071582, 614 | "action": "insert", 615 | "amount": 121, 616 | "pid": 0 617 | }, 618 | { 619 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 620 | "blockNumber": 22071587, 621 | "action": "insert", 622 | "amount": 781, 623 | "pid": 0 624 | }, 625 | { 626 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 627 | "blockNumber": 22071591, 628 | "action": "delete", 629 | "amount": -218, 630 | "pid": 0 631 | }, 632 | { 633 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 634 | "blockNumber": 22071592, 635 | "action": "insert", 636 | "amount": 973, 637 | "pid": 0 638 | }, 639 | { 640 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 641 | "blockNumber": 22071600, 642 | "action": "insert", 643 | "amount": 619, 644 | "pid": 0 645 | }, 646 | { 647 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 648 | "blockNumber": 22071605, 649 | "action": "delete", 650 | "amount": -726, 651 | "pid": 0 652 | }, 653 | { 654 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 655 | "blockNumber": 22071612, 656 | "action": "insert", 657 | "amount": 763, 658 | "pid": 0 659 | }, 660 | { 661 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 662 | "blockNumber": 22071622, 663 | "action": "delete", 664 | "amount": -724, 665 | "pid": 0 666 | }, 667 | { 668 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 669 | "blockNumber": 22071624, 670 | "action": "insert", 671 | "amount": 170, 672 | "pid": 0 673 | }, 674 | { 675 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 676 | "blockNumber": 22071632, 677 | "action": "insert", 678 | "amount": 231, 679 | "pid": 0 680 | }, 681 | { 682 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 683 | "blockNumber": 22071639, 684 | "action": "delete", 685 | "amount": -725, 686 | "pid": 0 687 | }, 688 | { 689 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 690 | "blockNumber": 22071640, 691 | "action": "insert", 692 | "amount": 1229, 693 | "pid": 0 694 | }, 695 | { 696 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 697 | "blockNumber": 22071648, 698 | "action": "delete", 699 | "amount": -272, 700 | "pid": 0 701 | }, 702 | { 703 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 704 | "blockNumber": 22071649, 705 | "action": "insert", 706 | "amount": 824, 707 | "pid": 0 708 | }, 709 | { 710 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 711 | "blockNumber": 22071654, 712 | "action": "delete", 713 | "amount": -892, 714 | "pid": 0 715 | }, 716 | { 717 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 718 | "blockNumber": 22071655, 719 | "action": "insert", 720 | "amount": 343, 721 | "pid": 0 722 | }, 723 | { 724 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 725 | "blockNumber": 22071657, 726 | "action": "insert", 727 | "amount": 758, 728 | "pid": 0 729 | }, 730 | { 731 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 732 | "blockNumber": 22071661, 733 | "action": "insert", 734 | "amount": 261, 735 | "pid": 0 736 | }, 737 | { 738 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 739 | "blockNumber": 22071669, 740 | "action": "insert", 741 | "amount": 1881, 742 | "pid": 0 743 | }, 744 | { 745 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 746 | "blockNumber": 22071674, 747 | "action": "delete", 748 | "amount": -499, 749 | "pid": 0 750 | }, 751 | { 752 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 753 | "blockNumber": 22071676, 754 | "action": "insert", 755 | "amount": 1255, 756 | "pid": 0 757 | }, 758 | { 759 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 760 | "blockNumber": 22071679, 761 | "action": "delete", 762 | "amount": -261, 763 | "pid": 0 764 | }, 765 | { 766 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 767 | "blockNumber": 22071680, 768 | "action": "insert", 769 | "amount": 1701, 770 | "pid": 0 771 | }, 772 | { 773 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 774 | "blockNumber": 22071684, 775 | "action": "delete", 776 | "amount": -1784, 777 | "pid": 0 778 | }, 779 | { 780 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 781 | "blockNumber": 22071685, 782 | "action": "insert", 783 | "amount": 415, 784 | "pid": 0 785 | }, 786 | { 787 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 788 | "blockNumber": 22071690, 789 | "action": "delete", 790 | "amount": -143, 791 | "pid": 0 792 | }, 793 | { 794 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 795 | "blockNumber": 22071691, 796 | "action": "insert", 797 | "amount": 379, 798 | "pid": 0 799 | }, 800 | { 801 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 802 | "blockNumber": 22071693, 803 | "action": "delete", 804 | "amount": -1016, 805 | "pid": 0 806 | }, 807 | { 808 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 809 | "blockNumber": 22071694, 810 | "action": "insert", 811 | "amount": 1112, 812 | "pid": 0 813 | }, 814 | { 815 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 816 | "blockNumber": 22071695, 817 | "action": "delete", 818 | "amount": -1515, 819 | "pid": 0 820 | }, 821 | { 822 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 823 | "blockNumber": 22071696, 824 | "action": "insert", 825 | "amount": 1986, 826 | "pid": 0 827 | }, 828 | { 829 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 830 | "blockNumber": 22071701, 831 | "action": "delete", 832 | "amount": -1298, 833 | "pid": 0 834 | }, 835 | { 836 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 837 | "blockNumber": 22071703, 838 | "action": "insert", 839 | "amount": 57, 840 | "pid": 0 841 | }, 842 | { 843 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 844 | "blockNumber": 22071706, 845 | "action": "delete", 846 | "amount": -1974, 847 | "pid": 0 848 | }, 849 | { 850 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 851 | "blockNumber": 22071708, 852 | "action": "insert", 853 | "amount": 1580, 854 | "pid": 0 855 | }, 856 | { 857 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 858 | "blockNumber": 22071709, 859 | "action": "delete", 860 | "amount": -1465, 861 | "pid": 0 862 | }, 863 | { 864 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 865 | "blockNumber": 22071710, 866 | "action": "insert", 867 | "amount": 1323, 868 | "pid": 0 869 | }, 870 | { 871 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 872 | "blockNumber": 22071718, 873 | "action": "delete", 874 | "amount": -4000000000000, 875 | "pid": 0 876 | }, 877 | { 878 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 879 | "blockNumber": 22071718, 880 | "action": "delete", 881 | "amount": -2000, 882 | "pid": 0 883 | }, 884 | { 885 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 886 | "blockNumber": 22071719, 887 | "action": "insert", 888 | "amount": 1093, 889 | "pid": 0 890 | }, 891 | { 892 | "address": "0x661d800966A44F7bce2856412a4c21b1287DB9Ca", 893 | "blockNumber": 22071725, 894 | "action": "insert", 895 | "amount": 1174, 896 | "pid": 0 897 | }, 898 | { 899 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 900 | "blockNumber": 22071730, 901 | "action": "delete", 902 | "amount": -343, 903 | "pid": 0 904 | }, 905 | { 906 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 907 | "blockNumber": 22071732, 908 | "action": "insert", 909 | "amount": 1822, 910 | "pid": 0 911 | }, 912 | { 913 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 914 | "blockNumber": 22071739, 915 | "action": "delete", 916 | "amount": -1093, 917 | "pid": 0 918 | }, 919 | { 920 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 921 | "blockNumber": 22071740, 922 | "action": "insert", 923 | "amount": 859, 924 | "pid": 0 925 | }, 926 | { 927 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 928 | "blockNumber": 22071747, 929 | "action": "delete", 930 | "amount": -410, 931 | "pid": 0 932 | }, 933 | { 934 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 935 | "blockNumber": 22071748, 936 | "action": "insert", 937 | "amount": 276, 938 | "pid": 0 939 | }, 940 | { 941 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 942 | "blockNumber": 22071754, 943 | "action": "delete", 944 | "amount": -231, 945 | "pid": 0 946 | }, 947 | { 948 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 949 | "blockNumber": 22071755, 950 | "action": "insert", 951 | "amount": 1462, 952 | "pid": 0 953 | }, 954 | { 955 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 956 | "blockNumber": 22071759, 957 | "action": "delete", 958 | "amount": -763, 959 | "pid": 0 960 | }, 961 | { 962 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 963 | "blockNumber": 22071760, 964 | "action": "insert", 965 | "amount": 1800, 966 | "pid": 0 967 | }, 968 | { 969 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 970 | "blockNumber": 22071762, 971 | "action": "delete", 972 | "amount": -758, 973 | "pid": 0 974 | }, 975 | { 976 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 977 | "blockNumber": 22071763, 978 | "action": "insert", 979 | "amount": 202, 980 | "pid": 0 981 | }, 982 | { 983 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 984 | "blockNumber": 22071768, 985 | "action": "delete", 986 | "amount": -1080, 987 | "pid": 0 988 | }, 989 | { 990 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 991 | "blockNumber": 22071769, 992 | "action": "insert", 993 | "amount": 796, 994 | "pid": 0 995 | }, 996 | { 997 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 998 | "blockNumber": 22071773, 999 | "action": "insert", 1000 | "amount": 971, 1001 | "pid": 0 1002 | }, 1003 | { 1004 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 1005 | "blockNumber": 22071777, 1006 | "action": "delete", 1007 | "amount": -202, 1008 | "pid": 0 1009 | }, 1010 | { 1011 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 1012 | "blockNumber": 22071778, 1013 | "action": "insert", 1014 | "amount": 1885, 1015 | "pid": 0 1016 | }, 1017 | { 1018 | "address": "0x2C13e81C1B3341a6417CE4E67d9789e94701590d", 1019 | "blockNumber": 22071785, 1020 | "action": "insert", 1021 | "amount": 589, 1022 | "pid": 0 1023 | }, 1024 | { 1025 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 1026 | "blockNumber": 22071791, 1027 | "action": "delete", 1028 | "amount": -781, 1029 | "pid": 0 1030 | }, 1031 | { 1032 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 1033 | "blockNumber": 22071793, 1034 | "action": "insert", 1035 | "amount": 52, 1036 | "pid": 0 1037 | }, 1038 | { 1039 | "address": "0xdFcd31F1950EcE39d8b6A597742D33151A49C4b8", 1040 | "blockNumber": 22071795, 1041 | "action": "insert", 1042 | "amount": 505, 1043 | "pid": 0 1044 | }, 1045 | { 1046 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 1047 | "blockNumber": 22071797, 1048 | "action": "delete", 1049 | "amount": -1803, 1050 | "pid": 0 1051 | }, 1052 | { 1053 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 1054 | "blockNumber": 22071798, 1055 | "action": "insert", 1056 | "amount": 1014, 1057 | "pid": 0 1058 | }, 1059 | { 1060 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 1061 | "blockNumber": 22071799, 1062 | "action": "delete", 1063 | "amount": -971, 1064 | "pid": 0 1065 | }, 1066 | { 1067 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 1068 | "blockNumber": 22071800, 1069 | "action": "insert", 1070 | "amount": 567, 1071 | "pid": 0 1072 | }, 1073 | { 1074 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 1075 | "blockNumber": 22071804, 1076 | "action": "delete", 1077 | "amount": -57, 1078 | "pid": 0 1079 | }, 1080 | { 1081 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 1082 | "blockNumber": 22071805, 1083 | "action": "insert", 1084 | "amount": 312, 1085 | "pid": 0 1086 | }, 1087 | { 1088 | "address": "0x0fff6131a6c7688048BfD5cB8aF9d56659fd4fb5", 1089 | "blockNumber": 22071812, 1090 | "action": "insert", 1091 | "amount": 538, 1092 | "pid": 0 1093 | }, 1094 | { 1095 | "address": "0x1Df37751FAcadDF647352f7008E48a514B5dB1c9", 1096 | "blockNumber": 22071818, 1097 | "action": "insert", 1098 | "amount": 980, 1099 | "pid": 0 1100 | }, 1101 | { 1102 | "address": "0x05911d66EF445C5E6a205A98d394Ff3AcBC3253E", 1103 | "blockNumber": 22071826, 1104 | "action": "insert", 1105 | "amount": 1574, 1106 | "pid": 0 1107 | }, 1108 | { 1109 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 1110 | "blockNumber": 22071830, 1111 | "action": "delete", 1112 | "amount": -1399, 1113 | "pid": 0 1114 | }, 1115 | { 1116 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 1117 | "blockNumber": 22071831, 1118 | "action": "insert", 1119 | "amount": 631, 1120 | "pid": 0 1121 | }, 1122 | { 1123 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 1124 | "blockNumber": 22071837, 1125 | "action": "delete", 1126 | "amount": -796, 1127 | "pid": 0 1128 | }, 1129 | { 1130 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 1131 | "blockNumber": 22071838, 1132 | "action": "insert", 1133 | "amount": 885, 1134 | "pid": 0 1135 | }, 1136 | { 1137 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 1138 | "blockNumber": 22071845, 1139 | "action": "delete", 1140 | "amount": -619, 1141 | "pid": 0 1142 | }, 1143 | { 1144 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 1145 | "blockNumber": 22071846, 1146 | "action": "insert", 1147 | "amount": 896, 1148 | "pid": 0 1149 | }, 1150 | { 1151 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 1152 | "blockNumber": 22071857, 1153 | "action": "insert", 1154 | "amount": 130000000000, 1155 | "pid": 0 1156 | }, 1157 | { 1158 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 1159 | "blockNumber": 22072266, 1160 | "action": "delete", 1161 | "amount": -1255, 1162 | "pid": 0 1163 | }, 1164 | { 1165 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 1166 | "blockNumber": 22072267, 1167 | "action": "insert", 1168 | "amount": 1632, 1169 | "pid": 0 1170 | }, 1171 | { 1172 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 1173 | "blockNumber": 22072280, 1174 | "action": "delete", 1175 | "amount": -1881, 1176 | "pid": 0 1177 | }, 1178 | { 1179 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 1180 | "blockNumber": 22072282, 1181 | "action": "insert", 1182 | "amount": 628, 1183 | "pid": 0 1184 | }, 1185 | { 1186 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 1187 | "blockNumber": 22080736, 1188 | "action": "delete", 1189 | "amount": -130000000000, 1190 | "pid": 0 1191 | } 1192 | ] -------------------------------------------------------------------------------- /test/steps_2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 4 | "blockNumber": 22070574, 5 | "action": "insert", 6 | "amount": 4000000000000, 7 | "pid": 0 8 | }, 9 | { 10 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 11 | "blockNumber": 22071253, 12 | "action": "insert", 13 | "amount": 100, 14 | "pid": 0 15 | }, 16 | { 17 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 18 | "blockNumber": 22071270, 19 | "action": "insert", 20 | "amount": 622, 21 | "pid": 0 22 | }, 23 | { 24 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 25 | "blockNumber": 22071279, 26 | "action": "insert", 27 | "amount": 725, 28 | "pid": 0 29 | }, 30 | { 31 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 32 | "blockNumber": 22071283, 33 | "action": "insert", 34 | "amount": 1477, 35 | "pid": 0 36 | }, 37 | { 38 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 39 | "blockNumber": 22071286, 40 | "action": "insert", 41 | "amount": 616, 42 | "pid": 0 43 | }, 44 | { 45 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 46 | "blockNumber": 22071289, 47 | "action": "insert", 48 | "amount": 1465, 49 | "pid": 0 50 | }, 51 | { 52 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 53 | "blockNumber": 22071294, 54 | "action": "insert", 55 | "amount": 1799, 56 | "pid": 0 57 | }, 58 | { 59 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 60 | "blockNumber": 22071301, 61 | "action": "insert", 62 | "amount": 1243, 63 | "pid": 0 64 | }, 65 | { 66 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 67 | "blockNumber": 22071308, 68 | "action": "insert", 69 | "amount": 1797, 70 | "pid": 0 71 | }, 72 | { 73 | "address": "0xa626Aef7c0dD74c825b786166b00929388c568e9", 74 | "blockNumber": 22071318, 75 | "action": "insert", 76 | "amount": 739, 77 | "pid": 0 78 | }, 79 | { 80 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 81 | "blockNumber": 22071326, 82 | "action": "insert", 83 | "amount": 1803, 84 | "pid": 0 85 | }, 86 | { 87 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 88 | "blockNumber": 22071335, 89 | "action": "insert", 90 | "amount": 1515, 91 | "pid": 0 92 | }, 93 | { 94 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 95 | "blockNumber": 22071342, 96 | "action": "insert", 97 | "amount": 250, 98 | "pid": 0 99 | }, 100 | { 101 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 102 | "blockNumber": 22071344, 103 | "action": "insert", 104 | "amount": 724, 105 | "pid": 0 106 | }, 107 | { 108 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 109 | "blockNumber": 22071350, 110 | "action": "insert", 111 | "amount": 355, 112 | "pid": 0 113 | }, 114 | { 115 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 116 | "blockNumber": 22071353, 117 | "action": "insert", 118 | "amount": 759, 119 | "pid": 0 120 | }, 121 | { 122 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 123 | "blockNumber": 22071362, 124 | "action": "insert", 125 | "amount": 585, 126 | "pid": 0 127 | }, 128 | { 129 | "address": "0x1814EE97caA322D7aeAdCF419f47B31FA03A4fc6", 130 | "blockNumber": 22071368, 131 | "action": "insert", 132 | "amount": 1276, 133 | "pid": 0 134 | }, 135 | { 136 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 137 | "blockNumber": 22071375, 138 | "action": "insert", 139 | "amount": 1399, 140 | "pid": 0 141 | }, 142 | { 143 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 144 | "blockNumber": 22071377, 145 | "action": "insert", 146 | "amount": 547, 147 | "pid": 0 148 | }, 149 | { 150 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 151 | "blockNumber": 22071382, 152 | "action": "insert", 153 | "amount": 865, 154 | "pid": 0 155 | }, 156 | { 157 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 158 | "blockNumber": 22071387, 159 | "action": "delete", 160 | "amount": -1477, 161 | "pid": 0 162 | }, 163 | { 164 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 165 | "blockNumber": 22071388, 166 | "action": "insert", 167 | "amount": 486, 168 | "pid": 0 169 | }, 170 | { 171 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 172 | "blockNumber": 22071394, 173 | "action": "delete", 174 | "amount": -622, 175 | "pid": 0 176 | }, 177 | { 178 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 179 | "blockNumber": 22071395, 180 | "action": "insert", 181 | "amount": 1261, 182 | "pid": 0 183 | }, 184 | { 185 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 186 | "blockNumber": 22071402, 187 | "action": "delete", 188 | "amount": -759, 189 | "pid": 0 190 | }, 191 | { 192 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 193 | "blockNumber": 22071403, 194 | "action": "insert", 195 | "amount": 337, 196 | "pid": 0 197 | }, 198 | { 199 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 200 | "blockNumber": 22071408, 201 | "action": "delete", 202 | "amount": -1799, 203 | "pid": 0 204 | }, 205 | { 206 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 207 | "blockNumber": 22071409, 208 | "action": "insert", 209 | "amount": 1823, 210 | "pid": 0 211 | }, 212 | { 213 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 214 | "blockNumber": 22071411, 215 | "action": "insert", 216 | "amount": 1784, 217 | "pid": 0 218 | }, 219 | { 220 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 221 | "blockNumber": 22071415, 222 | "action": "delete", 223 | "amount": -355, 224 | "pid": 0 225 | }, 226 | { 227 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 228 | "blockNumber": 22071416, 229 | "action": "insert", 230 | "amount": 1604, 231 | "pid": 0 232 | }, 233 | { 234 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 235 | "blockNumber": 22071417, 236 | "action": "delete", 237 | "amount": -1797, 238 | "pid": 0 239 | }, 240 | { 241 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 242 | "blockNumber": 22071419, 243 | "action": "insert", 244 | "amount": 1469, 245 | "pid": 0 246 | }, 247 | { 248 | "address": "0xaB7c029B605A79c95067D31A5eac5037DE867Ab4", 249 | "blockNumber": 22071421, 250 | "action": "insert", 251 | "amount": 1719, 252 | "pid": 0 253 | }, 254 | { 255 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 256 | "blockNumber": 22071428, 257 | "action": "insert", 258 | "amount": 804, 259 | "pid": 0 260 | }, 261 | { 262 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 263 | "blockNumber": 22071433, 264 | "action": "insert", 265 | "amount": 47, 266 | "pid": 0 267 | }, 268 | { 269 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 270 | "blockNumber": 22071441, 271 | "action": "delete", 272 | "amount": -547, 273 | "pid": 0 274 | }, 275 | { 276 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 277 | "blockNumber": 22071443, 278 | "action": "insert", 279 | "amount": 272, 280 | "pid": 0 281 | }, 282 | { 283 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 284 | "blockNumber": 22071450, 285 | "action": "delete", 286 | "amount": -585, 287 | "pid": 0 288 | }, 289 | { 290 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 291 | "blockNumber": 22071451, 292 | "action": "insert", 293 | "amount": 1505, 294 | "pid": 0 295 | }, 296 | { 297 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 298 | "blockNumber": 22071453, 299 | "action": "delete", 300 | "amount": -337, 301 | "pid": 0 302 | }, 303 | { 304 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 305 | "blockNumber": 22071454, 306 | "action": "insert", 307 | "amount": 143, 308 | "pid": 0 309 | }, 310 | { 311 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 312 | "blockNumber": 22071456, 313 | "action": "delete", 314 | "amount": -1243, 315 | "pid": 0 316 | }, 317 | { 318 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 319 | "blockNumber": 22071458, 320 | "action": "insert", 321 | "amount": 705, 322 | "pid": 0 323 | }, 324 | { 325 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 326 | "blockNumber": 22071464, 327 | "action": "delete", 328 | "amount": -250, 329 | "pid": 0 330 | }, 331 | { 332 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 333 | "blockNumber": 22071465, 334 | "action": "insert", 335 | "amount": 290, 336 | "pid": 0 337 | }, 338 | { 339 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 340 | "blockNumber": 22071469, 341 | "action": "insert", 342 | "amount": 1298, 343 | "pid": 0 344 | }, 345 | { 346 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 347 | "blockNumber": 22071476, 348 | "action": "delete", 349 | "amount": -865, 350 | "pid": 0 351 | }, 352 | { 353 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 354 | "blockNumber": 22071477, 355 | "action": "insert", 356 | "amount": 1836, 357 | "pid": 0 358 | }, 359 | { 360 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 361 | "blockNumber": 22071481, 362 | "action": "delete", 363 | "amount": -1604, 364 | "pid": 0 365 | }, 366 | { 367 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 368 | "blockNumber": 22071482, 369 | "action": "insert", 370 | "amount": 1080, 371 | "pid": 0 372 | }, 373 | { 374 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 375 | "blockNumber": 22071483, 376 | "action": "delete", 377 | "amount": -100, 378 | "pid": 0 379 | }, 380 | { 381 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 382 | "blockNumber": 22071483, 383 | "action": "insert", 384 | "amount": 1837, 385 | "pid": 0 386 | }, 387 | { 388 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 389 | "blockNumber": 22071483, 390 | "action": "delete", 391 | "amount": -47, 392 | "pid": 0 393 | }, 394 | { 395 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 396 | "blockNumber": 22071484, 397 | "action": "insert", 398 | "amount": 587, 399 | "pid": 0 400 | }, 401 | { 402 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 403 | "blockNumber": 22071488, 404 | "action": "delete", 405 | "amount": -1505, 406 | "pid": 0 407 | }, 408 | { 409 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 410 | "blockNumber": 22071489, 411 | "action": "insert", 412 | "amount": 410, 413 | "pid": 0 414 | }, 415 | { 416 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 417 | "blockNumber": 22071493, 418 | "action": "delete", 419 | "amount": -1837, 420 | "pid": 0 421 | }, 422 | { 423 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 424 | "blockNumber": 22071493, 425 | "action": "insert", 426 | "amount": 1838, 427 | "pid": 0 428 | }, 429 | { 430 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 431 | "blockNumber": 22071493, 432 | "action": "delete", 433 | "amount": -804, 434 | "pid": 0 435 | }, 436 | { 437 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 438 | "blockNumber": 22071494, 439 | "action": "insert", 440 | "amount": 499, 441 | "pid": 0 442 | }, 443 | { 444 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 445 | "blockNumber": 22071498, 446 | "action": "delete", 447 | "amount": -705, 448 | "pid": 0 449 | }, 450 | { 451 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 452 | "blockNumber": 22071499, 453 | "action": "insert", 454 | "amount": 1195, 455 | "pid": 0 456 | }, 457 | { 458 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 459 | "blockNumber": 22071501, 460 | "action": "delete", 461 | "amount": -1261, 462 | "pid": 0 463 | }, 464 | { 465 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 466 | "blockNumber": 22071502, 467 | "action": "insert", 468 | "amount": 1016, 469 | "pid": 0 470 | }, 471 | { 472 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 473 | "blockNumber": 22071503, 474 | "action": "delete", 475 | "amount": -1838, 476 | "pid": 0 477 | }, 478 | { 479 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 480 | "blockNumber": 22071503, 481 | "action": "insert", 482 | "amount": 1839, 483 | "pid": 0 484 | }, 485 | { 486 | "address": "0xa28Ea741aE38476172a5D8DcB4AA564f2b14c385", 487 | "blockNumber": 22071509, 488 | "action": "insert", 489 | "amount": 1005, 490 | "pid": 0 491 | }, 492 | { 493 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 494 | "blockNumber": 22071512, 495 | "action": "delete", 496 | "amount": -587, 497 | "pid": 0 498 | }, 499 | { 500 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 501 | "blockNumber": 22071513, 502 | "action": "insert", 503 | "amount": 1974, 504 | "pid": 0 505 | }, 506 | { 507 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 508 | "blockNumber": 22071517, 509 | "action": "insert", 510 | "amount": 1221, 511 | "pid": 0 512 | }, 513 | { 514 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 515 | "blockNumber": 22071518, 516 | "action": "delete", 517 | "amount": -1195, 518 | "pid": 0 519 | }, 520 | { 521 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 522 | "blockNumber": 22071519, 523 | "action": "insert", 524 | "amount": 805, 525 | "pid": 0 526 | }, 527 | { 528 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 529 | "blockNumber": 22071526, 530 | "action": "delete", 531 | "amount": -1221, 532 | "pid": 0 533 | }, 534 | { 535 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 536 | "blockNumber": 22071527, 537 | "action": "insert", 538 | "amount": 726, 539 | "pid": 0 540 | }, 541 | { 542 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 543 | "blockNumber": 22071535, 544 | "action": "delete", 545 | "amount": -486, 546 | "pid": 0 547 | }, 548 | { 549 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 550 | "blockNumber": 22071536, 551 | "action": "insert", 552 | "amount": 2000, 553 | "pid": 0 554 | }, 555 | { 556 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 557 | "blockNumber": 22071540, 558 | "action": "delete", 559 | "amount": -805, 560 | "pid": 0 561 | }, 562 | { 563 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 564 | "blockNumber": 22071541, 565 | "action": "insert", 566 | "amount": 218, 567 | "pid": 0 568 | }, 569 | { 570 | "address": "0x84e2067FEd32F9172168593621b03D5E2Fdb9EDF", 571 | "blockNumber": 22071550, 572 | "action": "insert", 573 | "amount": 766, 574 | "pid": 0 575 | }, 576 | { 577 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 578 | "blockNumber": 22071555, 579 | "action": "delete", 580 | "amount": -616, 581 | "pid": 0 582 | }, 583 | { 584 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 585 | "blockNumber": 22071556, 586 | "action": "insert", 587 | "amount": 1946, 588 | "pid": 0 589 | }, 590 | { 591 | "address": "0x0908e7bcb1534e327724E302D468976fe83bB1E5", 592 | "blockNumber": 22071564, 593 | "action": "insert", 594 | "amount": 32, 595 | "pid": 0 596 | }, 597 | { 598 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 599 | "blockNumber": 22071573, 600 | "action": "delete", 601 | "amount": -1469, 602 | "pid": 0 603 | }, 604 | { 605 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 606 | "blockNumber": 22071575, 607 | "action": "insert", 608 | "amount": 892, 609 | "pid": 0 610 | }, 611 | { 612 | "address": "0x01FA4BFfec396C336d1574c4c22d0B9cb5671647", 613 | "blockNumber": 22071582, 614 | "action": "insert", 615 | "amount": 121, 616 | "pid": 0 617 | }, 618 | { 619 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 620 | "blockNumber": 22071587, 621 | "action": "insert", 622 | "amount": 781, 623 | "pid": 0 624 | }, 625 | { 626 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 627 | "blockNumber": 22071591, 628 | "action": "delete", 629 | "amount": -218, 630 | "pid": 0 631 | }, 632 | { 633 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 634 | "blockNumber": 22071592, 635 | "action": "insert", 636 | "amount": 973, 637 | "pid": 0 638 | }, 639 | { 640 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 641 | "blockNumber": 22071600, 642 | "action": "insert", 643 | "amount": 619, 644 | "pid": 0 645 | }, 646 | { 647 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 648 | "blockNumber": 22071605, 649 | "action": "delete", 650 | "amount": -726, 651 | "pid": 0 652 | }, 653 | { 654 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 655 | "blockNumber": 22071612, 656 | "action": "insert", 657 | "amount": 763, 658 | "pid": 0 659 | }, 660 | { 661 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 662 | "blockNumber": 22071622, 663 | "action": "delete", 664 | "amount": -724, 665 | "pid": 0 666 | }, 667 | { 668 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 669 | "blockNumber": 22071624, 670 | "action": "insert", 671 | "amount": 170, 672 | "pid": 0 673 | }, 674 | { 675 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 676 | "blockNumber": 22071632, 677 | "action": "insert", 678 | "amount": 231, 679 | "pid": 0 680 | }, 681 | { 682 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 683 | "blockNumber": 22071639, 684 | "action": "delete", 685 | "amount": -725, 686 | "pid": 0 687 | }, 688 | { 689 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 690 | "blockNumber": 22071640, 691 | "action": "insert", 692 | "amount": 1229, 693 | "pid": 0 694 | }, 695 | { 696 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 697 | "blockNumber": 22071648, 698 | "action": "delete", 699 | "amount": -272, 700 | "pid": 0 701 | }, 702 | { 703 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 704 | "blockNumber": 22071649, 705 | "action": "insert", 706 | "amount": 824, 707 | "pid": 0 708 | }, 709 | { 710 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 711 | "blockNumber": 22071654, 712 | "action": "delete", 713 | "amount": -892, 714 | "pid": 0 715 | }, 716 | { 717 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 718 | "blockNumber": 22071655, 719 | "action": "insert", 720 | "amount": 343, 721 | "pid": 0 722 | }, 723 | { 724 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 725 | "blockNumber": 22071657, 726 | "action": "insert", 727 | "amount": 758, 728 | "pid": 0 729 | }, 730 | { 731 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 732 | "blockNumber": 22071661, 733 | "action": "insert", 734 | "amount": 261, 735 | "pid": 0 736 | }, 737 | { 738 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 739 | "blockNumber": 22071669, 740 | "action": "insert", 741 | "amount": 1881, 742 | "pid": 0 743 | }, 744 | { 745 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 746 | "blockNumber": 22071674, 747 | "action": "delete", 748 | "amount": -499, 749 | "pid": 0 750 | }, 751 | { 752 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 753 | "blockNumber": 22071676, 754 | "action": "insert", 755 | "amount": 1255, 756 | "pid": 0 757 | }, 758 | { 759 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 760 | "blockNumber": 22071679, 761 | "action": "delete", 762 | "amount": -261, 763 | "pid": 0 764 | }, 765 | { 766 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 767 | "blockNumber": 22071680, 768 | "action": "insert", 769 | "amount": 1701, 770 | "pid": 0 771 | }, 772 | { 773 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 774 | "blockNumber": 22071684, 775 | "action": "delete", 776 | "amount": -1784, 777 | "pid": 0 778 | }, 779 | { 780 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 781 | "blockNumber": 22071685, 782 | "action": "insert", 783 | "amount": 415, 784 | "pid": 0 785 | }, 786 | { 787 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 788 | "blockNumber": 22071690, 789 | "action": "delete", 790 | "amount": -143, 791 | "pid": 0 792 | }, 793 | { 794 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 795 | "blockNumber": 22071691, 796 | "action": "insert", 797 | "amount": 379, 798 | "pid": 0 799 | }, 800 | { 801 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 802 | "blockNumber": 22071693, 803 | "action": "delete", 804 | "amount": -1016, 805 | "pid": 0 806 | }, 807 | { 808 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 809 | "blockNumber": 22071694, 810 | "action": "insert", 811 | "amount": 1112, 812 | "pid": 0 813 | }, 814 | { 815 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 816 | "blockNumber": 22071695, 817 | "action": "delete", 818 | "amount": -1515, 819 | "pid": 0 820 | }, 821 | { 822 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 823 | "blockNumber": 22071696, 824 | "action": "insert", 825 | "amount": 1986, 826 | "pid": 0 827 | }, 828 | { 829 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 830 | "blockNumber": 22071701, 831 | "action": "delete", 832 | "amount": -1298, 833 | "pid": 0 834 | }, 835 | { 836 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 837 | "blockNumber": 22071703, 838 | "action": "insert", 839 | "amount": 57, 840 | "pid": 0 841 | }, 842 | { 843 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 844 | "blockNumber": 22071706, 845 | "action": "delete", 846 | "amount": -1974, 847 | "pid": 0 848 | }, 849 | { 850 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 851 | "blockNumber": 22071708, 852 | "action": "insert", 853 | "amount": 1580, 854 | "pid": 0 855 | }, 856 | { 857 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 858 | "blockNumber": 22071709, 859 | "action": "delete", 860 | "amount": -1465, 861 | "pid": 0 862 | }, 863 | { 864 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 865 | "blockNumber": 22071710, 866 | "action": "insert", 867 | "amount": 1323, 868 | "pid": 0 869 | }, 870 | { 871 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 872 | "blockNumber": 22071718, 873 | "action": "delete", 874 | "amount": -4000000000000, 875 | "pid": 0 876 | }, 877 | { 878 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 879 | "blockNumber": 22071718, 880 | "action": "delete", 881 | "amount": -2000, 882 | "pid": 0 883 | }, 884 | { 885 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 886 | "blockNumber": 22071719, 887 | "action": "insert", 888 | "amount": 1093, 889 | "pid": 0 890 | }, 891 | { 892 | "address": "0x661d800966A44F7bce2856412a4c21b1287DB9Ca", 893 | "blockNumber": 22071725, 894 | "action": "insert", 895 | "amount": 1174, 896 | "pid": 0 897 | }, 898 | { 899 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 900 | "blockNumber": 22071730, 901 | "action": "delete", 902 | "amount": -343, 903 | "pid": 0 904 | }, 905 | { 906 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 907 | "blockNumber": 22071732, 908 | "action": "insert", 909 | "amount": 1822, 910 | "pid": 0 911 | }, 912 | { 913 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 914 | "blockNumber": 22071739, 915 | "action": "delete", 916 | "amount": -1093, 917 | "pid": 0 918 | }, 919 | { 920 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 921 | "blockNumber": 22071740, 922 | "action": "insert", 923 | "amount": 859, 924 | "pid": 0 925 | }, 926 | { 927 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 928 | "blockNumber": 22071747, 929 | "action": "delete", 930 | "amount": -410, 931 | "pid": 0 932 | }, 933 | { 934 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 935 | "blockNumber": 22071748, 936 | "action": "insert", 937 | "amount": 276, 938 | "pid": 0 939 | }, 940 | { 941 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 942 | "blockNumber": 22071754, 943 | "action": "delete", 944 | "amount": -231, 945 | "pid": 0 946 | }, 947 | { 948 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 949 | "blockNumber": 22071755, 950 | "action": "insert", 951 | "amount": 1462, 952 | "pid": 0 953 | }, 954 | { 955 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 956 | "blockNumber": 22071759, 957 | "action": "delete", 958 | "amount": -763, 959 | "pid": 0 960 | }, 961 | { 962 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 963 | "blockNumber": 22071760, 964 | "action": "insert", 965 | "amount": 1800, 966 | "pid": 0 967 | }, 968 | { 969 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 970 | "blockNumber": 22071762, 971 | "action": "delete", 972 | "amount": -758, 973 | "pid": 0 974 | }, 975 | { 976 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 977 | "blockNumber": 22071763, 978 | "action": "insert", 979 | "amount": 202, 980 | "pid": 0 981 | }, 982 | { 983 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 984 | "blockNumber": 22071768, 985 | "action": "delete", 986 | "amount": -1080, 987 | "pid": 0 988 | }, 989 | { 990 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 991 | "blockNumber": 22071769, 992 | "action": "insert", 993 | "amount": 796, 994 | "pid": 0 995 | }, 996 | { 997 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 998 | "blockNumber": 22071773, 999 | "action": "insert", 1000 | "amount": 971, 1001 | "pid": 0 1002 | }, 1003 | { 1004 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 1005 | "blockNumber": 22071777, 1006 | "action": "delete", 1007 | "amount": -202, 1008 | "pid": 0 1009 | }, 1010 | { 1011 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 1012 | "blockNumber": 22071778, 1013 | "action": "insert", 1014 | "amount": 1885, 1015 | "pid": 0 1016 | }, 1017 | { 1018 | "address": "0x2C13e81C1B3341a6417CE4E67d9789e94701590d", 1019 | "blockNumber": 22071785, 1020 | "action": "insert", 1021 | "amount": 589, 1022 | "pid": 0 1023 | }, 1024 | { 1025 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 1026 | "blockNumber": 22071791, 1027 | "action": "delete", 1028 | "amount": -781, 1029 | "pid": 0 1030 | }, 1031 | { 1032 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 1033 | "blockNumber": 22071793, 1034 | "action": "insert", 1035 | "amount": 52, 1036 | "pid": 0 1037 | }, 1038 | { 1039 | "address": "0xdFcd31F1950EcE39d8b6A597742D33151A49C4b8", 1040 | "blockNumber": 22071795, 1041 | "action": "insert", 1042 | "amount": 505, 1043 | "pid": 0 1044 | }, 1045 | { 1046 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 1047 | "blockNumber": 22071797, 1048 | "action": "delete", 1049 | "amount": -1803, 1050 | "pid": 0 1051 | }, 1052 | { 1053 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 1054 | "blockNumber": 22071798, 1055 | "action": "insert", 1056 | "amount": 1014, 1057 | "pid": 0 1058 | }, 1059 | { 1060 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 1061 | "blockNumber": 22071799, 1062 | "action": "delete", 1063 | "amount": -971, 1064 | "pid": 0 1065 | }, 1066 | { 1067 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 1068 | "blockNumber": 22071800, 1069 | "action": "insert", 1070 | "amount": 567, 1071 | "pid": 0 1072 | }, 1073 | { 1074 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 1075 | "blockNumber": 22071804, 1076 | "action": "delete", 1077 | "amount": -57, 1078 | "pid": 0 1079 | }, 1080 | { 1081 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 1082 | "blockNumber": 22071805, 1083 | "action": "insert", 1084 | "amount": 312, 1085 | "pid": 0 1086 | }, 1087 | { 1088 | "address": "0x0fff6131a6c7688048BfD5cB8aF9d56659fd4fb5", 1089 | "blockNumber": 22071812, 1090 | "action": "insert", 1091 | "amount": 538, 1092 | "pid": 0 1093 | }, 1094 | { 1095 | "address": "0x1Df37751FAcadDF647352f7008E48a514B5dB1c9", 1096 | "blockNumber": 22071818, 1097 | "action": "insert", 1098 | "amount": 980, 1099 | "pid": 0 1100 | }, 1101 | { 1102 | "address": "0x05911d66EF445C5E6a205A98d394Ff3AcBC3253E", 1103 | "blockNumber": 22071826, 1104 | "action": "insert", 1105 | "amount": 1574, 1106 | "pid": 0 1107 | }, 1108 | { 1109 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 1110 | "blockNumber": 22071830, 1111 | "action": "delete", 1112 | "amount": -1399, 1113 | "pid": 0 1114 | }, 1115 | { 1116 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 1117 | "blockNumber": 22071831, 1118 | "action": "insert", 1119 | "amount": 631, 1120 | "pid": 0 1121 | }, 1122 | { 1123 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 1124 | "blockNumber": 22071837, 1125 | "action": "delete", 1126 | "amount": -796, 1127 | "pid": 0 1128 | }, 1129 | { 1130 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 1131 | "blockNumber": 22071838, 1132 | "action": "insert", 1133 | "amount": 885, 1134 | "pid": 0 1135 | }, 1136 | { 1137 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 1138 | "blockNumber": 22071845, 1139 | "action": "delete", 1140 | "amount": -619, 1141 | "pid": 0 1142 | }, 1143 | { 1144 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 1145 | "blockNumber": 22071846, 1146 | "action": "insert", 1147 | "amount": 896, 1148 | "pid": 0 1149 | }, 1150 | { 1151 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 1152 | "blockNumber": 22071857, 1153 | "action": "insert", 1154 | "amount": 130000000000, 1155 | "pid": 0 1156 | }, 1157 | { 1158 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 1159 | "blockNumber": 22072266, 1160 | "action": "delete", 1161 | "amount": -1255, 1162 | "pid": 0 1163 | }, 1164 | { 1165 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 1166 | "blockNumber": 22072267, 1167 | "action": "insert", 1168 | "amount": 1632, 1169 | "pid": 0 1170 | }, 1171 | { 1172 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 1173 | "blockNumber": 22072280, 1174 | "action": "delete", 1175 | "amount": -1881, 1176 | "pid": 0 1177 | }, 1178 | { 1179 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 1180 | "blockNumber": 22072282, 1181 | "action": "insert", 1182 | "amount": 628, 1183 | "pid": 0 1184 | }, 1185 | { 1186 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 1187 | "blockNumber": 22080736, 1188 | "action": "delete", 1189 | "amount": -130000000000, 1190 | "pid": 0 1191 | }, 1192 | { 1193 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 1194 | "blockNumber": 22080738, 1195 | "action": "delete", 1196 | "amount": -276, 1197 | "pid": 0 1198 | } 1199 | ] -------------------------------------------------------------------------------- /test/steps_3.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 4 | "blockNumber": 22070574, 5 | "action": "insert", 6 | "amount": 4000000000000, 7 | "pid": 0 8 | }, 9 | { 10 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 11 | "blockNumber": 22071253, 12 | "action": "insert", 13 | "amount": 100, 14 | "pid": 0 15 | }, 16 | { 17 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 18 | "blockNumber": 22071270, 19 | "action": "insert", 20 | "amount": 622, 21 | "pid": 0 22 | }, 23 | { 24 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 25 | "blockNumber": 22071279, 26 | "action": "insert", 27 | "amount": 725, 28 | "pid": 0 29 | }, 30 | { 31 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 32 | "blockNumber": 22071283, 33 | "action": "insert", 34 | "amount": 1477, 35 | "pid": 0 36 | }, 37 | { 38 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 39 | "blockNumber": 22071286, 40 | "action": "insert", 41 | "amount": 616, 42 | "pid": 0 43 | }, 44 | { 45 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 46 | "blockNumber": 22071289, 47 | "action": "insert", 48 | "amount": 1465, 49 | "pid": 0 50 | }, 51 | { 52 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 53 | "blockNumber": 22071294, 54 | "action": "insert", 55 | "amount": 1799, 56 | "pid": 0 57 | }, 58 | { 59 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 60 | "blockNumber": 22071301, 61 | "action": "insert", 62 | "amount": 1243, 63 | "pid": 0 64 | }, 65 | { 66 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 67 | "blockNumber": 22071308, 68 | "action": "insert", 69 | "amount": 1797, 70 | "pid": 0 71 | }, 72 | { 73 | "address": "0xa626Aef7c0dD74c825b786166b00929388c568e9", 74 | "blockNumber": 22071318, 75 | "action": "insert", 76 | "amount": 739, 77 | "pid": 0 78 | }, 79 | { 80 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 81 | "blockNumber": 22071326, 82 | "action": "insert", 83 | "amount": 1803, 84 | "pid": 0 85 | }, 86 | { 87 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 88 | "blockNumber": 22071335, 89 | "action": "insert", 90 | "amount": 1515, 91 | "pid": 0 92 | }, 93 | { 94 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 95 | "blockNumber": 22071342, 96 | "action": "insert", 97 | "amount": 250, 98 | "pid": 0 99 | }, 100 | { 101 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 102 | "blockNumber": 22071344, 103 | "action": "insert", 104 | "amount": 724, 105 | "pid": 0 106 | }, 107 | { 108 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 109 | "blockNumber": 22071350, 110 | "action": "insert", 111 | "amount": 355, 112 | "pid": 0 113 | }, 114 | { 115 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 116 | "blockNumber": 22071353, 117 | "action": "insert", 118 | "amount": 759, 119 | "pid": 0 120 | }, 121 | { 122 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 123 | "blockNumber": 22071362, 124 | "action": "insert", 125 | "amount": 585, 126 | "pid": 0 127 | }, 128 | { 129 | "address": "0x1814EE97caA322D7aeAdCF419f47B31FA03A4fc6", 130 | "blockNumber": 22071368, 131 | "action": "insert", 132 | "amount": 1276, 133 | "pid": 0 134 | }, 135 | { 136 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 137 | "blockNumber": 22071375, 138 | "action": "insert", 139 | "amount": 1399, 140 | "pid": 0 141 | }, 142 | { 143 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 144 | "blockNumber": 22071377, 145 | "action": "insert", 146 | "amount": 547, 147 | "pid": 0 148 | }, 149 | { 150 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 151 | "blockNumber": 22071382, 152 | "action": "insert", 153 | "amount": 865, 154 | "pid": 0 155 | }, 156 | { 157 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 158 | "blockNumber": 22071387, 159 | "action": "delete", 160 | "amount": -1477, 161 | "pid": 0 162 | }, 163 | { 164 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 165 | "blockNumber": 22071388, 166 | "action": "insert", 167 | "amount": 486, 168 | "pid": 0 169 | }, 170 | { 171 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 172 | "blockNumber": 22071394, 173 | "action": "delete", 174 | "amount": -622, 175 | "pid": 0 176 | }, 177 | { 178 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 179 | "blockNumber": 22071395, 180 | "action": "insert", 181 | "amount": 1261, 182 | "pid": 0 183 | }, 184 | { 185 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 186 | "blockNumber": 22071402, 187 | "action": "delete", 188 | "amount": -759, 189 | "pid": 0 190 | }, 191 | { 192 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 193 | "blockNumber": 22071403, 194 | "action": "insert", 195 | "amount": 337, 196 | "pid": 0 197 | }, 198 | { 199 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 200 | "blockNumber": 22071408, 201 | "action": "delete", 202 | "amount": -1799, 203 | "pid": 0 204 | }, 205 | { 206 | "address": "0x907b0FD3408915DDf4a1915e6D57d683c81b2E27", 207 | "blockNumber": 22071409, 208 | "action": "insert", 209 | "amount": 1823, 210 | "pid": 0 211 | }, 212 | { 213 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 214 | "blockNumber": 22071411, 215 | "action": "insert", 216 | "amount": 1784, 217 | "pid": 0 218 | }, 219 | { 220 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 221 | "blockNumber": 22071415, 222 | "action": "delete", 223 | "amount": -355, 224 | "pid": 0 225 | }, 226 | { 227 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 228 | "blockNumber": 22071416, 229 | "action": "insert", 230 | "amount": 1604, 231 | "pid": 0 232 | }, 233 | { 234 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 235 | "blockNumber": 22071417, 236 | "action": "delete", 237 | "amount": -1797, 238 | "pid": 0 239 | }, 240 | { 241 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 242 | "blockNumber": 22071419, 243 | "action": "insert", 244 | "amount": 1469, 245 | "pid": 0 246 | }, 247 | { 248 | "address": "0xaB7c029B605A79c95067D31A5eac5037DE867Ab4", 249 | "blockNumber": 22071421, 250 | "action": "insert", 251 | "amount": 1719, 252 | "pid": 0 253 | }, 254 | { 255 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 256 | "blockNumber": 22071428, 257 | "action": "insert", 258 | "amount": 804, 259 | "pid": 0 260 | }, 261 | { 262 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 263 | "blockNumber": 22071433, 264 | "action": "insert", 265 | "amount": 47, 266 | "pid": 0 267 | }, 268 | { 269 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 270 | "blockNumber": 22071441, 271 | "action": "delete", 272 | "amount": -547, 273 | "pid": 0 274 | }, 275 | { 276 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 277 | "blockNumber": 22071443, 278 | "action": "insert", 279 | "amount": 272, 280 | "pid": 0 281 | }, 282 | { 283 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 284 | "blockNumber": 22071450, 285 | "action": "delete", 286 | "amount": -585, 287 | "pid": 0 288 | }, 289 | { 290 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 291 | "blockNumber": 22071451, 292 | "action": "insert", 293 | "amount": 1505, 294 | "pid": 0 295 | }, 296 | { 297 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 298 | "blockNumber": 22071453, 299 | "action": "delete", 300 | "amount": -337, 301 | "pid": 0 302 | }, 303 | { 304 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 305 | "blockNumber": 22071454, 306 | "action": "insert", 307 | "amount": 143, 308 | "pid": 0 309 | }, 310 | { 311 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 312 | "blockNumber": 22071456, 313 | "action": "delete", 314 | "amount": -1243, 315 | "pid": 0 316 | }, 317 | { 318 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 319 | "blockNumber": 22071458, 320 | "action": "insert", 321 | "amount": 705, 322 | "pid": 0 323 | }, 324 | { 325 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 326 | "blockNumber": 22071464, 327 | "action": "delete", 328 | "amount": -250, 329 | "pid": 0 330 | }, 331 | { 332 | "address": "0xc575511a163Af985F4E9A52c8aAB580899F583C7", 333 | "blockNumber": 22071465, 334 | "action": "insert", 335 | "amount": 290, 336 | "pid": 0 337 | }, 338 | { 339 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 340 | "blockNumber": 22071469, 341 | "action": "insert", 342 | "amount": 1298, 343 | "pid": 0 344 | }, 345 | { 346 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 347 | "blockNumber": 22071476, 348 | "action": "delete", 349 | "amount": -865, 350 | "pid": 0 351 | }, 352 | { 353 | "address": "0x467C0A0b8D1276c0c6709cB80eaaB952A4b78508", 354 | "blockNumber": 22071477, 355 | "action": "insert", 356 | "amount": 1836, 357 | "pid": 0 358 | }, 359 | { 360 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 361 | "blockNumber": 22071481, 362 | "action": "delete", 363 | "amount": -1604, 364 | "pid": 0 365 | }, 366 | { 367 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 368 | "blockNumber": 22071482, 369 | "action": "insert", 370 | "amount": 1080, 371 | "pid": 0 372 | }, 373 | { 374 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 375 | "blockNumber": 22071483, 376 | "action": "delete", 377 | "amount": -100, 378 | "pid": 0 379 | }, 380 | { 381 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 382 | "blockNumber": 22071483, 383 | "action": "insert", 384 | "amount": 1837, 385 | "pid": 0 386 | }, 387 | { 388 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 389 | "blockNumber": 22071483, 390 | "action": "delete", 391 | "amount": -47, 392 | "pid": 0 393 | }, 394 | { 395 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 396 | "blockNumber": 22071484, 397 | "action": "insert", 398 | "amount": 587, 399 | "pid": 0 400 | }, 401 | { 402 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 403 | "blockNumber": 22071488, 404 | "action": "delete", 405 | "amount": -1505, 406 | "pid": 0 407 | }, 408 | { 409 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 410 | "blockNumber": 22071489, 411 | "action": "insert", 412 | "amount": 410, 413 | "pid": 0 414 | }, 415 | { 416 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 417 | "blockNumber": 22071493, 418 | "action": "delete", 419 | "amount": -1837, 420 | "pid": 0 421 | }, 422 | { 423 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 424 | "blockNumber": 22071493, 425 | "action": "insert", 426 | "amount": 1838, 427 | "pid": 0 428 | }, 429 | { 430 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 431 | "blockNumber": 22071493, 432 | "action": "delete", 433 | "amount": -804, 434 | "pid": 0 435 | }, 436 | { 437 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 438 | "blockNumber": 22071494, 439 | "action": "insert", 440 | "amount": 499, 441 | "pid": 0 442 | }, 443 | { 444 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 445 | "blockNumber": 22071498, 446 | "action": "delete", 447 | "amount": -705, 448 | "pid": 0 449 | }, 450 | { 451 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 452 | "blockNumber": 22071499, 453 | "action": "insert", 454 | "amount": 1195, 455 | "pid": 0 456 | }, 457 | { 458 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 459 | "blockNumber": 22071501, 460 | "action": "delete", 461 | "amount": -1261, 462 | "pid": 0 463 | }, 464 | { 465 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 466 | "blockNumber": 22071502, 467 | "action": "insert", 468 | "amount": 1016, 469 | "pid": 0 470 | }, 471 | { 472 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 473 | "blockNumber": 22071503, 474 | "action": "delete", 475 | "amount": -1838, 476 | "pid": 0 477 | }, 478 | { 479 | "address": "0xB33145d640223FAece37eF8aCFCD7B232181F54c", 480 | "blockNumber": 22071503, 481 | "action": "insert", 482 | "amount": 1839, 483 | "pid": 0 484 | }, 485 | { 486 | "address": "0xa28Ea741aE38476172a5D8DcB4AA564f2b14c385", 487 | "blockNumber": 22071509, 488 | "action": "insert", 489 | "amount": 1005, 490 | "pid": 0 491 | }, 492 | { 493 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 494 | "blockNumber": 22071512, 495 | "action": "delete", 496 | "amount": -587, 497 | "pid": 0 498 | }, 499 | { 500 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 501 | "blockNumber": 22071513, 502 | "action": "insert", 503 | "amount": 1974, 504 | "pid": 0 505 | }, 506 | { 507 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 508 | "blockNumber": 22071517, 509 | "action": "insert", 510 | "amount": 1221, 511 | "pid": 0 512 | }, 513 | { 514 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 515 | "blockNumber": 22071518, 516 | "action": "delete", 517 | "amount": -1195, 518 | "pid": 0 519 | }, 520 | { 521 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 522 | "blockNumber": 22071519, 523 | "action": "insert", 524 | "amount": 805, 525 | "pid": 0 526 | }, 527 | { 528 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 529 | "blockNumber": 22071526, 530 | "action": "delete", 531 | "amount": -1221, 532 | "pid": 0 533 | }, 534 | { 535 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 536 | "blockNumber": 22071527, 537 | "action": "insert", 538 | "amount": 726, 539 | "pid": 0 540 | }, 541 | { 542 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 543 | "blockNumber": 22071535, 544 | "action": "delete", 545 | "amount": -486, 546 | "pid": 0 547 | }, 548 | { 549 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 550 | "blockNumber": 22071536, 551 | "action": "insert", 552 | "amount": 2000, 553 | "pid": 0 554 | }, 555 | { 556 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 557 | "blockNumber": 22071540, 558 | "action": "delete", 559 | "amount": -805, 560 | "pid": 0 561 | }, 562 | { 563 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 564 | "blockNumber": 22071541, 565 | "action": "insert", 566 | "amount": 218, 567 | "pid": 0 568 | }, 569 | { 570 | "address": "0x84e2067FEd32F9172168593621b03D5E2Fdb9EDF", 571 | "blockNumber": 22071550, 572 | "action": "insert", 573 | "amount": 766, 574 | "pid": 0 575 | }, 576 | { 577 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 578 | "blockNumber": 22071555, 579 | "action": "delete", 580 | "amount": -616, 581 | "pid": 0 582 | }, 583 | { 584 | "address": "0xd1f799540aCaBf127AE8947608dF2ee1470CB013", 585 | "blockNumber": 22071556, 586 | "action": "insert", 587 | "amount": 1946, 588 | "pid": 0 589 | }, 590 | { 591 | "address": "0x0908e7bcb1534e327724E302D468976fe83bB1E5", 592 | "blockNumber": 22071564, 593 | "action": "insert", 594 | "amount": 32, 595 | "pid": 0 596 | }, 597 | { 598 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 599 | "blockNumber": 22071573, 600 | "action": "delete", 601 | "amount": -1469, 602 | "pid": 0 603 | }, 604 | { 605 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 606 | "blockNumber": 22071575, 607 | "action": "insert", 608 | "amount": 892, 609 | "pid": 0 610 | }, 611 | { 612 | "address": "0x01FA4BFfec396C336d1574c4c22d0B9cb5671647", 613 | "blockNumber": 22071582, 614 | "action": "insert", 615 | "amount": 121, 616 | "pid": 0 617 | }, 618 | { 619 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 620 | "blockNumber": 22071587, 621 | "action": "insert", 622 | "amount": 781, 623 | "pid": 0 624 | }, 625 | { 626 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 627 | "blockNumber": 22071591, 628 | "action": "delete", 629 | "amount": -218, 630 | "pid": 0 631 | }, 632 | { 633 | "address": "0xF534fbD1d8720fe5471fde01F83bA23ABE48Eb0B", 634 | "blockNumber": 22071592, 635 | "action": "insert", 636 | "amount": 973, 637 | "pid": 0 638 | }, 639 | { 640 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 641 | "blockNumber": 22071600, 642 | "action": "insert", 643 | "amount": 619, 644 | "pid": 0 645 | }, 646 | { 647 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 648 | "blockNumber": 22071605, 649 | "action": "delete", 650 | "amount": -726, 651 | "pid": 0 652 | }, 653 | { 654 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 655 | "blockNumber": 22071612, 656 | "action": "insert", 657 | "amount": 763, 658 | "pid": 0 659 | }, 660 | { 661 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 662 | "blockNumber": 22071622, 663 | "action": "delete", 664 | "amount": -724, 665 | "pid": 0 666 | }, 667 | { 668 | "address": "0x0e533538C7a07CfFb0587D49D1Edc5b67aaafAFD", 669 | "blockNumber": 22071624, 670 | "action": "insert", 671 | "amount": 170, 672 | "pid": 0 673 | }, 674 | { 675 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 676 | "blockNumber": 22071632, 677 | "action": "insert", 678 | "amount": 231, 679 | "pid": 0 680 | }, 681 | { 682 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 683 | "blockNumber": 22071639, 684 | "action": "delete", 685 | "amount": -725, 686 | "pid": 0 687 | }, 688 | { 689 | "address": "0xD2b7Cfa9A7662eFD8450b034FdD472Ffd8f36D68", 690 | "blockNumber": 22071640, 691 | "action": "insert", 692 | "amount": 1229, 693 | "pid": 0 694 | }, 695 | { 696 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 697 | "blockNumber": 22071648, 698 | "action": "delete", 699 | "amount": -272, 700 | "pid": 0 701 | }, 702 | { 703 | "address": "0x7B24838A7e9413603212619B78Da75Ea1C415250", 704 | "blockNumber": 22071649, 705 | "action": "insert", 706 | "amount": 824, 707 | "pid": 0 708 | }, 709 | { 710 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 711 | "blockNumber": 22071654, 712 | "action": "delete", 713 | "amount": -892, 714 | "pid": 0 715 | }, 716 | { 717 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 718 | "blockNumber": 22071655, 719 | "action": "insert", 720 | "amount": 343, 721 | "pid": 0 722 | }, 723 | { 724 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 725 | "blockNumber": 22071657, 726 | "action": "insert", 727 | "amount": 758, 728 | "pid": 0 729 | }, 730 | { 731 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 732 | "blockNumber": 22071661, 733 | "action": "insert", 734 | "amount": 261, 735 | "pid": 0 736 | }, 737 | { 738 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 739 | "blockNumber": 22071669, 740 | "action": "insert", 741 | "amount": 1881, 742 | "pid": 0 743 | }, 744 | { 745 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 746 | "blockNumber": 22071674, 747 | "action": "delete", 748 | "amount": -499, 749 | "pid": 0 750 | }, 751 | { 752 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 753 | "blockNumber": 22071676, 754 | "action": "insert", 755 | "amount": 1255, 756 | "pid": 0 757 | }, 758 | { 759 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 760 | "blockNumber": 22071679, 761 | "action": "delete", 762 | "amount": -261, 763 | "pid": 0 764 | }, 765 | { 766 | "address": "0x62412e703DF603dF878C76Ddb9B2f964c3AE436F", 767 | "blockNumber": 22071680, 768 | "action": "insert", 769 | "amount": 1701, 770 | "pid": 0 771 | }, 772 | { 773 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 774 | "blockNumber": 22071684, 775 | "action": "delete", 776 | "amount": -1784, 777 | "pid": 0 778 | }, 779 | { 780 | "address": "0xA654B8997AB9B55886626b31006a1916F71E9078", 781 | "blockNumber": 22071685, 782 | "action": "insert", 783 | "amount": 415, 784 | "pid": 0 785 | }, 786 | { 787 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 788 | "blockNumber": 22071690, 789 | "action": "delete", 790 | "amount": -143, 791 | "pid": 0 792 | }, 793 | { 794 | "address": "0x94ec6b3FE94441c0ED4CAE624acdA21532b1Bc70", 795 | "blockNumber": 22071691, 796 | "action": "insert", 797 | "amount": 379, 798 | "pid": 0 799 | }, 800 | { 801 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 802 | "blockNumber": 22071693, 803 | "action": "delete", 804 | "amount": -1016, 805 | "pid": 0 806 | }, 807 | { 808 | "address": "0xDaB8C61fae3A170CF2f4411D4689BD62Fa733021", 809 | "blockNumber": 22071694, 810 | "action": "insert", 811 | "amount": 1112, 812 | "pid": 0 813 | }, 814 | { 815 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 816 | "blockNumber": 22071695, 817 | "action": "delete", 818 | "amount": -1515, 819 | "pid": 0 820 | }, 821 | { 822 | "address": "0x4FC42E49c6b398Bb7298eCA5b6965789bcecf48D", 823 | "blockNumber": 22071696, 824 | "action": "insert", 825 | "amount": 1986, 826 | "pid": 0 827 | }, 828 | { 829 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 830 | "blockNumber": 22071701, 831 | "action": "delete", 832 | "amount": -1298, 833 | "pid": 0 834 | }, 835 | { 836 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 837 | "blockNumber": 22071703, 838 | "action": "insert", 839 | "amount": 57, 840 | "pid": 0 841 | }, 842 | { 843 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 844 | "blockNumber": 22071706, 845 | "action": "delete", 846 | "amount": -1974, 847 | "pid": 0 848 | }, 849 | { 850 | "address": "0x94Cda082c62FbB1e0a143CaC0C4daE67863817D6", 851 | "blockNumber": 22071708, 852 | "action": "insert", 853 | "amount": 1580, 854 | "pid": 0 855 | }, 856 | { 857 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 858 | "blockNumber": 22071709, 859 | "action": "delete", 860 | "amount": -1465, 861 | "pid": 0 862 | }, 863 | { 864 | "address": "0xffa92D777484680A3e509ac0A5B598fE85BBdeee", 865 | "blockNumber": 22071710, 866 | "action": "insert", 867 | "amount": 1323, 868 | "pid": 0 869 | }, 870 | { 871 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 872 | "blockNumber": 22071718, 873 | "action": "delete", 874 | "amount": -4000000000000, 875 | "pid": 0 876 | }, 877 | { 878 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 879 | "blockNumber": 22071718, 880 | "action": "delete", 881 | "amount": -2000, 882 | "pid": 0 883 | }, 884 | { 885 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 886 | "blockNumber": 22071719, 887 | "action": "insert", 888 | "amount": 1093, 889 | "pid": 0 890 | }, 891 | { 892 | "address": "0x661d800966A44F7bce2856412a4c21b1287DB9Ca", 893 | "blockNumber": 22071725, 894 | "action": "insert", 895 | "amount": 1174, 896 | "pid": 0 897 | }, 898 | { 899 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 900 | "blockNumber": 22071730, 901 | "action": "delete", 902 | "amount": -343, 903 | "pid": 0 904 | }, 905 | { 906 | "address": "0x0a11c0fEEE59F991891c88Ce623C050a7d1F934C", 907 | "blockNumber": 22071732, 908 | "action": "insert", 909 | "amount": 1822, 910 | "pid": 0 911 | }, 912 | { 913 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 914 | "blockNumber": 22071739, 915 | "action": "delete", 916 | "amount": -1093, 917 | "pid": 0 918 | }, 919 | { 920 | "address": "0x37611DA9a94cf3b466b8f1bEae206A26A3A6E4fC", 921 | "blockNumber": 22071740, 922 | "action": "insert", 923 | "amount": 859, 924 | "pid": 0 925 | }, 926 | { 927 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 928 | "blockNumber": 22071747, 929 | "action": "delete", 930 | "amount": -410, 931 | "pid": 0 932 | }, 933 | { 934 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 935 | "blockNumber": 22071748, 936 | "action": "insert", 937 | "amount": 276, 938 | "pid": 0 939 | }, 940 | { 941 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 942 | "blockNumber": 22071754, 943 | "action": "delete", 944 | "amount": -231, 945 | "pid": 0 946 | }, 947 | { 948 | "address": "0xADEEef8203921E80F9F7e55a67D552cE550d7140", 949 | "blockNumber": 22071755, 950 | "action": "insert", 951 | "amount": 1462, 952 | "pid": 0 953 | }, 954 | { 955 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 956 | "blockNumber": 22071759, 957 | "action": "delete", 958 | "amount": -763, 959 | "pid": 0 960 | }, 961 | { 962 | "address": "0x9174B3821999E251253BeeBD0D9EcCaC73EC38fA", 963 | "blockNumber": 22071760, 964 | "action": "insert", 965 | "amount": 1800, 966 | "pid": 0 967 | }, 968 | { 969 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 970 | "blockNumber": 22071762, 971 | "action": "delete", 972 | "amount": -758, 973 | "pid": 0 974 | }, 975 | { 976 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 977 | "blockNumber": 22071763, 978 | "action": "insert", 979 | "amount": 202, 980 | "pid": 0 981 | }, 982 | { 983 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 984 | "blockNumber": 22071768, 985 | "action": "delete", 986 | "amount": -1080, 987 | "pid": 0 988 | }, 989 | { 990 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 991 | "blockNumber": 22071769, 992 | "action": "insert", 993 | "amount": 796, 994 | "pid": 0 995 | }, 996 | { 997 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 998 | "blockNumber": 22071773, 999 | "action": "insert", 1000 | "amount": 971, 1001 | "pid": 0 1002 | }, 1003 | { 1004 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 1005 | "blockNumber": 22071777, 1006 | "action": "delete", 1007 | "amount": -202, 1008 | "pid": 0 1009 | }, 1010 | { 1011 | "address": "0x1D7F2d394Feb99339e2711429B37BbE6cA0b6835", 1012 | "blockNumber": 22071778, 1013 | "action": "insert", 1014 | "amount": 1885, 1015 | "pid": 0 1016 | }, 1017 | { 1018 | "address": "0x2C13e81C1B3341a6417CE4E67d9789e94701590d", 1019 | "blockNumber": 22071785, 1020 | "action": "insert", 1021 | "amount": 589, 1022 | "pid": 0 1023 | }, 1024 | { 1025 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 1026 | "blockNumber": 22071791, 1027 | "action": "delete", 1028 | "amount": -781, 1029 | "pid": 0 1030 | }, 1031 | { 1032 | "address": "0x2dD18F7Ff8328355d40Dec1eB8b8729503C41710", 1033 | "blockNumber": 22071793, 1034 | "action": "insert", 1035 | "amount": 52, 1036 | "pid": 0 1037 | }, 1038 | { 1039 | "address": "0xdFcd31F1950EcE39d8b6A597742D33151A49C4b8", 1040 | "blockNumber": 22071795, 1041 | "action": "insert", 1042 | "amount": 505, 1043 | "pid": 0 1044 | }, 1045 | { 1046 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 1047 | "blockNumber": 22071797, 1048 | "action": "delete", 1049 | "amount": -1803, 1050 | "pid": 0 1051 | }, 1052 | { 1053 | "address": "0x9DEFA9B9667708e1BE2f6Ba48ccB049F4A132408", 1054 | "blockNumber": 22071798, 1055 | "action": "insert", 1056 | "amount": 1014, 1057 | "pid": 0 1058 | }, 1059 | { 1060 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 1061 | "blockNumber": 22071799, 1062 | "action": "delete", 1063 | "amount": -971, 1064 | "pid": 0 1065 | }, 1066 | { 1067 | "address": "0x608bdAf31969Ec6D1EB4B94624a336c69F0E75E5", 1068 | "blockNumber": 22071800, 1069 | "action": "insert", 1070 | "amount": 567, 1071 | "pid": 0 1072 | }, 1073 | { 1074 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 1075 | "blockNumber": 22071804, 1076 | "action": "delete", 1077 | "amount": -57, 1078 | "pid": 0 1079 | }, 1080 | { 1081 | "address": "0x740f6D162b5d0bBdb9989Dae8aA43d8C0349edF5", 1082 | "blockNumber": 22071805, 1083 | "action": "insert", 1084 | "amount": 312, 1085 | "pid": 0 1086 | }, 1087 | { 1088 | "address": "0x0fff6131a6c7688048BfD5cB8aF9d56659fd4fb5", 1089 | "blockNumber": 22071812, 1090 | "action": "insert", 1091 | "amount": 538, 1092 | "pid": 0 1093 | }, 1094 | { 1095 | "address": "0x1Df37751FAcadDF647352f7008E48a514B5dB1c9", 1096 | "blockNumber": 22071818, 1097 | "action": "insert", 1098 | "amount": 980, 1099 | "pid": 0 1100 | }, 1101 | { 1102 | "address": "0x05911d66EF445C5E6a205A98d394Ff3AcBC3253E", 1103 | "blockNumber": 22071826, 1104 | "action": "insert", 1105 | "amount": 1574, 1106 | "pid": 0 1107 | }, 1108 | { 1109 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 1110 | "blockNumber": 22071830, 1111 | "action": "delete", 1112 | "amount": -1399, 1113 | "pid": 0 1114 | }, 1115 | { 1116 | "address": "0xA86599E95d11f79e254C228411f24846b8C3DaE1", 1117 | "blockNumber": 22071831, 1118 | "action": "insert", 1119 | "amount": 631, 1120 | "pid": 0 1121 | }, 1122 | { 1123 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 1124 | "blockNumber": 22071837, 1125 | "action": "delete", 1126 | "amount": -796, 1127 | "pid": 0 1128 | }, 1129 | { 1130 | "address": "0x81F57BCB681e6eeCe1785198D2C1df31c5d4898C", 1131 | "blockNumber": 22071838, 1132 | "action": "insert", 1133 | "amount": 885, 1134 | "pid": 0 1135 | }, 1136 | { 1137 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 1138 | "blockNumber": 22071845, 1139 | "action": "delete", 1140 | "amount": -619, 1141 | "pid": 0 1142 | }, 1143 | { 1144 | "address": "0xe02C06e6a59965457a0Eb867EBfc467a4D38712b", 1145 | "blockNumber": 22071846, 1146 | "action": "insert", 1147 | "amount": 896, 1148 | "pid": 0 1149 | }, 1150 | { 1151 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 1152 | "blockNumber": 22071857, 1153 | "action": "insert", 1154 | "amount": 130000000000, 1155 | "pid": 0 1156 | }, 1157 | { 1158 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 1159 | "blockNumber": 22072266, 1160 | "action": "delete", 1161 | "amount": -1255, 1162 | "pid": 0 1163 | }, 1164 | { 1165 | "address": "0x0AfedB0F0Bf0d09B37fCEc0688A1E04125A76A7C", 1166 | "blockNumber": 22072267, 1167 | "action": "insert", 1168 | "amount": 1632, 1169 | "pid": 0 1170 | }, 1171 | { 1172 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 1173 | "blockNumber": 22072280, 1174 | "action": "delete", 1175 | "amount": -1881, 1176 | "pid": 0 1177 | }, 1178 | { 1179 | "address": "0xA863E00d0F35f02d7cF5CD8CF1dc39947d8A28e2", 1180 | "blockNumber": 22072282, 1181 | "action": "insert", 1182 | "amount": 628, 1183 | "pid": 0 1184 | }, 1185 | { 1186 | "address": "0x42EAA716bE1006FaAb659AFa775102B03934AB10", 1187 | "blockNumber": 22080736, 1188 | "action": "delete", 1189 | "amount": -130000000000, 1190 | "pid": 0 1191 | }, 1192 | { 1193 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 1194 | "blockNumber": 22080738, 1195 | "action": "delete", 1196 | "amount": -276, 1197 | "pid": 0 1198 | }, 1199 | { 1200 | "address": "0x1f28D61B3d5a6eD05bFE7Ed0f0987B65afcDC6d8", 1201 | "blockNumber": 22080740, 1202 | "action": "insert", 1203 | "amount": 276, 1204 | "pid": 0 1205 | } 1206 | ] -------------------------------------------------------------------------------- /truffle-config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Use this file to configure your truffle project. It's seeded with some 3 | * common settings for different networks and features like migrations, 4 | * compilation and testing. Uncomment the ones you need or modify 5 | * them to suit your project as necessary. 6 | * 7 | * More information about configuration can be found at: 8 | * 9 | * trufflesuite.com/docs/advanced/configuration 10 | * 11 | * To deploy via Infura you'll need a wallet provider (like @truffle/hdwallet-provider) 12 | * to sign your transactions before they're sent to a remote public node. Infura accounts 13 | * are available for free at: infura.io/register. 14 | * 15 | * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate 16 | * public/private key pairs. If you're publishing your code to GitHub make sure you load this 17 | * phrase from a file you've .gitignored so it doesn't accidentally become public. 18 | * 19 | */ 20 | 21 | // const HDWalletProvider = require('@truffle/hdwallet-provider'); 22 | // const infuraKey = "fj4jll3k....."; 23 | // 24 | // const fs = require('fs'); 25 | // const mnemonic = fs.readFileSync(".secret").toString().trim(); 26 | 27 | module.exports = { 28 | /** 29 | * Networks define how you connect to your ethereum client and let you set the 30 | * defaults web3 uses to send transactions. If you don't specify one truffle 31 | * will spin up a development blockchain for you on port 9545 when you 32 | * run `develop` or `test`. You can ask a truffle command to use a specific 33 | * network from the command line, e.g 34 | * 35 | * $ truffle test --network 36 | */ 37 | 38 | networks: { 39 | // Useful for testing. The `development` name is special - truffle uses it by default 40 | // if it's defined here and no other network is specified at the command line. 41 | // You should run a client (like ganache-cli, geth or parity) in a separate terminal 42 | // tab if you use this network and you must also set the `host`, `port` and `network_id` 43 | // options below to some value. 44 | // 45 | development: { 46 | host: "127.0.0.1", // Localhost (default: none) 47 | port: 8545, // Standard Ethereum port (default: none) 48 | network_id: "*", // Any network (default: none) 49 | } 50 | // Another network with more advanced options... 51 | // advanced: { 52 | // port: 8777, // Custom port 53 | // network_id: 1342, // Custom network 54 | // gas: 8500000, // Gas sent with each transaction (default: ~6700000) 55 | // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) 56 | // from:
, // Account to send txs from (default: accounts[0]) 57 | // websockets: true // Enable EventEmitter interface for web3 (default: false) 58 | // }, 59 | // Useful for deploying to a public network. 60 | // NB: It's important to wrap the provider as a function. 61 | // ropsten: { 62 | // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), 63 | // network_id: 3, // Ropsten's id 64 | // gas: 5500000, // Ropsten has a lower block limit than mainnet 65 | // confirmations: 2, // # of confs to wait between deployments. (default: 0) 66 | // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) 67 | // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) 68 | // }, 69 | // Useful for private networks 70 | // private: { 71 | // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), 72 | // network_id: 2111, // This network is yours, in the cloud. 73 | // production: true // Treats this network as if it was a public net. (default: false) 74 | // } 75 | }, 76 | 77 | // Set default mocha options here, use special reporters etc. 78 | mocha: { 79 | timeout: 10000000 80 | }, 81 | 82 | // Configure your compilers 83 | compilers: { 84 | solc: { 85 | version: "0.5.1", // Fetch exact version from solc-bin (default: truffle's version) 86 | // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) 87 | // settings: { // See the solidity docs for advice about optimization and evmVersion 88 | // optimizer: { 89 | // enabled: false, 90 | // runs: 200 91 | // }, 92 | // evmVersion: "byzantium" 93 | // } 94 | } 95 | } 96 | }; 97 | --------------------------------------------------------------------------------