@lazy-sol/access-control 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,240 @@
1
+ # Style Guides
2
+
3
+ A programming style guide is an opinionated guide of programming conventions, style, and best practices for a
4
+ team or project.
5
+
6
+ This section breaks into several subsections depending on the programming, scripting, and markup languages used.
7
+ When new language is added to the project, one should also add a corresponding style guide subsection to this section.
8
+
9
+ For each language we use, a style guide is based on one or more widely used style guides. When several reference
10
+ guides are used, we assume that the first one is a basic one, and next ones supplement it (contradicting rules
11
+ in the next ones are ignored).
12
+
13
+ There are always controversial rules leading to endless debates, these rules are more a matter of taste, than a
14
+ rational thing. One of the examples is a famous endless "tabs vs spaces debate".
15
+ For each style guide we maintain the list of these controversial rules together with overridden rules.
16
+
17
+ This is yet another element for encouraging people to lead a project.
18
+ You get a chance to demonstrate in practice how the rules you've chosen help the development, readability, maintainability, etc.
19
+
20
+ ## JavaScript
21
+
22
+ JavaScript is a non-class based object oriented programming language that is one of the core technologies of the
23
+ World Wide Web.
24
+ JavaScript was developed in September 1995 by a Netscape programmer Brandan Eich.
25
+ It was originally named Mocha, but quickly became known as LiveScript and, later, JavaScript.
26
+
27
+ JavaScript's syntax and naming conventions are similar to Java, for example both languages use camelCase to name
28
+ functions and variables, PascalCase for class names, UPPER_CASE for constants.
29
+ JavaScript, however, is not so strict: programs using snake_case instead of camelCase can also be seen widely.
30
+
31
+ We use [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript) as a base.
32
+ Following rules are considered contentious (to be extended) and/or are overridden:
33
+
34
+ - [Whitespace](https://github.com/airbnb/javascript#whitespace)
35
+ - use of soft tabs (space character) set to 2 spaces (eslint: indent)
36
+ - **no** spaces inside curly braces (eslint: object-curly-spacing: **"never"**)
37
+ **reason:** monospace fonts have already enough spare space in braces, commas, dots, etc.
38
+ to make these symbols clearly distinguishable from the literals' symbols
39
+ - characters per line limit (eslint: max-len): **120**
40
+ **reason:**: most of the screens allow to easily see 120 characters in one line
41
+ - [Blocks](https://github.com/airbnb/javascript#blocks)
42
+ - `else` statements in an `if-else` construct, as well as `catch` and `finally`,
43
+ must be **on its own line** after the preceding closing brace (eslint: brace-style: **"stroustrup"**)
44
+ **reason:** this makes `if-else` blocks better distinguishable when statements inside are very short
45
+ - [Naming Conventions](https://github.com/airbnb/javascript#naming-conventions)
46
+ - camelCase naming for objects, functions, and instances (eslint: camelcase)
47
+
48
+ ## TypeScript
49
+
50
+ TypeScript is a strongly typed programming language that builds on JavaScript, developed by Microsoft, published
51
+ in 2012.
52
+
53
+ TypeScript style guide inherits from [JavaScript](#javascript) and is enriched with
54
+ [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html), which is used basically
55
+ to cover areas not covered in [Airbnb Javascript Style Guide](https://github.com/airbnb/javascript).
56
+
57
+ ## Solidity
58
+
59
+ Solidity is an object-oriented programming language for implementing smart contracts.
60
+ Solidity was proposed in August 2014 by Dr. Gavin Wood.
61
+ As specified by Dr. Gavin Wood, Solidity is designed around the JavaScript syntax to make it familiar for existing web
62
+ developers.
63
+
64
+ Solidity inherits its syntax and naming conventions from JavaScript. Both languages use camelCase naming for
65
+ functions and variables, PascalCase for class names, UPPER_CASE for constants.
66
+
67
+ We use [Official Solidity Style Guide](https://docs.soliditylang.org/en/v0.8.16/style-guide.html) as a base,
68
+ enriched with [Official Java Code Conventions](https://www.oracle.com/technetwork/java/codeconventions-150003.pdf)
69
+ (for example, Official Solidity Guide misses ideas on interface naming).
70
+ Following rules are considered contentious and/or are overridden:
71
+
72
+ - Tabs or Spaces: spaces are the preferred indentation method
73
+ - `else` statements in an `if-else` construct must be **on its own line** after the preceding closing brace
74
+
75
+ Prefer `Interface` naming to Zeppelin's `IInterface` one.
76
+ Name the interface by answering the question "what it is?", based on functional requirements. A `Truck`.
77
+ Name the implementation contract by answering the question "how it works?", or "what it looks like?",
78
+ based on non-functional requirements. A `RedTruck`.
79
+ ERC standards like ERC20, ERC721, and others are effectively interfaces already and do not require an "I" prefix.
80
+
81
+ Bad:
82
+
83
+ ```
84
+ interface IPriceOracle {
85
+ ...
86
+ }
87
+ contract PriceOracle is IPriceOracle {
88
+ ...
89
+ }
90
+ ```
91
+
92
+ Good:
93
+
94
+ ```
95
+ interface PriceOracle {
96
+ ...
97
+ }
98
+ contract PriceOracleV1 is PriceOracle {
99
+ ...
100
+ }
101
+ ```
102
+
103
+ Bad:
104
+
105
+ ```
106
+ interface IERC20 {
107
+ ...
108
+ }
109
+ contract Token is IERC20 {
110
+ ...
111
+ }
112
+ ```
113
+
114
+ Good:
115
+
116
+ ```
117
+ interface ERC20 {
118
+ ...
119
+ }
120
+ contract Token is ERC20 {
121
+ ...
122
+ }
123
+ ```
124
+
125
+ ## Markdown
126
+
127
+ Markdown is a lightweight markup language created by John Gruber and Aaron Swartz in 2004 with the goal to be
128
+ appealing to human readers in its source code form. Markdown was standardized in 2012-2016.
129
+
130
+ We use [Google Markdown Style Guide](https://google.github.io/styleguide/docguide/style.html) as a base,
131
+ enriched with [Matt Cone Markdown Style Guide](https://www.markdownguide.org/basic-syntax/).
132
+ Following rules are considered contentious and/or are overridden:
133
+
134
+ - [Trailing whitespace](https://google.github.io/styleguide/docguide/style.html#trailing-whitespace)
135
+ / [Line Breaks Best Practices](https://www.markdownguide.org/basic-syntax/#line-break-best-practices):
136
+ don't use the trailing backslash, use trailing whitespace and ensure .editorconfig has
137
+ `trim_trailing_whitespace = false` for `*.md` files
138
+
139
+ ## Automating Formatting Standards
140
+
141
+ The above standards can be more easily met by automating their implementation.
142
+ Many repositories will have a `.editorconfig` file, which tells editors how to interpret inputs, such as tab.
143
+ The EditorConfig file is read automatically by many IDEs, including WebStorm, IntellijIDEA and Visual Studio,
144
+ but is **not** picked up automatically by many even related tools including PHPStorm, Sublime, Eclipse,
145
+ and Visual Studio Code: a [supporting plugin](https://editorconfig.org/) should be used.
146
+ You should ensure your IDE setup supports these editor expectations.
147
+
148
+ Optionally you may additionally use Prettier or a similar formatter.
149
+ Prettier is an opinionated code formatter, which uses sensible defaults that can often (but not always)
150
+ be overridden in a `.prettierrc` file.
151
+ Prettier will also inspect `.editorconfig` files and use those settings as its defaults.
152
+ Note that Visual Studio Code includes Prettier formatter by default, and its Format command triggers it.
153
+ It can also be configured to trigger on-save.
154
+
155
+ Prettier should **not** be used on existing projects that already have an established standard.
156
+
157
+ Finally, a _linter_ such as eslint or solhint may be a good option to be used.
158
+ Linters dynamically inspect code and point out potential issues.
159
+ This can include style issues as above but also code quality issues like unused variables,
160
+ deprecated functions, unreachable code, etc.
161
+ Installing the solidity plugin for Visual Studio Code automatically installs a linter.
162
+
163
+ Note that the above tools can all be used together. EditorConfig works as you type, ensuring you meet standards,
164
+ Prettier formats your code after you write it, while linters highlight, but do not fix, potential quality issues.
165
+
166
+ ## Testing Standards and Style Guidelines
167
+
168
+ Testing smart contracts is of critical importance. Tests are used to validate security requirements,
169
+ and to confirm behaviour to be as expected and intended.
170
+ Proper testing of any software is a difficult skill that takes a long time to learn. Here are some important guides.
171
+
172
+ **Unit testing** is intended to test a single, specific behaviour, such as a function.
173
+ In the context of smart contracts this typically means to execute a function and then check the resulting state
174
+ and events emitted.
175
+
176
+ Unit testing forms the vast majority of test cases and requires large numbers of simple tests,
177
+ with each test verifying a single aspect of behaviour.
178
+ It should be possible for any failed test to immediately identify the error.
179
+
180
+ Unit tests are often built in a way phrased as _arrange-act-assert_.
181
+ Arrange is the process to set up the contract to a suitable initial state.
182
+ Act is executing the desired function.
183
+ Assert is verifying the state changes occurred and events emitted.
184
+
185
+ Arrange steps **do not belong to the test function** and should be implemented as part of a `beforeEach` or similar
186
+ hook which sets up the state for all the tests.
187
+ Use `describe` blocks to separate test functionality that has different state setup.
188
+
189
+ It is vitally important that tests are not an afterthought, but a key part of the development deliverable.
190
+ This means that the test should cover not just "the behaviour", but edge cases, error handling, permission checking,
191
+ bounds-checking and other similar difficulties. "Happy path" testing is of minimal value.
192
+
193
+ Some important points on unit tests:
194
+
195
+ - Only test one thing at a time - do not run compound tests
196
+ - Each test must be independent
197
+ - Consider making utility functions for things like state setup to ensure simplicity and consistency
198
+ - Separate contracts by a file and only test one contract per file
199
+ - Separate functionality areas with `describe` blocks, and note you can nest these blocks for sub-functionality
200
+ - Tests should be as small as possible, ideally only one line, or a few lines
201
+ - You can append `.only` to a test case while implementing it, to isolate that one test (not to run the whole suite
202
+ during the test development), though keep in mind that the entire suite must also work
203
+ - Do not add suite setup to `beforeEach`, as this will run before every test.
204
+ For example, getting all the accounts from the provider can be implemented either as global function, or if
205
+ using async mode - can be run in the `before` hook, which runs one single time.
206
+ - Ensure the test checks function execution constraints (contract state, function input params, access control), smart
207
+ contract state change(s), event emission(s)
208
+ - Favour constants (or TypeScript enums) for testing values, as they can convey meaning and be reused as the
209
+ assertion value
210
+
211
+ Many areas of functionality may also implement an end-to-end test, where multiple steps are undertaken in order
212
+ to ensure a cohesive and correct workflow.
213
+ These typically act as a "sanity check" to verify complex behaviours work as intended.
214
+ Such tests supplement, but do not replace, comprehensive unit tests.
215
+
216
+ Code Coverage reports can be generated with `npm run coverage`.
217
+ Reports show the coverage as a percentage of lines covered with tests.
218
+ It is important to ensure this is not reduced by your modifications.
219
+ It is also important the testing is not done **solely** to increase the test coverage percentage.
220
+ Instead, the code coverage outputs are used to highlight areas where tests are lacking.
221
+ The coverage reports generate output artifacts that show line-by-line where code is untested,
222
+ as well as summaries by files overall.
223
+
224
+ When beginning a new block of work you should ensure that you run the coverage report prior to starting
225
+ to ensure your changes do not lower the code coverage.
226
+
227
+ See also: [Gitlab Testing Standards](https://docs.gitlab.com/ee/development/testing_guide/)
228
+
229
+ ## References
230
+ 1. Srđan Popić, Gordana Velikić at al.
231
+ The Benefits of the Coding Standards Enforcement and it's Influence on the
232
+ Developers' Coding Behaviour: A Case Study on Two Small Projects
233
+ 2. [Coding standards: what are they, and why do you need
234
+ them](https://blog.codacy.com/coding-standards-what-are-they-and-why-do-you-need-them/)
235
+
236
+ ## About
237
+
238
+ Prepared by Basil Gorin
239
+
240
+ (c) 2017–2024 Basil Gorin
@@ -0,0 +1,359 @@
1
+ /**
2
+ * default Hardhat configuration which uses account mnemonic to derive accounts
3
+ * script expects following environment variables to be set:
4
+ * - P_KEY1 – mainnet private key, should start with 0x
5
+ * or
6
+ * - MNEMONIC1 – mainnet mnemonic, 12 words
7
+ *
8
+ * - P_KEY3 – ropsten private key, should start with 0x
9
+ * or
10
+ * - MNEMONIC3 – ropsten mnemonic, 12 words
11
+ *
12
+ * - P_KEY4 – rinkeby private key, should start with 0x
13
+ * or
14
+ * - MNEMONIC4 – rinkeby mnemonic, 12 words
15
+ *
16
+ * - P_KEY41 – kovan private key, should start with 0x
17
+ * or
18
+ * - MNEMONIC41 – kovan mnemonic, 12 words
19
+ *
20
+ * - P_KEY5 – goerli private key, should start with 0x
21
+ * or
22
+ * - MNEMONIC5 – goerli mnemonic, 12 words
23
+ *
24
+ * - P_KEY137 – polygon/matic private key, should start with 0x
25
+ * or
26
+ * - MNEMONIC137 – polygon/matic mnemonic, 12 words
27
+ *
28
+ * - P_KEY80001 – mumbai (polygon testnet) private key, should start with 0x
29
+ * or
30
+ * - MNEMONIC80001 – mumbai (polygon testnet) mnemonic, 12 words
31
+ *
32
+ * - P_KEY56 – Binance Smart Chain (BSC) mainnet private key, should start with 0x
33
+ * or
34
+ * - MNEMONIC56 – Binance Smart Chain (BSC) mainnet mnemonic, 12 words
35
+ *
36
+ * - P_KEY97 – Binance Smart Chain (BSC) testnet private key, should start with 0x
37
+ * or
38
+ * - MNEMONIC97 – Binance Smart Chain (BSC) testnet mnemonic, 12 words
39
+ *
40
+ * - ALCHEMY_KEY – Alchemy API key
41
+ * or
42
+ * - INFURA_KEY – Infura API key (Project ID)
43
+ *
44
+ * - ETHERSCAN_KEY – Etherscan API key
45
+ *
46
+ * - POLYSCAN_KEY – polygonscan API key
47
+ *
48
+ * - BSCSCAN_KEY – BscScan API key
49
+ *
50
+ * - REPORT_GAS - optional, set it to true to print gas usage info
51
+ */
52
+
53
+ // Enable Truffle 5 plugin for tests
54
+ // https://hardhat.org/guides/truffle-testing.html
55
+ require("@nomiclabs/hardhat-truffle5");
56
+
57
+ // enable Solidity-coverage
58
+ // https://hardhat.org/plugins/solidity-coverage.html
59
+ require("solidity-coverage");
60
+
61
+ // enable hardhat-gas-reporter
62
+ // https://github.com/cgewecke/hardhat-gas-reporter
63
+ require("hardhat-gas-reporter");
64
+
65
+ // adds a mechanism to deploy contracts to any network,
66
+ // keeping track of them and replicating the same environment for testing
67
+ // https://www.npmjs.com/package/hardhat-deploy
68
+ require("hardhat-deploy");
69
+
70
+ // verify environment setup, display warning if required, replace missing values with fakes
71
+ const FAKE_MNEMONIC = "test test test test test test test test test test test junk";
72
+ if(!process.env.MNEMONIC1 && !process.env.P_KEY1) {
73
+ console.warn("neither MNEMONIC1 nor P_KEY1 is not set. Mainnet deployments won't be available");
74
+ process.env.MNEMONIC1 = FAKE_MNEMONIC;
75
+ }
76
+ else if(process.env.P_KEY1 && !process.env.P_KEY1.startsWith("0x")) {
77
+ console.warn("P_KEY1 doesn't start with 0x. Appended 0x");
78
+ process.env.P_KEY1 = "0x" + process.env.P_KEY1;
79
+ }
80
+ if(!process.env.MNEMONIC3 && !process.env.P_KEY3) {
81
+ console.warn("neither MNEMONIC3 nor P_KEY3 is not set. Ropsten deployments won't be available");
82
+ process.env.MNEMONIC3 = FAKE_MNEMONIC;
83
+ }
84
+ else if(process.env.P_KEY3 && !process.env.P_KEY3.startsWith("0x")) {
85
+ console.warn("P_KEY3 doesn't start with 0x. Appended 0x");
86
+ process.env.P_KEY3 = "0x" + process.env.P_KEY3;
87
+ }
88
+ if(!process.env.MNEMONIC4 && !process.env.P_KEY4) {
89
+ console.warn("neither MNEMONIC4 nor P_KEY4 is not set. Rinkeby deployments won't be available");
90
+ process.env.MNEMONIC4 = FAKE_MNEMONIC;
91
+ }
92
+ else if(process.env.P_KEY4 && !process.env.P_KEY4.startsWith("0x")) {
93
+ console.warn("P_KEY4 doesn't start with 0x. Appended 0x");
94
+ process.env.P_KEY4 = "0x" + process.env.P_KEY4;
95
+ }
96
+ if(!process.env.MNEMONIC42 && !process.env.P_KEY42) {
97
+ console.warn("neither MNEMONIC42 nor P_KEY42 is not set. Kovan deployments won't be available");
98
+ process.env.MNEMONIC42 = FAKE_MNEMONIC;
99
+ }
100
+ else if(process.env.P_KEY42 && !process.env.P_KEY42.startsWith("0x")) {
101
+ console.warn("P_KEY42 doesn't start with 0x. Appended 0x");
102
+ process.env.P_KEY42 = "0x" + process.env.P_KEY42;
103
+ }
104
+ if(!process.env.MNEMONIC5 && !process.env.P_KEY5) {
105
+ console.warn("neither MNEMONIC5 nor P_KEY5 is not set. Goerli deployments won't be available");
106
+ process.env.MNEMONIC5 = FAKE_MNEMONIC;
107
+ }
108
+ else if(process.env.P_KEY5 && !process.env.P_KEY5.startsWith("0x")) {
109
+ console.warn("P_KEY5 doesn't start with 0x. Appended 0x");
110
+ process.env.P_KEY5 = "0x" + process.env.P_KEY5;
111
+ }
112
+ if(!process.env.MNEMONIC137 && !process.env.P_KEY137) {
113
+ console.warn("neither MNEMONIC137 nor P_KEY137 is not set. Polygon mainnet deployments won't be available");
114
+ process.env.MNEMONIC137 = FAKE_MNEMONIC;
115
+ }
116
+ else if(process.env.P_KEY137 && !process.env.P_KEY137.startsWith("0x")) {
117
+ console.warn("P_KEY137 doesn't start with 0x. Appended 0x");
118
+ process.env.P_KEY137 = "0x" + process.env.P_KEY137;
119
+ }
120
+ if(!process.env.MNEMONIC80001 && !process.env.P_KEY80001) {
121
+ console.warn("neither MNEMONIC80001 nor P_KEY80001 is not set. Mumbai (matic/polygon L2 testnet) deployments won't be available");
122
+ process.env.MNEMONIC80001 = FAKE_MNEMONIC;
123
+ }
124
+ else if(process.env.P_KEY80001 && !process.env.P_KEY80001.startsWith("0x")) {
125
+ console.warn("P_KEY80001 doesn't start with 0x. Appended 0x");
126
+ process.env.P_KEY80001 = "0x" + process.env.P_KEY80001;
127
+ }
128
+ if(!process.env.MNEMONIC56 && !process.env.P_KEY56) {
129
+ console.warn("neither MNEMONIC56 nor P_KEY56 is not set. Binance Smart Chain (BSC) mainnet deployments won't be available");
130
+ process.env.MNEMONIC56 = FAKE_MNEMONIC;
131
+ }
132
+ else if(process.env.P_KEY56 && !process.env.P_KEY56.startsWith("0x")) {
133
+ console.warn("P_KEY56 doesn't start with 0x. Appended 0x");
134
+ process.env.P_KEY56 = "0x" + process.env.P_KEY56;
135
+ }
136
+ if(!process.env.MNEMONIC97 && !process.env.P_KEY97) {
137
+ console.warn("neither MNEMONIC97 nor P_KEY97 is not set. Binance Smart Chain (BSC) testnet deployments won't be available");
138
+ process.env.MNEMONIC97 = FAKE_MNEMONIC;
139
+ }
140
+ else if(process.env.P_KEY97 && !process.env.P_KEY97.startsWith("0x")) {
141
+ console.warn("P_KEY97 doesn't start with 0x. Appended 0x");
142
+ process.env.P_KEY97 = "0x" + process.env.P_KEY97;
143
+ }
144
+ if(!process.env.INFURA_KEY && !process.env.ALCHEMY_KEY) {
145
+ console.warn("neither INFURA_KEY nor ALCHEMY_KEY is not set. Deployments may not be available");
146
+ process.env.INFURA_KEY = "";
147
+ process.env.ALCHEMY_KEY = "";
148
+ }
149
+ if(!process.env.ETHERSCAN_KEY) {
150
+ console.warn("ETHERSCAN_KEY is not set. Deployed smart contract code verification won't be available");
151
+ process.env.ETHERSCAN_KEY = "";
152
+ }
153
+ if(!process.env.POLYSCAN_KEY) {
154
+ console.warn("POLYSCAN_KEY is not set. Deployed smart contract code verification won't be available on polyscan");
155
+ process.env.POLYSCAN_KEY = "";
156
+ }
157
+ if(!process.env.BSCSCAN_KEY) {
158
+ console.warn("BSCSCAN_KEY is not set. Deployed smart contract code verification won't be available on BscScan");
159
+ process.env.BSCSCAN_KEY = "";
160
+ }
161
+
162
+ /**
163
+ * @type import('hardhat/config').HardhatUserConfig
164
+ */
165
+ module.exports = {
166
+ defaultNetwork: "hardhat",
167
+ networks: {
168
+ // https://hardhat.org/hardhat-network/
169
+ hardhat: {
170
+ // set networkId to 0xeeeb04de as for all local networks
171
+ chainId: 0xeeeb04de,
172
+ // set the gas price to one for convenient tx costs calculations in tests
173
+ // gasPrice: 1,
174
+ // London hard fork fix: impossible to set gas price lower than baseFeePerGas (875,000,000)
175
+ initialBaseFeePerGas: 0,
176
+ accounts: {
177
+ count: 35,
178
+ },
179
+ /*
180
+ forking: {
181
+ url: "https://mainnet.infura.io/v3/" + process.env.INFURA_KEY, // create a key: https://infura.io/
182
+ enabled: !!(process.env.HARDHAT_FORK),
183
+ },
184
+ */
185
+ },
186
+ // https://etherscan.io/
187
+ mainnet: {
188
+ url: get_endpoint_url("mainnet"),
189
+ accounts: get_accounts(process.env.P_KEY1, process.env.MNEMONIC1),
190
+ },
191
+ // https://ropsten.etherscan.io/
192
+ ropsten: {
193
+ url: get_endpoint_url("ropsten"),
194
+ accounts: get_accounts(process.env.P_KEY3, process.env.MNEMONIC3),
195
+ },
196
+ // https://rinkeby.etherscan.io/
197
+ rinkeby: {
198
+ url: get_endpoint_url("rinkeby"),
199
+ accounts: get_accounts(process.env.P_KEY4, process.env.MNEMONIC4),
200
+ },
201
+ // https://kovan.etherscan.io/
202
+ kovan: {
203
+ url: get_endpoint_url("kovan"),
204
+ accounts: get_accounts(process.env.P_KEY42, process.env.MNEMONIC42),
205
+ },
206
+ // https://goerli.etherscan.io/
207
+ goerli: {
208
+ url: get_endpoint_url("goerli"),
209
+ accounts: get_accounts(process.env.P_KEY5, process.env.MNEMONIC5),
210
+ },
211
+ // matic/polygon L2 mainnet
212
+ // https://polygonscan.com/
213
+ polygon: {
214
+ url: "https://polygon-rpc.com/",
215
+ accounts: get_accounts(process.env.P_KEY137, process.env.MNEMONIC137),
216
+ },
217
+ // matic/polygon L1 testnet – Mumbai
218
+ // https://mumbai.polygonscan.com/
219
+ mumbai: {
220
+ url: "https://rpc-mumbai.maticvigil.com",
221
+ accounts: get_accounts(process.env.P_KEY80001, process.env.MNEMONIC80001),
222
+ },
223
+ // Binance Smart Chain (BSC) L2 mainnet
224
+ binance: {
225
+ url: "https://bsc-dataseed1.binance.org/",
226
+ accounts: get_accounts(process.env.P_KEY56, process.env.MNEMONIC56),
227
+ },
228
+ // Binance Smart Chain (BSC) L2 testnet
229
+ binance_testnet: {
230
+ url: "https://data-seed-prebsc-1-s3.binance.org:8545/",
231
+ accounts: get_accounts(process.env.P_KEY97, process.env.MNEMONIC97),
232
+ },
233
+ },
234
+
235
+ // Configure Solidity compiler
236
+ solidity: {
237
+ // https://hardhat.org/guides/compile-contracts.html
238
+ compilers: [
239
+ {
240
+ version: "0.8.21",
241
+ settings: {
242
+ optimizer: {
243
+ enabled: true,
244
+ runs: 200
245
+ }
246
+ }
247
+ },
248
+ {
249
+ version: "0.6.2",
250
+ settings: {
251
+ optimizer: {
252
+ enabled: true,
253
+ runs: 200
254
+ }
255
+ }
256
+ },
257
+ {
258
+ version: "0.4.22",
259
+ settings: {
260
+ optimizer: {
261
+ enabled: true,
262
+ runs: 200
263
+ }
264
+ }
265
+ },
266
+ {
267
+ version: "0.4.11",
268
+ settings: {
269
+ optimizer: {
270
+ enabled: true,
271
+ runs: 200
272
+ }
273
+ }
274
+ },
275
+ ]
276
+ },
277
+
278
+ // Set default mocha options here, use special reporters etc.
279
+ mocha: {
280
+ // timeout: 100000,
281
+
282
+ // disable mocha timeouts:
283
+ // https://mochajs.org/api/mocha#enableTimeouts
284
+ enableTimeouts: false,
285
+ // https://github.com/mochajs/mocha/issues/3813
286
+ timeout: false,
287
+ },
288
+
289
+ // hardhat-gas-reporter will be disabled by default, use REPORT_GAS environment variable to enable it
290
+ // https://hardhat.org/plugins/hardhat-gas-reporter.html
291
+ gasReporter: {
292
+ enabled: !!(process.env.REPORT_GAS)
293
+ },
294
+ }
295
+
296
+ /**
297
+ * Determines a JSON-RPC endpoint to use to connect to the node
298
+ * based on the requested network name and environment variables set
299
+ *
300
+ * Tries to use custom RPC URL first (MAINNET_RPC_URL/ROPSTEN_RPC_URL/RINKEBY_RPC_URL/KOVAN_RPC_URL)
301
+ * Tries to use alchemy RPC URL next (if ALCHEMY_KEY is set)
302
+ * Fallbacks to infura RPC URL
303
+ *
304
+ * @param network_name one of mainnet/ropsten/rinkeby/kovan
305
+ * @return JSON-RPC endpoint URL
306
+ */
307
+ function get_endpoint_url(network_name) {
308
+ // try custom RPC endpoint first (private node, quicknode, etc.)
309
+ // create a quicknode key: https://www.quicknode.com/
310
+ if(process.env.MAINNET_RPC_URL && network_name === "mainnet") {
311
+ return process.env.MAINNET_RPC_URL;
312
+ }
313
+ if(process.env.ROPSTEN_RPC_URL && network_name === "ropsten") {
314
+ return process.env.ROPSTEN_RPC_URL;
315
+ }
316
+ if(process.env.RINKEBY_RPC_URL && network_name === "rinkeby") {
317
+ return process.env.RINKEBY_RPC_URL;
318
+ }
319
+ if(process.env.KOVAN_RPC_URL && network_name === "kovan") {
320
+ return process.env.KOVAN_RPC_URL;
321
+ }
322
+ if(process.env.GOERLI_RPC_URL && network_name === "goerli") {
323
+ return process.env.GOERLI_RPC_URL;
324
+ }
325
+
326
+ // try the alchemy next
327
+ // create a key: https://www.alchemy.com/
328
+ if(process.env.ALCHEMY_KEY) {
329
+ switch(network_name) {
330
+ case "mainnet": return "https://eth-mainnet.alchemyapi.io/v2/" + process.env.ALCHEMY_KEY;
331
+ case "ropsten": return "https://eth-ropsten.alchemyapi.io/v2/" + process.env.ALCHEMY_KEY;
332
+ case "rinkeby": return "https://eth-rinkeby.alchemyapi.io/v2/" + process.env.ALCHEMY_KEY;
333
+ case "kovan": return "https://eth-kovan.alchemyapi.io/v2/" + process.env.ALCHEMY_KEY;
334
+ case "goerli": return "https://eth-goerli.alchemyapi.io/v2/" + process.env.ALCHEMY_KEY;
335
+ }
336
+ }
337
+
338
+ // fallback to infura
339
+ // create a key: https://infura.io/
340
+ switch(network_name) {
341
+ case "mainnet": return "https://mainnet.infura.io/v3/" + process.env.INFURA_KEY;
342
+ case "ropsten": return "https://ropsten.infura.io/v3/" + process.env.INFURA_KEY;
343
+ case "rinkeby": return "https://rinkeby.infura.io/v3/" + process.env.INFURA_KEY;
344
+ case "kovan": return "https://kovan.infura.io/v3/" + process.env.INFURA_KEY;
345
+ case "goerli": return "https://goerli.infura.io/v3/" + process.env.INFURA_KEY;
346
+ }
347
+ }
348
+
349
+ /**
350
+ * Depending on which of the inputs are available (private key or mnemonic),
351
+ * constructs an account object for use in the hardhat config
352
+ *
353
+ * @param p_key account private key, export private key from mnemonic: https://metamask.io/
354
+ * @param mnemonic 12 words mnemonic, create 12 words: https://metamask.io/
355
+ * @return either [p_key] if p_key is defined, or {mnemonic} if mnemonic is defined
356
+ */
357
+ function get_accounts(p_key, mnemonic) {
358
+ return p_key? [p_key]: mnemonic? {mnemonic, initialIndex: 0}: undefined;
359
+ }
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@lazy-sol/access-control",
3
+ "version": "1.0.3",
4
+ "description": "Enable the modular plug and play (PnP) architecture for your dapp by incorporating the role-based access control (RBAC) into the smart contracts",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "clean": "hardhat clean",
8
+ "compile": "hardhat compile",
9
+ "test": "hardhat test",
10
+ "coverage": "hardhat coverage",
11
+ "deploy": "hardhat deploy"
12
+ },
13
+ "engines": {
14
+ "node": ">=16.0.0"
15
+ },
16
+ "keywords": [
17
+ "RBAC",
18
+ "Solidity",
19
+ "access control",
20
+ "modular architecture"
21
+ ],
22
+ "author": "Basil Gorin",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "@lazy-sol/a-missing-gem": "^1.0.0",
26
+ "@nomiclabs/hardhat-truffle5": "^2.0.7",
27
+ "hardhat": "^2.16.0",
28
+ "hardhat-deploy": "^0.11.45"
29
+ },
30
+ "devDependencies": {
31
+ "@lazy-sol/zeppelin-test-helpers": "^1.0.0",
32
+ "hardhat-gas-reporter": "^1.0.10",
33
+ "solidity-coverage": "^0.8.10"
34
+ },
35
+ "overrides": {
36
+ "tough-cookie": "^4.1.3",
37
+ "yargs-parser": "^5.0.1"
38
+ }
39
+ }
@@ -0,0 +1,54 @@
1
+ // AdapterFactory tests
2
+
3
+ // Zeppelin test helpers
4
+ const {
5
+ BN,
6
+ constants,
7
+ expectEvent,
8
+ expectRevert,
9
+ } = require("@openzeppelin/test-helpers");
10
+ const {
11
+ assert,
12
+ expect,
13
+ } = require("chai");
14
+ const {
15
+ ZERO_ADDRESS,
16
+ ZERO_BYTES32,
17
+ MAX_UINT256,
18
+ } = constants;
19
+
20
+ // deployment routines in use
21
+ const {
22
+ deploy_usdt,
23
+ deploy_adapter_factory,
24
+ factory_deploy_ownable_to_ac_adapter,
25
+ } = require("./include/deployment_routines");
26
+
27
+ // run AdapterFactory tests
28
+ contract("AdapterFactory tests", function(accounts) {
29
+ // extract accounts to be used:
30
+ // A0 – special default zero account accounts[0] used by Truffle, reserved
31
+ // a0 – deployment account having all the permissions, reserved
32
+ // H0 – initial token holder account
33
+ // a1, a2,... – working accounts to perform tests on
34
+ const [A0, a0, H0, a1, a2, a3] = accounts;
35
+
36
+ let usdt, factory;
37
+ beforeEach(async function() {
38
+ usdt = await deploy_usdt(a1);
39
+ factory = await deploy_adapter_factory();
40
+ });
41
+
42
+ it("adapter deployment fails if executed not by the ownable owner", async function() {
43
+ await expectRevert(factory_deploy_ownable_to_ac_adapter(a2, factory, usdt), "not an owner");
44
+ });
45
+ describe("adapter deployment succeeds if executed by the ownable owner", async function() {
46
+ let adapter;
47
+ beforeEach(async function() {
48
+ ({adapter} = await factory_deploy_ownable_to_ac_adapter(a1, factory, usdt));
49
+ });
50
+ it("adapter's target is set correctly", async function() {
51
+ expect(await adapter.target()).to.be.equal(usdt.address);
52
+ });
53
+ });
54
+ });