@lazy-sol/access-control 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.editorconfig ADDED
@@ -0,0 +1,21 @@
1
+ # EditorConfig is awesome: https://EditorConfig.org
2
+
3
+ # top-most EditorConfig file
4
+ root = true
5
+
6
+ [*]
7
+ charset = utf-8
8
+ end_of_line = lf
9
+ indent_style = tab
10
+ indent_size = 2
11
+ insert_final_newline = true
12
+ max_line_length = 120
13
+
14
+ [*.md]
15
+ indent_size = 4
16
+ tab_width = 4
17
+ indent_style = space
18
+ trim_trailing_whitespace = false
19
+
20
+ [package*.json]
21
+ indent_style = space
package/.solcover.js ADDED
@@ -0,0 +1,39 @@
1
+ // https://hardhat.org/plugins/solidity-coverage.html
2
+ // https://github.com/sc-forks/solidity-coverage#config-options
3
+ module.exports = {
4
+ // Ganache only: ganache-core options
5
+ // https://github.com/trufflesuite/ganache-core/tree/master#options
6
+ /*
7
+ providerOptions: {
8
+ host: "localhost",
9
+ network_id: 0xeeeb04de,
10
+ port: 8669,
11
+ default_balance_ether: 10000,
12
+ total_accounts: 35,
13
+ // gasLimit: 0xffffffff,
14
+ gasPrice: 1,
15
+ },
16
+ */
17
+ // Array of contracts or folders (with paths expressed relative to the contracts directory)
18
+ // that should be skipped when doing instrumentation.
19
+ skipFiles: [
20
+ "interfaces",
21
+ "mocks",
22
+ ],
23
+
24
+ // Set default mocha options here, use special reporters etc.
25
+ mocha: {
26
+ // timeout: 100000,
27
+
28
+ // disable mocha timeouts:
29
+ // https://mochajs.org/api/mocha#enableTimeouts
30
+ enableTimeouts: false,
31
+ // https://github.com/mochajs/mocha/issues/3813
32
+ timeout: false,
33
+
34
+ // https://github.com/sc-forks/solidity-coverage/blob/master/docs/advanced.md#skipping-tests
35
+ grep: "@skip-on-coverage", // Find everything with this tag
36
+ invert: true // Run the grep's inverse set.
37
+ },
38
+
39
+ };
@@ -0,0 +1,200 @@
1
+ # Contribution Guide
2
+
3
+ Thank you for your interest and your will to contribute.
4
+ This document will help you with the guidelines, tips, and advises on how to contribute into the project(s).
5
+
6
+ This guide is intended for both the Public/Community Contributors and core team,
7
+ though the levels of access and processes may slightly differ between these types.
8
+ This will be noted where possible.
9
+
10
+ ## Index
11
+
12
+ - [Getting Started With Smart Contracts](#getting-started-with-smart-contracts)
13
+ - [Reporting Issues](#reporting-issues)
14
+ - [Contributing to the Source Code](#contributing-to-the-source-code)
15
+ - [Frameworks and Tooling Conventions](#frameworks-and-tooling-conventions)
16
+ - [Design Principles](#design-principles)
17
+ - [Pull Requests](#pull-requests)
18
+ - [Commit Policy and Code Review Guideline](#commit-policy-and-code-review-guideline)
19
+ - [Style Guides](#style-guides)
20
+ - [Audit Guide](#audit-guide)
21
+
22
+ ## Getting Started with Smart Contracts
23
+
24
+ Smart Contracts are part of the collection of repositories under the
25
+ [lazy-sol](https://github.com/lazy-sol/).
26
+ Some of these repositories are still private and used only by core team for active development,
27
+ while others have been open sourced and allow for the peer review and public contribution.
28
+ Blockchain layer contains the most crucial and security sensitive part of the business logic of the protocol(s)
29
+ and ecosystem. This includes digital assets (ERC20, ERC721, ERC1155 tokens),
30
+ DeFi protocols (staking, yield farming, vesting, etc.), and other components.
31
+
32
+ ## Reporting Issues
33
+
34
+ Please open an issue in [GitHub](https://github.com/lazy-sol/access-control) if you find a bug or have a feature request.
35
+
36
+ Before submitting a bug report or feature request, double check and make sure it hasn't been submitted already.
37
+
38
+ The more detailed your report is, the faster it can be resolved.
39
+ If you report a bug, please provide steps to reproduce it and source code revision number where this bug reproduces.
40
+
41
+ ## Contributing to the Source Code
42
+
43
+ If you would like to contribute to the code to fix a bug, add a new feature, enhance documentation,
44
+ or otherwise improve the project, pull requests are most welcome.
45
+
46
+ Any code is committed to `develop`, `main`, or `master` branches through pull requests.
47
+
48
+ The code should comply with [Style Guides](docs/style_guides.md), [Design Principles](#design-principles),
49
+ [Frameworks and Tooling Conventions](#frameworks-and-tooling-conventions).
50
+
51
+ Our pull request template contains a [checklist](docs/pull_request_template.md)
52
+ of acceptance criteria for your pull requests.
53
+ Please read it before you start contributing and make sure your contributions adhere to the checklist.
54
+
55
+ ### Frameworks and Tooling Conventions
56
+
57
+ There are standard build and development frameworks, libraries, other tooling that has evolved across the smart contract
58
+ development community in order to facilitate interoperability and consistent development.
59
+
60
+ We require that EVM compatible smart contracts are written in Solidity programming language version 0.8.4 or higher,
61
+ smart contracts tests, deployment scripts, and other supporting scripts are written in ECMAScript 6 or TypeScript.
62
+
63
+ One of the following development frameworks should be used:
64
+
65
+ - [Truffle Suite](https://trufflesuite.com/), including standalone Ganache EVM compatible test node
66
+ - [Hardhat](https://hardhat.org/), including embedded Hardhat Network EVM compatible test node
67
+ - [Foundry](https://github.com/foundry-rs/foundry), including local Anvil EVM compatible test node
68
+
69
+ The use of Hardhat is recommended, you may count on more core team support when you get into any hardhat-related
70
+ issues. Make sure you will be able to resolve such issues on your own if you choose Truffle or Foundry.
71
+
72
+ [web3.js](https://web3js.readthedocs.io/) or [ethers.js](https://docs.ethers.io/) Ethereum JSON-RPC client libraries
73
+ should be used for tests, deployment and other supporting scripts.
74
+ It is recommended to stick to only one of these libraries when possible.
75
+
76
+ When creating a new project its lead developer is free to choose any combination of the frameworks, libraries,
77
+ languages, and other tooling mentioned and not mentioned above.
78
+
79
+ When contributing to existing project one should stick to the frameworks, libraries, languages, and other tooling
80
+ which were already chosen for this project by its lead.
81
+
82
+ As a rule of thumb we try to keep project dependency tree (frameworks, libraries, and other tooling) small, importing
83
+ only the dependencies we have to use.
84
+
85
+ ### Design Principles
86
+
87
+ Smart Contracts are designed to follow industry best-practises for security and maintainability.
88
+
89
+ The protocol is built in the modular way where modules can be attached, detached, upgraded.
90
+
91
+ When designing a new module, one should consider the compromise between reusing already built, audited, deployed,
92
+ and time-tested code (always safer) versus the chances to implement a better, more efficient code (risky!).
93
+ A delicate balance between the two should be maintained:
94
+
95
+ - we don't want to take the unnecessary risks here, neither we don't want to reinvent the wheel;
96
+ - in the same time we're not afraid to propose our vision of how things can be done better, safer, more efficient;
97
+ - we realise that many protocols were developed fast, under time constraint pressure, some things may look
98
+ like a wheel at a first glance, but turn out to be a rough log after looking more carefully (as an example,
99
+ take a look into numerous ERC721 implementations, including the most famous and frequently used ones)
100
+ - we keep in mind our ambition: everything we do targets the highest quality grade, think about
101
+ the decision you make from a "taking responsibility for" perspective, not from "avoiding responsibility for"
102
+ perspective (ex.: "I take responsibility for reusing this ERC721 impl because it was audited 2 times,
103
+ runs in the mainnet for 3 years, it has 10,000+ transaction interactions, its behaviour is fully predictable
104
+ and easy to understand, while its gas inefficiencies are not important in our case since we expect 99.9%
105
+ transactions to happen in L2")
106
+
107
+ Taking into account mentioned above, the following principles should be followed:
108
+
109
+ - if same or similar module was already designed, built, and audited, we should reuse it in whole or in part
110
+ - if we didn't design a similar module in the past (or if we have uncommon parts),
111
+ - we search for same or similar smart contract(s) in the third party protocols, learn from them,
112
+ and design our own based on the take aways we get from the research and our own requirements
113
+ - we may use the third party smart contract(s) as is if it is audited by a respectful entity,
114
+ if it passed our own internal audit, and we think we can't do better in the context of requirements we have
115
+ and time constraints we have
116
+ - third party smart contract libraries such as OpenZeppelin, or other protocols are a good source to learn from,
117
+ they are not always a perfect source to use "as is" when it comes to gas efficiency and simplicity.
118
+
119
+ ### Pull Requests
120
+
121
+ The pull request process has a number of goals:
122
+
123
+ - Maintain the project quality and security levels
124
+ - Allow users to fix problems or add features that they find beneficial
125
+ - Engage the community in working toward the best possible code
126
+ - Enable a sustainable system for core team to review and facilitate public contributions
127
+
128
+ Please follow these steps to have your contribution considered by the maintainers:
129
+
130
+ 1. Verify that your pull request contain only the changes related to the issue it solves;
131
+ if you find the opposite, split it into separate pull requests, so that each of them
132
+ corresponds to exactly one issue or feature
133
+ 2. Make sure you follow the [Style Guides](docs/style_guides.md),
134
+ [Design Principles](#design-principles),
135
+ [Frameworks and Tooling Conventions](#frameworks-and-tooling-conventions), and
136
+ [Commit Policy](docs/commit_policy.md)
137
+ 3. Ensure that all existing tests pass, and that code coverage has not diminished
138
+ 4. Write any new tests to cover your added functionality
139
+ 1. Test coverage must not be formal, but functional
140
+ 2. Pay attention to all possible corner cases, flowing from the requirements
141
+ 3. Don't hesitate to implement parameterized tests which are then run several times using different inputs
142
+ 5. Check if deployment scripts, hardhat tasks, other supporting scripts, etc. require modifications, or if
143
+ new scripts must be introduced to support the code and functionality added
144
+ 6. Ensure the code submitted includes a comprehensive documentation
145
+ 1. Any Solidity contract should have a Soldoc header describing the purpose of the contract or module,
146
+ its role and place in the overall architecture of the protocol
147
+ 2. Any Solidity contract function should have an appropriate Soldoc description:
148
+ 1. Public functions description should be written taking into account that these functions can be accessed
149
+ not only by blockchain engineers, but also by less technical people
150
+ 2. All descriptions should clearly explain what function does, what are input and output parameters,
151
+ what are valid and invalid corner cases, what is the function access policy
152
+ 3. Tests should have brief explanation in the file headers regarding what they apply to
153
+ 4. Tests should be minimalistic (1-2 lines of code per test) and self-explanatory:
154
+ 1. A failing test should point to the problem without a need to open and read test case code
155
+ 2. Self-explanatory test cases doesn't require additional documentation
156
+ 5. Check if root [README](README.md), or other documentation files require update(s)
157
+
158
+ The reviewer(s) may ask you to complete additional design work, tests, or other changes before your pull request can be
159
+ ultimately accepted.
160
+ Public submission of features may not always be approved if they do not align with the product goals of the core team.
161
+
162
+ ### Commit Policy and Code Review Guideline
163
+
164
+ This section describes in detail branch and commit naming, opening a pull request, reviewing it, merging, and other
165
+ topics related to the development workflow.
166
+
167
+ It is available as a separate document [Where and How to Commit Your Work](docs/commit_policy.md)
168
+
169
+ ### Style Guides
170
+
171
+ This section describes in detail programming conventions, style, and best practices for writing code, tests, etc..
172
+
173
+ It is available as a separate document [Style Guides](docs/style_guides.md)
174
+
175
+ ## Audit Guide
176
+
177
+ To ensure code quality is maintained, we ensure that there is an internal audit process for any project implemented
178
+ or smart contract introduced or modified.
179
+
180
+ Ideally, internal audit happens after the project is fully developed, when no significant smart contract changes are
181
+ expected to happen, right before the external audit is executed.
182
+
183
+ Auditor must have no conflict of interest and should be able to perform the audit independently.
184
+
185
+ There should be an immutable (ex.: committed into github) audit trail that
186
+
187
+ - includes trace of audit findings, their severity, applicability, resolution and possibly re-audit
188
+ - covers the involved systems: messengers, github, etc.
189
+
190
+ The process applies only to internal audits, as external auditors will have their own process.
191
+
192
+ See also:
193
+ - [Introduction to Auditing and our smart contract audit process](https://extropy-io.medium.com/introduction-to-auditing-and-our-smart-contract-audit-process-fa7aed2d5d3d)
194
+ - [The Solcurity Security and Code Quality Standard](https://github.com/transmissions11/solcurity)
195
+
196
+ ## About
197
+
198
+ Prepared by Basil Gorin
199
+
200
+ (c) 2017–2024 Basil Gorin
@@ -0,0 +1,26 @@
1
+ Licensing inclusion for test & contract code:
2
+
3
+
4
+ The MIT License (MIT)
5
+
6
+ Copyright (c) 2016-2020 zOS Global Limited
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining
9
+ a copy of this software and associated documentation files (the
10
+ "Software"), to deal in the Software without restriction, including
11
+ without limitation the rights to use, copy, modify, merge, publish,
12
+ distribute, sublicense, and/or sell copies of the Software, and to
13
+ permit persons to whom the Software is furnished to do so, subject to
14
+ the following conditions:
15
+
16
+ The above copyright notice and this permission notice shall be included
17
+ in all copies or substantial portions of the Software.
18
+
19
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+
package/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017-2024 Basil Gorin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included
14
+ in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # Role-based Access Control (RBAC) #
2
+ A shortcut to a modular and easily pluggable dapp architecture.
3
+
4
+ Enable the modular plug and play (PnP) architecture for your dapp by incorporating the role-based access control (RBAC)
5
+ into the smart contracts.
6
+
7
+ ## Installation
8
+ ```
9
+ npm i -D @lazy-sol/access-control
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ### Creating a Restricted Function
15
+
16
+ Restricted function is a function with a `public` Solidity modifier access to which is restricted
17
+ so that only a pre-configured set of accounts can execute it.
18
+
19
+ 1. Enable role-based access control (RBAC) in a new smart contract
20
+ by inheriting the RBAC contract from the [AccessControl](./contracts/AccessControl.sol) contract:
21
+ ```solidity
22
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
23
+ import "@lazy-sol/access-control/contracts/AccessControl.sol";
24
+
25
+ /**
26
+ * @title Simple ERC20 Implementation
27
+ *
28
+ * @notice Zeppelin based ERC20 implementation with the RBAC support
29
+ *
30
+ * @author Lazy So[u]l
31
+ */
32
+ contract MyERC20Token is ERC20, AccessControl {
33
+
34
+ ...
35
+
36
+ }
37
+ ```
38
+
39
+ 2. Define an access control role with the unique integer value:
40
+ ```solidity
41
+ ...
42
+
43
+ /**
44
+ * @notice Token creator is responsible for creating (minting)
45
+ tokens to an arbitrary address
46
+ * @dev Role ROLE_TOKEN_CREATOR allows minting tokens
47
+ (calling `mint` function)
48
+ */
49
+ uint32 public constant ROLE_TOKEN_CREATOR = 0x0001_0000;
50
+
51
+ ...
52
+ ```
53
+
54
+ 3. Add the `require(isSenderInRole(ROLE_TOKEN_CREATOR), "access denied")"` check into the function body:
55
+ ```solidity
56
+ ...
57
+
58
+ /**
59
+ * @inheritdoc ERC20
60
+ */
61
+ function _mint(address _to, uint256 _value) internal virtual override {
62
+ // check if caller has sufficient permissions to mint tokens
63
+ require(isSenderInRole(ROLE_TOKEN_CREATOR), "access denied");
64
+
65
+ // delegate to super implementation
66
+ super._mint(_to, _value);
67
+ }
68
+
69
+ ...
70
+ ```
71
+
72
+ Note: you could also use the `restrictedTo` modifier in the function declaration instead of the `require`
73
+ in the function body if you don't need a custom error message:
74
+ ```solidity
75
+ ...
76
+
77
+ /**
78
+ * @inheritdoc ERC20
79
+ */
80
+ function _mint(address _to, uint256 _value) internal virtual override restrictedTo(ROLE_TOKEN_CREATOR) {
81
+ // delegate to super implementation
82
+ super._mint(_to, _value);
83
+ }
84
+
85
+ ...
86
+ ```
87
+
88
+ Examples:
89
+ [ERC20Impl](https://raw.githubusercontent.com/vgorin/solidity-template/master/contracts/token/ERC20Impl.sol),
90
+ [ERC721Impl](https://raw.githubusercontent.com/vgorin/solidity-template/master/contracts/token/ERC721Impl.sol).
91
+
92
+ ### Adopting an Already Deployed OZ Ownable Contract to the RBAC Model
93
+
94
+ [OpenZeppelin Ownable](https://docs.openzeppelin.com/contracts/2.x/access-control#ownership-and-ownable)
95
+ is one of the most popular access control models since it is very easy to understand and to use.
96
+ Many deployed contracts are using this model, and when the time comes to switch to a more flexible model,
97
+ [OwnableToAccessControlAdapter](./contracts/OwnableToAccessControlAdapter.sol) comes into play.
98
+
99
+ #### Installation Flow
100
+
101
+ Prerequisite: deployed OZ Ownable contract (target contract) address (target_address)
102
+
103
+ 1. Deploy the AccessControl Adapter bound to the already deployed OZ Ownable contract
104
+ (specify the target OZ Ownable contract address in the constructor upon the deployment)
105
+ ```javascript
106
+ const adapter = await (artifacts.require("OwnableToAccessControlAdapter")).new(target_address);
107
+ ```
108
+
109
+ 2. Define what Ownable-restricted public functions on the target contract you'd like to be able
110
+ to provide access to through the adapter contract
111
+
112
+ 3. Map every such function with the role required to execute it using `updateAccessRole()` function
113
+ For example, to be able to provide an access to the transferOwnership(address) function, you could do
114
+ ```javascript
115
+ const ROLE_TRANSFER_OWNERSHIP_MANAGER = 0x00010000;
116
+ await adapter.updateAccessRole("transferOwnership(address)", ROLE_TRANSFER_OWNERSHIP_MANAGER);
117
+ ```
118
+
119
+ 4. Provide the roles to the corresponding operators as you would usually do with AccessControl
120
+ For example, if you wish an address 0x00000000000000000000000000000000000Ff1CE to grant an access to the
121
+ transferOwnership(address) function on the target, you could do
122
+ ```javascript
123
+ const operator = "0x00000000000000000000000000000000000Ff1CE";
124
+ await adapter.updateRole(operator, ROLE_TRANSFER_OWNERSHIP_MANAGER);
125
+ ```
126
+
127
+ 5. Transfer the ownership of the target contract to the deployed AccessControl Adapter contract
128
+ Note that you can also do steps 2-4 after the step 5
129
+
130
+ #### Usage Flow
131
+
132
+ Prerequisite: installed AccessControl Adapter with the access to at least one restricted target contract
133
+ function configured
134
+
135
+ To execute the restricted access function on the target contract via the AccessControl Adapter
136
+ 1. Use target contract ABI to construct a low-level function call calldata
137
+ For example, to construct the transferOwnership() function calldata to transfer the ownership to the
138
+ 0x00000000000000000000000000000000DEAdc0De address, you could do
139
+ ```javascript
140
+ const to = "0x00000000000000000000000000000000DEAdc0De";
141
+ const calldata = target.contract.methods.transferOwnership(to).encodeABI();
142
+ ```
143
+
144
+ 2. Execute a low-level function call on the AccessControl Adapter contract using the constructed calldata
145
+ For example, to execute the transferOwnership() function (prepared in step 1), you could do
146
+ ```javascript
147
+ await web3.eth.sendTransaction({
148
+ from: operator,
149
+ to: adapter.address,
150
+ data: calldata,
151
+ }
152
+ ```
153
+
154
+ 3. It is also ok to add an ether to the transaction by adding a value field to the `sendTransaction` call,
155
+ as well as sending plain ether transfer transaction, as long as target contract has payable functions,
156
+ and/or has a default payable receiver
157
+
158
+ ## Contributing
159
+ Please see the [Contribution Guide](./CONTRIBUTING.md) document to get understanding on how to report issues,
160
+ contribute to the source code, fix bugs, introduce new features, etc.
161
+
162
+ (c) 2017–2024 Basil Gorin