@lazy-sol/access-control 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
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