@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 +21 -0
- package/.solcover.js +39 -0
- package/CONTRIBUTING.md +200 -0
- package/CRIBBED_CODE.txt +26 -0
- package/LICENSE.txt +22 -0
- package/README.md +162 -0
- package/artifacts/contracts/OwnableToAccessControlAdapter.sol/OwnableToAccessControlAdapter.json +342 -0
- package/contracts/AccessControl.sol +305 -0
- package/contracts/AdapterFactory.sol +56 -0
- package/contracts/OwnableToAccessControlAdapter.sol +231 -0
- package/contracts/mocks/AccessControlMock.sol +14 -0
- package/contracts/mocks/TetherToken.sol +443 -0
- package/deploy/deploy-AdapterFactory.js +59 -0
- package/deployments/goerli/.chainId +1 -0
- package/deployments/goerli/AdapterFactory.json +104 -0
- package/deployments/goerli/solcInputs/9f8f20c7b4fd0796d45c56d37e790191.json +42 -0
- package/docs/commit_policy.md +201 -0
- package/docs/pull_request_template.md +40 -0
- package/docs/style_guides.md +240 -0
- package/hardhat.config.js +359 -0
- package/package.json +39 -0
- package/test/adapter_factory.js +54 -0
- package/test/include/deployment_routines.js +150 -0
- package/test/include/features_roles.js +42 -0
- package/test/include/rbac.behaviour.js +315 -0
- package/test/ownable_to_rbac_adapter.js +100 -0
- package/test/ownable_to_rbac_adapter_rbac.js +57 -0
- package/test/rbac_core.js +24 -0
- package/test/rbac_modifier.js +53 -0
@@ -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
|
+
});
|