{"id":24054331,"url":"https://github.com/solidity-utilities/address-storage","last_synced_at":"2025-11-20T14:04:09.642Z","repository":{"id":38080730,"uuid":"419571522","full_name":"solidity-utilities/address-storage","owner":"solidity-utilities","description":"Solidity contract for storing and interacting with key/value address pairs","archived":false,"fork":false,"pushed_at":"2023-07-03T17:07:49.000Z","size":2289,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-20T05:50:25.877Z","etag":null,"topics":["address","contract","ethereum","solidity","truffle"],"latest_commit_sha":null,"homepage":"","language":"Solidity","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/solidity-utilities.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-21T03:44:11.000Z","updated_at":"2025-03-12T11:01:47.000Z","dependencies_parsed_at":"2025-01-09T03:04:17.802Z","dependency_job_id":"d8a4d33b-1634-4617-a398-052ab25be488","html_url":"https://github.com/solidity-utilities/address-storage","commit_stats":{"total_commits":62,"total_committers":2,"mean_commits":31.0,"dds":0.4032258064516129,"last_synced_commit":"20179a6286d6324f5a0892349702b54c96a64f21"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/solidity-utilities/address-storage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidity-utilities%2Faddress-storage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidity-utilities%2Faddress-storage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidity-utilities%2Faddress-storage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidity-utilities%2Faddress-storage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/solidity-utilities","download_url":"https://codeload.github.com/solidity-utilities/address-storage/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/solidity-utilities%2Faddress-storage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":285447937,"owners_count":27173436,"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","status":"online","status_checked_at":"2025-11-20T02:00:05.334Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["address","contract","ethereum","solidity","truffle"],"created_at":"2025-01-09T03:04:10.748Z","updated_at":"2025-11-20T14:04:09.625Z","avatar_url":"https://github.com/solidity-utilities.png","language":"Solidity","readme":"# Address Storage\n[heading__top]:\n  #address-storage\n  \"\u0026#x2B06; Solidity contract for storing and interacting with key/value address pairs\"\n\n\nSolidity contract for storing and interacting with key/value address pairs\n\n\n## [![Byte size of Address Storage][badge__main__address_storage__source_code]][address_storage__main__source_code] [![Open Issues][badge__issues__address_storage]][issues__address_storage] [![Open Pull Requests][badge__pull_requests__address_storage]][pull_requests__address_storage] [![Latest commits][badge__commits__address_storage__main]][commits__address_storage__main] [![Build Status][badge__github_actions]][activity_log__github_actions]\n\n\n---\n\n\n- [:arrow_up: Top of Document][heading__top]\n\n- [:building_construction: Requirements][heading__requirements]\n\n- [:zap: Quick Start][heading__quick_start]\n\n- [\u0026#x1F9F0; Usage][heading__usage]\n\n- [\u0026#x1F523; API][heading__api]\n  - [Contract `AddressStorage`][heading__contract_addressstorage]\n    - [Method `addAuthorized`][heading__method_addauthorized]\n    - [Method `changeOwner`][heading__method_changeowner]\n    - [Method `clear`][heading__method_clear]\n    - [Method `deleteAuthorized`][heading__method_deleteauthorized]\n    - [Method `get`][heading__method_get]\n    - [Method `getOrElse`][heading__method_getorelse]\n    - [Method `getOrError`][heading__method_getorerror]\n    - [Method `has`][heading__method_has]\n    - [Method `indexOf`][heading__method_indexof]\n    - [Method `indexOfOrError`][heading__method_indexoforerror]\n    - [Method `listKeys`][heading__method_listkeys]\n    - [Method `remove`][heading__method_remove]\n    - [Method `removeOrError`][heading__method_removeorerror]\n    - [Method `selfDestruct`][heading__method_selfdestruct]\n    - [Method `set`][heading__method_set]\n    - [Method `setOrError`][heading__method_setorerror]\n    - [Method `size`][heading__method_size]\n\n- [\u0026#x1F5D2; Notes][heading__notes]\n\n- [:chart_with_upwards_trend: Contributing][heading__contributing]\n  - [:trident: Forking][heading__forking]\n  - [:currency_exchange: Sponsor][heading__sponsor]\n\n- [\u0026#x1f4dc; Change Log][heading__change_log]\n  - [Version `0.1.0`][heading__version_010]\n  - [Version `0.2.0`][heading__version_020]\n\n- [:card_index: Attribution][heading__attribution]\n\n- [:balance_scale: Licensing][heading__license]\n\n\n---\n\n\n\n## Requirements\n[heading__requirements]:\n  #requirements\n  \"\u0026#x1F3D7; Prerequisites and/or dependencies that this project needs to function properly\"\n\n\n\u003e Prerequisites and/or dependencies that this project needs to function properly\n\n\nThis project utilizes Truffle for organization of source code and tests, thus\nit is recommended to install Truffle _globally_ to your current user account\n\n\n```Bash\nnpm install -g truffle\n```\n\n\n______\n\n\n## Quick Start\n[heading__quick_start]:\n  #quick-start\n  \"\u0026#9889; Perhaps as easy as one, 2.0,...\"\n\n\n\u003e Perhaps as easy as one, 2.0,...\n\n\nNPM and Truffle are recommended for importing and managing dependencies\n\n\n```Bash\ncd your_project\n\nnpm install @solidity-utilities/address-storage\n```\n\n\n\u003e Note, source code will be located within the\n\u003e `node_modules/@solidity-utilities/address-storage` directory of\n\u003e _`your_project`_ root\n\n\nSolidity contracts may then import code via similar syntax as shown\n\n\n```Solidity\nimport {\n    AddressStorage\n} from \"@solidity-utilities/address-storage/contracts/AddressStorage.sol\";\n\nimport {\n    InterfaceAddressStorage\n} from \"@solidity-utilities/address-storage/contracts/InterfaceAddressStorage.sol\";\n```\n\n\n\u003e Note, above path is **not** relative (ie. there's no `./` preceding the file\n\u003e path) which causes Truffle to search the `node_modules` subs-directories\n\n\n\u003e Tip, whenever possible it is recommended to utilize `InterfaceAddressStorage`\n\u003e instead, because calling methods directly from `AddressStorage` will cause\n\u003e compiler to copy method byte code.\n\n\nReview the [Truffle -- Package Management via NPM][truffle__package_management_via_npm] documentation for more details.\n\n\n______\n\n\n## Usage\n[heading__usage]:\n  #usage\n  \"\u0026#x1F9F0; How to utilize this repository\"\n\n\n\u003e How to utilize this repository\n\n\nWrite a set of contracts that make use of, and extend, `AddressStorage` features.\n\n\n[**`contracts/Account.sol`**][source__test__examples__account_sol]\n\n\n```Solidity\n// SPDX-License-Identifier: AGPL-3.0\npragma solidity 0.8.7;\n\n/// @title Example contract instance to be reconstituted by `Host`\n/// @author S0AndS0\ncontract Account {\n    address public owner;\n    string public name;\n\n    /* -------------------------------------------------------------------- */\n\n    ///\n    constructor(address _owner, string memory _name) {\n        owner = _owner;\n        name = _name;\n    }\n\n    /* -------------------------------------------------------------------- */\n\n    /// @notice Require message sender to be an instance owner\n    /// @param _caller {string} Function name that implements this modifier\n    modifier onlyOwner(string memory _caller) {\n        string memory _message = string(\n            abi.encodePacked(\n                \"Account.\",\n                _caller,\n                \": message sender not an owner\"\n            )\n        );\n        require(msg.sender == owner, _message);\n        _;\n    }\n\n    /* -------------------------------------------------------------------- */\n\n    /// @notice Update `Account.name`\n    /// @param _new_name **{string}** Name to assign to `Account.name`\n    /// @custom:throws **{Error}** `\"Account.changeName: message sender not an owner\"`\n    function changeName(string memory _new_name)\n        public\n        onlyOwner(\"changeName\")\n    {\n        name = _new_name;\n    }\n\n    /// @notice Update `Account.owner`\n    /// @param _new_owner **{address}** Address to assign to `Account.owner`\n    /// @custom:throws **{Error}** `\"Account.changeOwner: message sender not an owner\"`\n    function changeOwner(address _new_owner) public onlyOwner(\"changeOwner\") {\n        owner = _new_owner;\n    }\n}\n```\n\n\nAbove the `Account.sol` contract;\n\n\n- stores owner information, such as `name`\n\n- restricts certain mutation actions to owner only\n\n- allows updating stored information by owner\n\n\n[**`contracts/Host.sol`**][source__test__examples__host_sol]\n\n\n```Solidity\n// SPDX-License-Identifier: AGPL-3.0\npragma solidity 0.8.7;\n\nimport {\n    AddressStorage\n} from \"@solidity-utilities/address-storage/contracts/AddressStorage.sol\";\n\nimport {\n    InterfaceAddressStorage\n} from \"@solidity-utilities/address-storage/contracts/InterfaceAddressStorage.sol\";\n\nimport { Account } from \"./Account.sol\";\n\n/// @title Example contract to demonstrate further abstraction of `AddressStorage` features\n/// @author S0AndS0\ncontract Host {\n    address public active_accounts = address(new AddressStorage(address(this)));\n    address public banned_accounts = address(new AddressStorage(address(this)));\n    address public owner;\n\n    /* -------------------------------------------------------------------- */\n\n    ///\n    constructor(address _owner) {\n        owner = _owner;\n    }\n\n    /* -------------------------------------------------------------------- */\n\n    /// @notice Require message sender to be an instance owner\n    /// @param _caller {string} Function name that implements this modifier\n    modifier onlyOwner(string memory _caller) {\n        string memory _message = string(\n            abi.encodePacked(\"Host.\", _caller, \": message sender not an owner\")\n        );\n        require(msg.sender == owner, _message);\n        _;\n    }\n\n    /// @notice Require `_key` to not be stored by `active_accounts`\n    /// @param _key **{address}** Reference to `Account.owner`\n    modifier onlyNotActive(address _key, string memory _caller) {\n        string memory _message = string(\n            abi.encodePacked(\"Host.\", _caller, \": account already active\")\n        );\n        require(!InterfaceAddressStorage(active_accounts).has(_key), _message);\n        _;\n    }\n\n    /// @notice Require `_key` to not be stored by `banned_accounts`\n    /// @param _key **{address}** Reference to `Account.owner`\n    modifier onlyNotBanned(address _key, string memory _caller) {\n        string memory _message = string(\n            abi.encodePacked(\"Host.\", _caller, \": account was banned\")\n        );\n        require(!InterfaceAddressStorage(banned_accounts).has(_key), _message);\n        _;\n    }\n\n    /* -------------------------------------------------------------------- */\n\n    ///\n    event ActivatedAccount(address owner, address account_reference);\n\n    ///\n    event BannedAccount(address owner, address account_reference);\n\n    /* -------------------------------------------------------------------- */\n\n    /// @notice Move `Account` reference from `active_accounts` to `banned_accounts`\n    /// @param _key **{address}** Key within `active_accounts` to ban\n    /// @custom:throws `\"Host.banAccount: not active\"`\n    /// @custom:throws `\"Host.banAccount: already banned\"`\n    function banAccount(address _key) external onlyOwner(\"banAccount\") {\n        address _account_reference = InterfaceAddressStorage(active_accounts)\n            .removeOrError(_key, \"Host.banAccount: not active\");\n        InterfaceAddressStorage(banned_accounts).setOrError(\n            _key,\n            _account_reference,\n            \"Host.banAccount: already banned\"\n        );\n        emit BannedAccount(_key, _account_reference);\n    }\n\n    /// @notice Add existing `Account` instance to `active_accounts`\n    /// @param **{Account}** Previously deployed `Account` contract instance\n    /// @return **{Account}** Instance of `Account`\n    /// @custom:throws `\"Host.importAccount: account already active\"`\n    /// @custom:throws `\"Host.importAccount: account was banned\"`\n    function importAccount(Account _account)\n        public\n        onlyNotActive(_account.owner(), \"importAccount\")\n        onlyNotBanned(_account.owner(), \"importAccount\")\n        returns (Account)\n    {\n        address _owner = _account.owner();\n        address _account_reference = address(_account);\n        InterfaceAddressStorage(active_accounts).set(\n            _owner,\n            _account_reference\n        );\n        emit ActivatedAccount(_owner, _account_reference);\n        return _account;\n    }\n\n    /// @notice Initialize new instance of `Account` and add to `active_accounts`\n    /// @param _owner **{address}** Account owner to assign\n    /// @param _name **{string}** Account name to assign\n    /// @return **{Account}** Instance of `Account` with given `owner` and `name`\n    /// @custom:throws `\"Host.registerAccount: account already active\"`\n    /// @custom:throws `\"Host.registerAccount: account was banned\"`\n    function registerAccount(address _owner, string memory _name)\n        external\n        onlyNotActive(_owner, \"registerAccount\")\n        onlyNotBanned(_owner, \"registerAccount\")\n        returns (Account)\n    {\n        Account _account = new Account(_owner, _name);\n        address _account_reference = address(_account);\n\n        InterfaceAddressStorage(active_accounts).set(\n            _owner,\n            _account_reference\n        );\n        emit ActivatedAccount(_owner, _account_reference);\n\n        return _account;\n    }\n\n    /// @notice Delete reference from either `active_accounts` or `banned_accounts`\n    /// @param _key **{address}** Owner of `Account` instance to remove\n    /// @return **{Account}** Instance from removed value `address`\n    /// @custom:throws `\"Host.removeAccount: message sender not an owner\"`\n    /// @custom:throws `\"Host.removeAccount: account not available\"`\n    function removeAccount(address _key)\n        external\n        onlyOwner(\"removeAccount\")\n        returns (Account)\n    {\n        address _account_reference;\n        if (InterfaceAddressStorage(active_accounts).has(_key)) {\n            _account_reference = InterfaceAddressStorage(active_accounts)\n                .remove(_key);\n        } else if (InterfaceAddressStorage(banned_accounts).has(_key)) {\n            _account_reference = InterfaceAddressStorage(banned_accounts)\n                .remove(_key);\n        }\n\n        require(\n            _account_reference != address(0x0),\n            \"Host.removeAccount: account not available\"\n        );\n\n        return Account(_account_reference);\n    }\n\n    /// @notice Sync `active_accounts` key with `Account.owner`\n    /// @dev Account instance should update `owner` before calling this method\n    /// @param _key **{address}** Old owner `address` to sync with `Account.owner`\n    /// @custom:throws **{Error}** `\"Host.updateKey: message sender not Account owner\"`\n    function updateKey(address _key) external {\n        Account _account = Account(\n            InterfaceAddressStorage(active_accounts).get(_key)\n        );\n        require(\n            msg.sender == _account.owner(),\n            \"Host.updateKey: message sender not Account owner\"\n        );\n        InterfaceAddressStorage(active_accounts).remove(_key);\n        importAccount(_account);\n    }\n\n    /// @notice Retrieve `Account.name` for given `_key`\n    /// @param _key **{address}** Owner of `active_accounts` instance\n    /// @return **{string}** Name saved within `Account` instance\n    /// @custom:throws **{Error}** `\"Host.whoIs: account not active\"`\n    function whoIs(address _key) external view returns (string memory) {\n        address _account_reference = InterfaceAddressStorage(active_accounts)\n            .getOrError(_key, \"Host.whoIs: account not active\");\n        Account _account_instance = Account(_account_reference);\n        return _account_instance.name();\n    }\n}\n```\n\n\nAbove the `Host` contract;\n\n\n- demonstrates how to utilize `InterfaceAddressStorage` within another contract\n\n- maintains mapping of `Account.owner` to `address(Account)` for `active_accounts` and `banned_accounts`\n\n- restricts certain mutation actions to owner only\n\n- provides convenience functions for retrieving information about `Account` instances\n\n\n---\n\n\nThere is much more that can be accomplished by leveraging abstractions provided\nby `AddressStorage`, check the [API][heading__api] section for full set of\nfeatures available. And review the\n[`test/test__examples__Account.js`][source__test__test__examples__account_js]\nand\n[`test/test__examples__Host.js`][source__test__test__examples__host_js]\nfiles for inspiration on how to use these examples within projects.\n\n\n______\n\n\n## API\n[heading__api]:\n  #api\n  \"Application Programming Interfaces for Solidity smart contracts\"\n\n\n\u003e Application Programming Interfaces for Solidity smart contracts\n\n\n---\n\n\n### Contract `AddressStorage`\n[heading__contract_addressstorage]:\n  #contract-addressstorage\n  \"Solidity contract for storing and interacting with key/value address pairs\"\n\n\n\u003e Solidity contract for storing and interacting with key/value address pairs\n\n\n**Source** [`contracts/AddressStorage.sol`][source__contracts__addressstorage_sol]\n\n\n**Properties**\n\n\n- `data` **{mapping(address =\u003e address)}** Store key/value `address` pairs\n\n- `indexes` **{mapping(address =\u003e uint256)}** Warning order of indexes **NOT** guaranteed!\n\n- `keys` **{address[]}** Warning order of keys **NOT** guaranteed!\n\n- `owner` **{address}** Allow mutation or selfdestruct from specified `address`\n\n- `authorized` **{mapping(address =\u003e bool)}** Allow mutation from mapped `address`s\n\n\n**Developer note** -\u003e Depends on\n[`@solidity-utilities/library-mapping-address`][docs__library_mapping_address]\n\n\n---\n\n\n#### Method `addAuthorized`\n[heading__method_addauthorized]:\n  #method-addauthorized\n  \"Insert `address` into `mapping` of `authorized` data structure\"\n\n\n\u003e Insert `address` into `mapping` of `authorized` data structure\n\n\n[**Source**][source__contracts__addressstorage_sol__addauthorized] `addAuthorized(address _key)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Key to set value of `true`\n\n\n**Throws** -\u003e **{Error}** `\"AddressStorage.addAuthorized: message sender not an owner\"`\n\n\n**Developer note** -\u003e Does not check if `address` is already `authorized`\n\n\n---\n\n\n#### Method `changeOwner`\n[heading__method_changeowner]:\n  #method-changeowner\n  \"Overwrite old `owner` with new owner `address`\"\n\n\n\u003e Overwrite old `owner` with new owner `address`\n\n\n[**Source**][source__contracts__addressstorage_sol__changeowner] `changeOwner(address _new_owner)`\n\n\n**Parameters**\n\n\n- `_new_owner` **{address}** New owner address\n\n\n**Throws** -\u003e **{Error}** `\"AddressStorage.changeOwner: message sender not an owner\"`\n\n\n---\n\n\n#### Method `clear`\n[heading__method_clear]:\n  #method-clear\n  \"Delete `mapping` address key/value pairs and remove all `address` from `keys`\"\n\n\n\u003e Delete `mapping` address key/value pairs and remove all `address` from `keys`\n\n\n[**Source**][source__contracts__addressstorage_sol__clear] `clear()`\n\n\n**Throws** -\u003e **{Error}** `\"AddressStorage.clear: message sender not authorized\"`\n\n\n**Developer note** -\u003e **Warning** may fail if storing many `address` pairs\n\n\n---\n\n\n#### Method `deleteAuthorized`\n[heading__method_deleteauthorized]:\n  #method-deleteauthorized\n  \"Remove `address` from `mapping` of `authorized` data structure\"\n\n\n\u003e Remove `address` from `mapping` of `authorized` data structure\n\n\n[**Source**][source__contracts__addressstorage_sol__deleteauthorized] `deleteAuthorized(address _key)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Key to set value of `false`\n\n\n**Throws**\n\n\n- **{Error}** `\"AddressStorage.deleteAuthorized: message sender not authorized\"`\n\n- **{Error}** `\"AddressStorage.deleteAuthorized: cannot remove owner\"`\n\n\n---\n\n\n#### Method `get`\n[heading__method_get]:\n  #method-get\n  \"Retrieve stored value `address` or throws an error if _undefined_\"\n\n\n\u003e Retrieve stored value `address` or throws an error if _undefined_\n\n\n[**Source**][source__contracts__addressstorage_sol__get] `get(address _key)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key `address` to lookup corresponding value `address` for\n\n\n**Returns** -\u003e **{address}** Value for given key `address`\n\n\n**Throws** -\u003e **{Error}** `\"AddressStorage.get: value not defined\"`\n\n\n**Developer note** -\u003e Passes parameter to\n[`data.getOrError`][docs__library_mapping_address__method__getorerror] with\ndefault Error `_reason` to throw\n\n\n---\n\n\n#### Method `getOrElse`\n[heading__method_getorelse]:\n  #method-getorelse\n  \"Retrieve stored value `address` or provided default `address` if _undefined_\"\n\n\n\u003e Retrieve stored value `address` or provided default `address` if _undefined_\n\n\n[**Source**][source__contracts__addressstorage_sol__getorelse] `getOrElse(address _key, address _default)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key `address` to lookup corresponding value `address` for\n\n- `_default` **{address}** Value to return if key `address` lookup is _undefined_\n\n\n**Returns** -\u003e **{address}** Value `address` for given key `address` or `_default` if _undefined_\n\n\n**Developer note** -\u003e Forwards parameters to\n[`data.getOrElse`][docs__library_mapping_address__method__getorelse]\n\n\n---\n\n\n#### Method `getOrError`\n[heading__method_getorerror]:\n  #method-getorerror\n  \"Allow for defining custom error reason if value `address` is _undefined_\"\n\n\n\u003e Allow for defining custom error reason if value `address` is _undefined_\n\n\n[**Source**][source__contracts__addressstorage_sol__getorerror] `getOrError(address _key, string _reason)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key `address` to lookup corresponding value `address` for\n\n- `_reason` **{string}** Custom error message to throw if value `address` is _undefined_\n\n\n**Returns** -\u003e **{address}** Value for given key `address`\n\n\n**Throws** -\u003e **{Error}** `_reason` if value is _undefined_\n\n\n**Developer note** -\u003e Forwards parameters to\n[`data.getOrError`][docs__library_mapping_address__method__getorerror]\n\n\n---\n\n\n#### Method `has`\n[heading__method_has]:\n  #method-has\n  \"Check if `address` key has a corresponding value `address` defined\"\n\n\n\u003e Check if `address` key has a corresponding value `address` defined\n\n\n[**Source**][source__contracts__addressstorage_sol__has] `has(address _key)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key to check if value `address` is defined\n\n\n**Returns** -\u003e **{bool}** `true` if value `address` is defined, or `false` if\n_undefined_\n\n\n**Developer note** -\u003e Forwards parameter to\n[`data.has`][docs__library_mapping_address__method__has]\n\n\n---\n\n\n#### Method `indexOf`\n[heading__method_indexof]:\n  #method-indexof\n  \"Index for `address` key within `keys` array\"\n\n\n\u003e Index for `address` key within `keys` array\n\n\n[**Source**][source__contracts__addressstorage_sol__indexof] `indexOf(address _key)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Key to lookup index for\n\n\n**Returns** -\u003e **{uint256}** Current index for given `_key` within `keys` array\n\n\n**Throws** -\u003e **{Error}** `\"AddressStorage.indexOf: key not defined\"`\n\n\n**Developer note** -\u003e Passes parameter to\n[`indexOfOrError`][heading__method_indexoforerror] with default `_reason`\n\n\n---\n\n\n#### Method `indexOfOrError`\n[heading__method_indexoforerror]:\n  #method-indexoforerror\n  \"Index for `address` key within `keys` array\"\n\n\n\u003e Index for `address` key within `keys` array\n\n\n[**Source**][source__contracts__addressstorage_sol__indexoforerror] `indexOfOrError(address _key, string _reason)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Key to lookup index for\n\n\n**Returns** -\u003e **{uint256}** Current index for given `_key` within `keys` array\n\n\n**Throws** -\u003e **{Error}** `_reason` if value for `_key` is _undefined_\n\n\n**Developer note** -\u003e Cannot depend on results being valid if mutation is\nallowed between calls\n\n\n---\n\n\n#### Method `listKeys`\n[heading__method_listkeys]:\n  #method-listkeys\n  \"Convenience function to read all `mapping` key addresses\"\n\n\n\u003e Convenience function to read all `mapping` key addresses\n\n\n[**Source**][source__contracts__addressstorage_sol__listkeys] `listKeys()`\n\n\n**Returns** -\u003e **{address[]}** Keys `address` array\n\n\n**Developer note** -\u003e Cannot depend on results being valid if mutation is\nallowed between calls\n\n\n---\n\n\n#### Method `remove`\n[heading__method_remove]:\n  #method-remove\n  \"Delete value `address` for given `_key`\"\n\n\n\u003e Delete value `address` for given `_key`\n\n\n[**Source**][source__contracts__addressstorage_sol__remove] `remove(address _key)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key to delete corresponding value `address` for\n\n\n**Returns** -\u003e **{address}** Value `address` that was removed from `data`\nstorage\n\n\n**Throws**\n\n\n- **{Error}** `\"AddressStorage.remove: message sender not authorized\"`\n\n- **{Error}** `\"AddressStorage.remove: value not defined\"`\n\n\n**Developer note** -\u003e Passes parameter to\n[`removeOrError`][heading__method_removeorerror] with default `_reason`\n\n\n---\n\n\n#### Method `removeOrError`\n[heading__method_removeorerror]:\n  #method-removeorerror\n  \"Delete value `address` for given `_key`\"\n\n\n\u003e Delete value `address` for given `_key`\n\n\n[**Source**][source__contracts__addressstorage_sol__removeorerror] `removeOrError(address _key, string _reason)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key to delete corresponding value `address` for\n\n- `_reason` **{string}** Custom error message to throw if value `address` is _undefined_\n\n\n**Returns** -\u003e **{address}** Value `address` that was removed from `data`\nstorage\n\n\n**Throws**\n\n\n- **{Error}** `\"AddressStorage.removeOrError: message sender not authorized\"`\n\n- **{Error}** `_reason` if value is _undefined_\n\n\n**Developer note** -\u003e **Warning** reorders `keys`, and mutates `indexes`, for\nefficiency reasons\n\n\n---\n\n\n#### Method `selfDestruct`\n[heading__method_selfdestruct]:\n  #method-selfdestruct\n  \"Call `selfdestruct` with provided `address`\"\n\n\n\u003e Call `selfdestruct` with provided `address`\n\n\n[**Source**][source__contracts__addressstorage_sol__selfdestruct] `selfDestruct(address payable _to)`\n\n\n**Parameters**\n\n\n- `_to` **{address}** Where to transfer any funds this contract has\n\n\n**Throws** -\u003e **{Error}** `\"AddressStorage.selfDestruct: message sender not an owner\"`\n\n\n---\n\n\n#### Method `set`\n[heading__method_set]:\n  #method-set\n  \"Store `_value` under given `_key` while preventing unintentional overwrites\"\n\n\n\u003e Store `_value` under given `_key` while preventing unintentional overwrites\n\n\n[**Source**][source__contracts__addressstorage_sol__set] `set(address _key, address _value)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key to set corresponding value `address` for\n\n- `_value` **{address}** Mapping value to set\n\n\n**Throws**\n\n\n- **{Error}** `\"AddressStorage.set: message sender not authorized\"`\n\n- **{Error}** `\"AddressStorage.set: value already defined\"`\n\n\n**Developer note** -\u003e Forwards parameters to\n[`setOrError`][heading__method_setorerror] with default `_reason`\n\n\n---\n\n\n#### Method `setOrError`\n[heading__method_setorerror]:\n  #method-setorerror\n  \"Store `_value` under given `_key` while preventing unintentional overwrites\"\n\n\n\u003e Store `_value` under given `_key` while preventing unintentional overwrites\n\n\n[**Source**][source__contracts__addressstorage_sol__setorerror] `setOrError(address _key, address _value, string _reason)`\n\n\n**Parameters**\n\n\n- `_key` **{address}** Mapping key to set corresponding value `address` for\n\n- `_value` **{address}** Mapping value to set\n\n- `_reason` **{string}** Custom error message to present if value `address` is defined\n\n\n**Throws**\n\n\n- **{Error}** `\"AddressStorage.setOrError: message sender not authorized\"`\n\n- **{Error}** `_reason` if value is defined\n\n\n**Developer note** -\u003e Forwards parameters to\n[`data.setOrError`][docs__library_mapping_address__method__setorerror]\n\n\n---\n\n\n#### Method `size`\n[heading__method_size]:\n  #method-size\n  \"Number of key/value `address` pairs currently stored\"\n\n\n\u003e Number of key/value `address` pairs currently stored\n\n\n[**Source**][source__contracts__addressstorage_sol__size] `size()`\n\n\n**Returns** -\u003e **{uint256}** Length of `keys` array\n\n\n**Developer note** -\u003e Cannot depend on results being valid if mutation is\nallowed between calls\n\n\n______\n\n\n## Notes\n[heading__notes]:\n  #notes\n  \"\u0026#x1F5D2; Additional things to keep in mind when developing\"\n\n\n\u003e Additional things to keep in mind when developing\n\n\nIn some cases it may be cheaper for deployment costs to use the\n`library-mapping-address` project directly instead, especially if tracking\ndefined keys is not needed.\n\n\n---\n\n\nThis repository may not be feature complete and/or fully functional, Pull\nRequests that add features or fix bugs are certainly welcomed.\n\n\n______\n\n\n## Contributing\n[heading__contributing]:\n  #contributing\n  \"\u0026#x1F4C8; Options for contributing to address-storage and solidity-utilities\"\n\n\n\u003e Options for contributing to address-storage and solidity-utilities\n\n\n---\n\n\n### Forking\n[heading__forking]:\n  #forking\n  \"\u0026#x1F531; Tips for forking `address-storage`\"\n\n\n\u003e Tips for forking `address-storage`\n\n\nMake a [Fork][address_storage__fork_it] of this repository to an account that\nyou have write permissions for.\n\n\n- Clone fork URL. The URL syntax is _`git@github.com:\u003cNAME\u003e/\u003cREPO\u003e.git`_, then add this repository as a remote...\n\n\n```Bash\nmkdir -p ~/git/hub/solidity-utilities\n\ncd ~/git/hub/solidity-utilities\n\ngit clone --origin fork git@github.com:\u003cNAME\u003e/address-storage.git\n\ngit remote add origin git@github.com:solidity-utilities/address-storage.git\n```\n\n\n- Install development dependencies\n\n\n```Bash\ncd ~/git/hub/solidity-utilities/address-storage\n\nnpm ci\n```\n\n\n\u003e Note, the `ci` option above is recommended instead of `install` to avoid\n\u003e mutating the `package.json`, and/or `package-lock.json`, file(s) implicitly\n\n\n- Commit your changes and push to your fork, eg. to fix an issue...\n\n\n```Bash\ncd ~/git/hub/solidity-utilities/address-storage\n\n\ngit commit -F- \u003c\u003c'EOF'\n:bug: Fixes #42 Issue\n\n\n**Edits**\n\n\n- `\u003cSCRIPT-NAME\u003e` script, fixes some bug reported in issue\nEOF\n\n\ngit push fork main\n```\n\n\n- Then on GitHub submit a Pull Request through the Web-UI, the URL syntax is _`https://github.com/\u003cNAME\u003e/\u003cREPO\u003e/pull/new/\u003cBRANCH\u003e`_\n\n\n\u003e Note; to decrease the chances of your Pull Request needing modifications\n\u003e before being accepted, please check the\n\u003e [dot-github](https://github.com/solidity-utilities/.github) repository for\n\u003e detailed contributing guidelines.\n\n\n---\n\n\n### Sponsor\n  [heading__sponsor]:\n  #sponsor\n  \"\u0026#x1F4B1; Methods for financially supporting `solidity-utilities` that maintains `address-storage`\"\n\n\n\u003e Methods for financially supporting `solidity-utilities` that maintains\n\u003e `address-storage`\n\n\nThanks for even considering it!\n\n\nVia Liberapay you may\n\u003csub\u003e[![sponsor__shields_io__liberapay]][sponsor__link__liberapay]\u003c/sub\u003e on a\nrepeating basis.\n\n\nFor non-repeating contributions Ethereum is accepted via the following public address;\n\n\n    0x5F3567160FF38edD5F32235812503CA179eaCbca\n\n\nRegardless of if you're able to financially support projects such as\n`address-storage` that `solidity-utilities` maintains, please consider sharing\nprojects that are useful with others, because one of the goals of maintaining\nOpen Source repositories is to provide value to the community.\n\n\n______\n\n\n## Change Log\n[heading__change_log]:\n  #change-log\n  \"\u0026#x1f4dc; Note, this section only documents breaking changes or major feature releases\"\n\n\n\u003e Note, this section only documents breaking changes or major feature releases\n\n\n---\n\n\n### Version `0.1.0`\n[heading__version_010]:\n  #version-010\n  \"Make eligible functions `external`\"\n\n\n\u003e Make eligible functions `external`\n\n\n```bash\ngit diff 'v0.1.0' 'v0.0.2'\n```\n\n\n**Developer notes**\n\n\nRecent update to version `0.1.0` of `library-mapping-address` dependency now\nattempts to prevent assigning values of `0x0`\n\n\nFunctions `get`, `has`, and `remove` are now `external` typed. However,\n`getOrError` and `removeOrError` will remain `public` due to code duplication\ncausing _\"out of gas\"_ errors for some use cases.\n\n\n---\n\n\n### Version `0.2.0`\n[heading__version_020]:\n  #version-020\n  \"Allow multiple addresses to mutate `data`\"\n\n\n\u003e Allow multiple addresses to mutate `data`\n\n\n```bash\ngit diff 'v0.2.0' 'v0.1.0'\n```\n\n\n**Developer notes**\n\n\nFunctions `clear`, `remove`, `removeOrError`, `set`, and `setOrError` now\nutilize the `onlyAuthorized` modifier. If using `try`/`catch` and filtering on\nreason, then please update from\n`\"AddressStorage.__name__: message sender not an owner\"`\nto\n`\"AddressStorage.__name__: message sender not authorized\"`\n\n\n**Warning** the `authorized` mapping does not track defined keys, and is\nintended for allowing other smart contract(s) mutation permissions.\n\n\n**Warning** due to code additions of `addAuthorized` and `deleteAuthorized`\ncompiler optimization is currently necessary, eg.\n\n\n[**`truffle-config.js` (snip)**][source__truffle_config_js]\n\n\n```JavaScript\nmodule.exports = {\n  /* ... */\n  compilers: {\n    solc: {\n      version: \"0.8.7\",\n      settings: {\n        optimizer: {\n          enabled: true,\n          runs: 200\n        },\n        /* ... */\n      },\n    },\n  },\n  /* ... */\n};\n```\n\n\n______\n\n\n## Attribution\n[heading__attribution]:\n  #attribution\n  \"\u0026#x1F4C7; Resources that where helpful in building this project so far.\"\n\n\n- [GitHub -- `github-utilities/make-readme`](https://github.com/github-utilities/make-readme)\n\n- [GitHub -- `solidity-utilities/library-mapping-address`](https://github.com/solidity-utilities/library-mapping-address)\n\n- [GitHub -- `actions/setup-node/issues/214`](https://github.com/actions/setup-node/issues/214#issuecomment-810829250)\n\n\n______\n\n\n## License\n[heading__license]:\n  #license\n  \"\u0026#x2696; Legal side of Open Source\"\n\n\n\u003e Legal side of Open Source\n\n\n```\nSolidity contract for storing and interacting with key/value address pairs\nCopyright (C) 2021 S0AndS0\n\nThis program is free software: you can redistribute it and/or modify\nit under the terms of the GNU Affero General Public License as published\nby the Free Software Foundation, version 3 of the License.\n\nThis program is distributed in the hope that it will be useful,\nbut WITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\nGNU Affero General Public License for more details.\n\nYou should have received a copy of the GNU Affero General Public License\nalong with this program.  If not, see \u003chttps://www.gnu.org/licenses/\u003e.\n```\n\n\nFor further details review full length version of\n[AGPL-3.0][branch__current__license] License.\n\n\n\n[branch__current__license]:\n  LICENSE\n  \"\u0026#x2696; Full length version of AGPL-3.0 License\"\n\n\n[badge__commits__address_storage__main]:\n  https://img.shields.io/github/last-commit/solidity-utilities/address-storage/main.svg\n\n[commits__address_storage__main]:\n  https://github.com/solidity-utilities/address-storage/commits/main\n  \"\u0026#x1F4DD; History of changes on this branch\"\n\n\n[address_storage__community]:\n  https://github.com/solidity-utilities/address-storage/community\n  \"\u0026#x1F331; Dedicated to functioning code\"\n\n\n[issues__address_storage]:\n  https://github.com/solidity-utilities/address-storage/issues\n  \"\u0026#x2622; Search for and _bump_ existing issues or open new issues for project maintainer to address.\"\n\n[address_storage__fork_it]:\n  https://github.com/solidity-utilities/address-storage/fork\n  \"\u0026#x1F531; Fork it!\"\n\n[pull_requests__address_storage]:\n  https://github.com/solidity-utilities/address-storage/pulls\n  \"\u0026#x1F3D7; Pull Request friendly, though please check the Community guidelines\"\n\n[address_storage__main__source_code]:\n  https://github.com/solidity-utilities/address-storage/\n  \"\u0026#x2328; Project source!\"\n\n[badge__issues__address_storage]:\n  https://img.shields.io/github/issues/solidity-utilities/address-storage.svg\n\n[badge__pull_requests__address_storage]:\n  https://img.shields.io/github/issues-pr/solidity-utilities/address-storage.svg\n\n[badge__main__address_storage__source_code]:\n  https://img.shields.io/github/repo-size/solidity-utilities/address-storage\n\n\n[badge__github_actions]:\n  https://github.com/solidity-utilities/address-storage/actions/workflows/test.yaml/badge.svg?branch=main\n\n[activity_log__github_actions]:\n  https://github.com/solidity-utilities/address-storage/deployments/activity_log\n\n\n[truffle__package_management_via_npm]:\n  https://www.trufflesuite.com/docs/truffle/getting-started/package-management-via-npm\n  \"Documentation on how to install, import, and interact with Solidity packages\"\n\n\n[docs__library_mapping_address]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md\n  \"`solidity-utilities/library-mapping-address` -- Solidity library for mapping addresses\"\n\n[docs__library_mapping_address__method__get]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-get\n  \"`solidity-utilities/library-mapping-address` -- Retrieves stored value `address` or throws an error if _undefined_\"\n\n[docs__library_mapping_address__method__getorelse]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-getorelse\n  \"`solidity-utilities/library-mapping-address` -- Retrieves stored value `address` or provided default `address` if _undefined_\"\n\n[docs__library_mapping_address__method__getorerror]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-getorerror\n  \"`solidity-utilities/library-mapping-address` -- Allows for defining custom error reason if value `address` is _undefined_\"\n\n[docs__library_mapping_address__method__has]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-has\n  \"`solidity-utilities/library-mapping-address` -- Check if `address` key has a corresponding value `address` defined\"\n\n[docs__library_mapping_address__method__overwrite]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-overwrite\n  \"`solidity-utilities/library-mapping-address` -- Store `_value` under given `_key` **without** preventing unintentional overwrites\"\n\n[docs__library_mapping_address__method__overwriteorError]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-overwriteorerror\n  \"`solidity-utilities/library-mapping-address` -- Store `_value` under given `_key` **without** preventing unintentional overwrites\"\n\n[docs__library_mapping_address__method__remove]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-remove\n  \"`solidity-utilities/library-mapping-address` -- Delete value `address` for given `_key`\"\n\n[docs__library_mapping_address__method__removeorerror]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-removeorerror\n  \"`solidity-utilities/library-mapping-address` -- Delete value `address` for given `_key`\"\n\n[docs__library_mapping_address__method__set]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-set\n  \"`solidity-utilities/library-mapping-address` -- Store `_value` under given `_key` while preventing unintentional overwrites\"\n\n[docs__library_mapping_address__method__setorerror]:\n  https://github.com/solidity-utilities/library-mapping-address/blob/main/README.md#method-setorerror\n  \"`solidity-utilities/library-mapping-address` -- Store `_value` under given `_key` while preventing unintentional overwrites\"\n\n\n[source__test]:\n  test\n  \"CI/CD (Continuous Integration/Deployment) tests and examples\"\n\n[source__test__examples__account_sol]:\n  test/examples/Account.sol\n  \"Solidity code for demonstrating test/examples/Account.sol\"\n\n[source__test__examples__host_sol]:\n  test/examples/Host.sol\n  \"Solidity code for demonstrating test/examples/host.sol\"\n\n[source__test__test__examples__account_js]:\n  test/test__examples__Account.js\n  \"JavaScript code for testing test/examples/Account.sol\"\n\n[source__test__test__examples__host_js]:\n  test/test__examples__Host.js\n  \"JavaScript code for testing test/examples/Host.sol\"\n\n[source__truffle_config_js]:\n  truffle-config.js\n  \"Use this file to configure your truffle project\"\n\n[source__contracts__addressstorage_sol]:\n  contracts/AddressStorage.sol\n  \"Solidity contract for storing and interacting with key/value `address` pairs\"\n\n[source__contracts__addressstorage_sol__addauthorized]:\n  contracts/AddressStorage.sol#L64\n  \"Insert `address` into `mapping` of `authorized` data structure\"\n\n[source__contracts__addressstorage_sol__changeowner]:\n  contracts/AddressStorage.sol#L72\n  \"Overwrite old `owner` with new owner `address`\"\n\n[source__contracts__addressstorage_sol__clear]:\n  contracts/AddressStorage.sol#L79\n  \"Delete `mapping` address key/value pairs and remove all `address` from `keys`\"\n\n[source__contracts__addressstorage_sol__deleteauthorized]:\n  contracts/AddressStorage.sol#L93\n  \"Remove `address` from `mapping` of `authorized` data structure\"\n\n[source__contracts__addressstorage_sol__get]:\n  contracts/AddressStorage.sol#L112\n  \"Retrieve stored value `address` or throws an error if _undefined_\"\n\n[source__contracts__addressstorage_sol__getorelse]:\n  contracts/AddressStorage.sol#L121\n  \"Retrieve stored value `address` or provided default `address` if _undefined_\"\n\n[source__contracts__addressstorage_sol__getorerror]:\n  contracts/AddressStorage.sol#L134\n  \"Allow for defining custom error reason if value `address` is _undefined_\"\n\n[source__contracts__addressstorage_sol__has]:\n  contracts/AddressStorage.sol#L148\n  \"Check if `address` key has a corresponding value `address` defined\"\n\n[source__contracts__addressstorage_sol__indexof]:\n  contracts/AddressStorage.sol#L156\n  \"Index for `address` key within `keys` array\"\n\n[source__contracts__addressstorage_sol__indexoforerror]:\n  contracts/AddressStorage.sol#L165\n  \"Index for `address` key within `keys` array\"\n\n[source__contracts__addressstorage_sol__listkeys]:\n  contracts/AddressStorage.sol#L180\n  \"Convenience function to read all `mapping` key addresses\"\n\n[source__contracts__addressstorage_sol__remove]:\n  contracts/AddressStorage.sol#L187\n  \"Delete value `address` for given `_key`\"\n\n[source__contracts__addressstorage_sol__removeorerror]:\n  contracts/AddressStorage.sol#L201\n  \"Delete value `address` for given `_key`\"\n\n[source__contracts__addressstorage_sol__selfdestruct]:\n  contracts/AddressStorage.sol#L226\n  \"Call `selfdestruct` with provided `address`\"\n\n[source__contracts__addressstorage_sol__set]:\n  contracts/AddressStorage.sol#L236\n  \"Store `_value` under given `_key` while preventing unintentional overwrites\"\n\n[source__contracts__addressstorage_sol__setorerror]:\n  contracts/AddressStorage.sol#L246\n  \"Store `_value` under given `_key` while preventing unintentional overwrites\"\n\n[source__contracts__addressstorage_sol__size]:\n  contracts/AddressStorage.sol#L263\n  \"Number of key/value `address` pairs currently stored\"\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolidity-utilities%2Faddress-storage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsolidity-utilities%2Faddress-storage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsolidity-utilities%2Faddress-storage/lists"}