{"id":18953165,"url":"https://github.com/0xpolygon/account-binary-search-tree","last_synced_at":"2025-04-16T02:32:04.226Z","repository":{"id":62948357,"uuid":"563865232","full_name":"0xPolygon/account-binary-search-tree","owner":"0xPolygon","description":null,"archived":false,"fork":false,"pushed_at":"2023-03-03T15:10:59.000Z","size":4002,"stargazers_count":45,"open_issues_count":10,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-03-06T04:27:45.425Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0xPolygon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-11-09T13:58:23.000Z","updated_at":"2023-02-23T13:31:47.000Z","dependencies_parsed_at":"2023-02-11T03:30:57.640Z","dependency_job_id":null,"html_url":"https://github.com/0xPolygon/account-binary-search-tree","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygon%2Faccount-binary-search-tree","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygon%2Faccount-binary-search-tree/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygon%2Faccount-binary-search-tree/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0xPolygon%2Faccount-binary-search-tree/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0xPolygon","download_url":"https://codeload.github.com/0xPolygon/account-binary-search-tree/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223692702,"owners_count":17187064,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-08T13:36:54.310Z","updated_at":"2024-11-08T13:36:54.798Z","avatar_url":"https://github.com/0xPolygon.png","language":"Solidity","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Account Binary Search Tree\n\n[![License](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)\n[![CI Status](https://github.com/gretzke/account-binary-search-tree/actions/workflows/tests.yml/badge.svg)](https://github.com/gretzke/account-binary-search-tree/actions)\n\n## Contents\n\n- [Description](#description)\n- [Usage](#usage)\n- [API](#api)\n- [Build and Test](#build-and-test)\n- [Etherscan Verification](#etherscan-verification)\n- [Performance Optimizations](#performance-optimizations)\n\n## Description\n\nThis project demonstrates an implementation of a self balancing red-black binary search tree for usecases where accounts/addresses need to be sorted by their balance. This could be used inside of a game where players are sorted by their points or a staking implementation where stakers need to be sorted by their stake.\n\nIf an array or linked list was used for such a use case the insertion and deletion cost would be `O(n)` worst case which is not suitable for a smart contract implementation. With this self balancing binary implementation the insertion and deletion cost can be reduced to `O(log n)`. This library is based on [Rob Hitchens's (B9Labs) order statistics tree](https://github.com/rob-Hitchens/OrderStatisticsTree).\n\nDor more information on red-black trees see https://en.wikipedia.org/wiki/Red%E2%80%93black_tree\n\n## Usage\n\nThese contracts were originally developed for Polygon's [Core Contracts](https://github.com/0xPolygon/core-contracts), where they are used to maintain the list of validators and sort them by stake. You can read more about this implementation [here](https://github.com/0xPolygon/core-contracts/tree/main/contracts/libs#queue-pool-and-tree-libs-in-more-detail).\n\nAs you can see in both the example implementation in this repo and in Polygon's Core Contracts, you will generally use a two-contract approach, using `AccountStorage.sol` as a lib inside of a queue implemented to use it. (In the case of this repo, `DemoContract.sol`.)\n\nIn addition, the structs used throughout the tree are located in `contracts/interfaces/IAccount.sol`.\n\nThe example in this repo sorts accounts in a tree based on the amount of native asset (e.g. ETH on Ethereum mainnet) staked in the `DemoContract.sol` contract. We hope this example also helps illustrate how the tree could be used easily for ERC20 tokens or NFTs.\n\nThere are also basic tests to demonstrate basic usage.\n\n## API\n\nAll structs and functions have detailed natspec, more detail on these can be found there. This will be a brief overview of the function API for `AccountStorage`. Note that all functions are `internal`. This contract is meant to be consumed as a library. Here is the function API:\n\n- `function get(AccountTree storage self, address account) returns (Account storage)`\n- `function balanceOf(AccountTree storage self, address account) returns (uint256 balance)`\n- `function first(AccountTree storage self) returns (address _key)`\n- `function last(AccountTree storage self) returns (address _key)`\n- `function next(AccountTree storage self, address target) returns (address cursor)`\n- `function prev(AccountTree storage self, address target) returns (address cursor)`\n- `function exists(AccountTree storage self, address key) returns (bool)`\n- `function isEmpty(address key) returns (bool)`\n- `function getNode(AccountTree storage self, address key) returns (address _returnKey, address _parent, address _left, address _right, bool _red)`\n- `function insert(AccountTree storage self, address key, Account memory account)`\n- `function remove(AccountTree storage self, address key)`\n- `function treeMinimum(AccountTree storage self, address key) returns (address)`\n- `function treeMaximum(AccountTree storage self, address key) returns (address)`\n- `function rotateLeft(AccountTree storage self, address key)`\n- `function rotateRight(AccountTree storage self, address key)`\n- `function insertFixup(AccountTree storage self, address key)`\n- `function replaceParent(AccountTree storage self, address a, address b)`\n- `function removeFixup(AccountTree storage self, address key)`\n\nIn addition, the struct API for `Account`, used in `insert()` is:\n\n```\nstruct Account {\n  uint256 balance;\n  bool isActive;\n}\n```\n\n## Build and Test\n\nOn the project root, run:\n\n```bash\n$ npm i                 # install dependencies\n$ npm run compile       # compile contracts and generate typechain\n$ npm test              # run contract tests\n```\n\nTo run foundry tests for the library:\n\n```bash\n$ forge build           # compile contracts\n$ forge test            # run library tests\n```\n\noptional:\n\n```bash\n$ npm run coverage      # run test coverage tool\n```\n\n## Etherscan verification\n\nTo try out Etherscan verification, you first need to deploy a contract to an Ethereum network that's supported by Etherscan, such as Goerli.\n\nIn this project, copy the .env.example file to a file named .env, and then edit it to fill in the details. Enter your Etherscan API key, your Infura API key, and the mnemonic phrase of the account which will send the deployment transaction. With a valid .env file in place, first deploy your contract:\n\n```shell\nnpx hardhat run scripts/deploy.ts --network goerli\n```\n\nThen, copy the deployment address and paste it in to replace `DEPLOYED_CONTRACT_ADDRESS` in this command:\n\n```shell\nnpx hardhat verify --network goerli DEPLOYED_CONTRACT_ADDRESS \"Hello, Hardhat!\"\n```\n\n# Performance optimizations\n\nFor faster runs of your tests and scripts, consider skipping ts-node's type checking by setting the environment variable `TS_NODE_TRANSPILE_ONLY` to `1` in hardhat's environment. For more details see [the documentation](https://hardhat.org/guides/typescript.html#performance-optimizations).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xpolygon%2Faccount-binary-search-tree","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0xpolygon%2Faccount-binary-search-tree","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0xpolygon%2Faccount-binary-search-tree/lists"}