@lazy-sol/access-control 1.0.6 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +43 -0
- package/README.md +69 -48
- package/artifacts/contracts/OwnableToAccessControlAdapter.sol/OwnableToAccessControlAdapter.json +7 -64
- package/contracts/AccessControl.sol +15 -219
- package/contracts/AccessControlCore.sol +353 -0
- package/contracts/AdapterFactory.sol +1 -1
- package/contracts/OwnableToAccessControlAdapter.sol +7 -5
- package/contracts/mocks/AccessControlMock.sol +7 -1
- package/hardhat.config.js +6 -6
- package/index.js +4 -0
- package/package.json +12 -10
- package/test/include/deployment_routines.js +3 -12
- package/test/include/rbac.behaviour.js +22 -7
- package/test/ownable_to_rbac_adapter.js +1 -1
- package/test/ownable_to_rbac_adapter_rbac.js +3 -3
- package/test/rbac_modifier.js +1 -1
- package/ui.html +506 -0
package/CHANGELOG.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
v1.1.1: Role-based Access Control (RBAC) Inspector
|
2
|
+
- Introduced the Role-based Access Control (RBAC) Inspector UI capable of evaluating features and roles
|
3
|
+
for already deployed contracts; supports all EVM-based networks (mainnet, sepolia, etc.)
|
4
|
+
- Optimized npm imports moving all prod dependencies into dev dependencies
|
5
|
+
|
6
|
+
v1.1.0: Contact Size Optimizations
|
7
|
+
|
8
|
+
- __Breaking Change:__ Solidity 0.8.4 is now required to compile the contracts
|
9
|
+
(previously was 0.4.22 for the core contract and 0.6.2 for periphery contracts).
|
10
|
+
- Replaced "access denied" error with string literal (0.4.22) with the custom error AccessDenied() (0.8.4)
|
11
|
+
- Introduced lighter modification of the "AccessControl" RBAC contract – "AccessControlCore" (RBAC-C).
|
12
|
+
The 'core' version of the RBAC contract hides three rarely used external functions from the public ABI,
|
13
|
+
making them internal and thus reducing the overall compiled implementation size.
|
14
|
+
|
15
|
+
| old name | old modifier | new name | new modifier |
|
16
|
+
|----------------------|--------------|-----------------------|--------------|
|
17
|
+
| `isFeatureEnabled()` | `public` | `isFeatureEnabled()` | `internal` |
|
18
|
+
| `isSenderInRole()` | `public` | `_isSenderInRole()` | `internal` |
|
19
|
+
| `isOperatorInRole()` | `public` | `_isOperatorInRole()` | `internal` |
|
20
|
+
|
21
|
+
- Added `_requireSenderInRole()` and `_requireAccessCondition()` internal functions for a convenient and gas-efficient
|
22
|
+
way of checking the access permissions and throwing the AccessDenied() error.
|
23
|
+
- Added the CHANGELOG (this file)
|
24
|
+
|
25
|
+
v1.0.7:
|
26
|
+
- Exported the RBAC behavior
|
27
|
+
|
28
|
+
v1.0.6:
|
29
|
+
- Updated the documentation
|
30
|
+
|
31
|
+
v1.0.5:
|
32
|
+
- Exported RBAC JavaScript constants and functions
|
33
|
+
|
34
|
+
v1.0.4:
|
35
|
+
- Fixed broken dependencies
|
36
|
+
- Upgraded npm libraries
|
37
|
+
- Added Sepolia network support
|
38
|
+
|
39
|
+
v1.0.3:
|
40
|
+
- Allowed lower versions of Hardhat to be used
|
41
|
+
|
42
|
+
v1.0.2:
|
43
|
+
- Optimized npm dependencies
|
package/README.md
CHANGED
@@ -65,7 +65,7 @@ features and roles. Usually, smart contracts use different values for all the fe
|
|
65
65
|
next section).
|
66
66
|
|
67
67
|
Access manager may revoke its own permissions, including the bit 255. Eventually that allows an access manager to let
|
68
|
-
the smart contract “float freely” and be controlled only by the community (via DAO) or by no one at all.
|
68
|
+
the smart contract “float freely” and be controlled only by the community (via the DAO) or by no one at all.
|
69
69
|
|
70
70
|
## Comparing with OpenZeppelin
|
71
71
|
|
@@ -73,7 +73,7 @@ Both our and OpenZeppelin Access Control implementations feature a similar API t
|
|
73
73
|
thing".
|
74
74
|
|
75
75
|
Zeppelin implementation is more flexible:
|
76
|
-
* it allows setting unlimited number of roles, while current is limited to 256 different roles
|
76
|
+
* it allows setting an unlimited number of roles, while current is limited to 256 different roles
|
77
77
|
* it allows setting an admin for each role, while current allows having only one global admin
|
78
78
|
|
79
79
|
Our implementation is more lightweight:
|
@@ -81,21 +81,6 @@ Our implementation is more lightweight:
|
|
81
81
|
* it allows setting up to 256 roles at once, in a single transaction, while Zeppelin allows setting only one role in a
|
82
82
|
single transaction
|
83
83
|
|
84
|
-
## Upgradeability
|
85
|
-
|
86
|
-
[Upgradeable Access Control](https://github.com/lazy-sol/access-control-upgradeable) is a Role-based Access Control
|
87
|
-
extension supporting the OpenZeppelin UUPS Proxy upgrades. Smart contracts inheriting from the
|
88
|
-
`UpgradeableAccessControl` can be deployed behind the ERC1967 proxy and will get the upgradeability mechanism setup.
|
89
|
-
|
90
|
-
Upgradeable Access Control introduces another “special” permission bit 254 which is reserved for an upgrade manager role
|
91
|
-
`ROLE_UPGRADE_MANAGER` which is allowed to and is responsible for implementation upgrades of the ERC1967 Proxy.
|
92
|
-
|
93
|
-
Being controlled by the upgrade manager, the upgradeability is also a revocable feature of the smart contract: the
|
94
|
-
`upgradeTo` restricted function access can be revoked from all the admin accounts.
|
95
|
-
|
96
|
-
The best practice is to disable contract upgradeability when the protocol is mature enough and has already proven its
|
97
|
-
security and stability.
|
98
|
-
|
99
84
|
## Installation
|
100
85
|
```
|
101
86
|
npm i -D @lazy-sol/access-control
|
@@ -108,11 +93,11 @@ npm i -D @lazy-sol/access-control
|
|
108
93
|
Restricted function is a function with a `public` Solidity modifier access to which is restricted
|
109
94
|
so that only a pre-configured set of accounts can execute it.
|
110
95
|
|
111
|
-
1.
|
112
|
-
|
96
|
+
1. Enable role-based access control (RBAC) in a new smart contract
|
97
|
+
by inheriting the RBAC contract from the [AccessControlCore](./contracts/AccessControlCore.sol) contract:
|
113
98
|
```solidity
|
114
99
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
115
|
-
import "@lazy-sol/access-control/contracts/
|
100
|
+
import "@lazy-sol/access-control/contracts/AccessControlCore.sol";
|
116
101
|
|
117
102
|
/**
|
118
103
|
* @title Simple ERC20 Implementation
|
@@ -121,29 +106,29 @@ so that only a pre-configured set of accounts can execute it.
|
|
121
106
|
*
|
122
107
|
* @author Lazy So[u]l
|
123
108
|
*/
|
124
|
-
contract MyERC20Token is ERC20,
|
109
|
+
contract MyERC20Token is ERC20, AccessControlCore {
|
125
110
|
|
126
111
|
...
|
127
112
|
|
128
113
|
}
|
129
114
|
```
|
130
115
|
|
131
|
-
2.
|
116
|
+
2. Define an access control role with the unique integer value:
|
132
117
|
```solidity
|
133
118
|
...
|
134
119
|
|
135
120
|
/**
|
136
121
|
* @notice Token creator is responsible for creating (minting)
|
137
|
-
tokens to an arbitrary address
|
122
|
+
* tokens to an arbitrary address
|
138
123
|
* @dev Role ROLE_TOKEN_CREATOR allows minting tokens
|
139
|
-
(calling `mint` function)
|
124
|
+
* (calling `mint` function)
|
140
125
|
*/
|
141
126
|
uint32 public constant ROLE_TOKEN_CREATOR = 0x0001_0000;
|
142
127
|
|
143
128
|
...
|
144
129
|
```
|
145
130
|
|
146
|
-
3.
|
131
|
+
3. Add the `_requireSenderInRole(ROLE_TOKEN_CREATOR)` check into the function body:
|
147
132
|
```solidity
|
148
133
|
...
|
149
134
|
|
@@ -152,7 +137,7 @@ so that only a pre-configured set of accounts can execute it.
|
|
152
137
|
*/
|
153
138
|
function _mint(address _to, uint256 _value) internal virtual override {
|
154
139
|
// check if caller has sufficient permissions to mint tokens
|
155
|
-
|
140
|
+
_requireSenderInRole(ROLE_TOKEN_CREATOR);
|
156
141
|
|
157
142
|
// delegate to super implementation
|
158
143
|
super._mint(_to, _value);
|
@@ -161,8 +146,8 @@ so that only a pre-configured set of accounts can execute it.
|
|
161
146
|
...
|
162
147
|
```
|
163
148
|
|
164
|
-
|
165
|
-
|
149
|
+
Note: it is also possible to use the `restrictedTo` modifier in the function declaration instead of the `require`
|
150
|
+
in the function body if this better suits the coding style:
|
166
151
|
```solidity
|
167
152
|
...
|
168
153
|
|
@@ -177,6 +162,31 @@ so that only a pre-configured set of accounts can execute it.
|
|
177
162
|
...
|
178
163
|
```
|
179
164
|
|
165
|
+
### Customizing the Error Message
|
166
|
+
|
167
|
+
Modifier `restrictedTo()`, internal functions `_requireSenderInRole()` and `_requireAccessCondition()` throw the
|
168
|
+
`AccessDenied` denied error when access check fails.
|
169
|
+
|
170
|
+
It is also possible to use your own custom errors or string messages if needed by leveraging a lower level boolean
|
171
|
+
functions `_isSenderInRole()` and `_isOperatorInRole()`:
|
172
|
+
|
173
|
+
```solidity
|
174
|
+
...
|
175
|
+
|
176
|
+
/**
|
177
|
+
* @inheritdoc ERC20
|
178
|
+
*/
|
179
|
+
function _mint(address _to, uint256 _value) internal virtual override {
|
180
|
+
// check if caller has sufficient permissions to mint tokens
|
181
|
+
require(_isSenderInRole(ROLE_TOKEN_CREATOR), "access denied");
|
182
|
+
|
183
|
+
// delegate to super implementation
|
184
|
+
super._mint(_to, _value);
|
185
|
+
}
|
186
|
+
|
187
|
+
...
|
188
|
+
```
|
189
|
+
|
180
190
|
Examples:
|
181
191
|
[ERC20Impl](https://raw.githubusercontent.com/vgorin/solidity-template/master/contracts/token/ERC20Impl.sol),
|
182
192
|
[ERC721Impl](https://raw.githubusercontent.com/vgorin/solidity-template/master/contracts/token/ERC721Impl.sol).
|
@@ -192,32 +202,32 @@ Many deployed contracts are using this model, and when the time comes to switch
|
|
192
202
|
|
193
203
|
Prerequisite: deployed OZ Ownable contract (target contract) address (target_address)
|
194
204
|
|
195
|
-
1.
|
196
|
-
|
205
|
+
1. Deploy the AccessControl Adapter bound to the already deployed OZ Ownable contract
|
206
|
+
(specify the target OZ Ownable contract address in the constructor upon the deployment)
|
197
207
|
```javascript
|
198
208
|
const adapter = await (artifacts.require("OwnableToAccessControlAdapter")).new(target_address);
|
199
209
|
```
|
200
210
|
|
201
|
-
2.
|
202
|
-
|
211
|
+
2. Define what Ownable-restricted public functions on the target contract you'd like to be able
|
212
|
+
to provide access to through the adapter contract
|
203
213
|
|
204
|
-
3.
|
205
|
-
|
214
|
+
3. Map every such function with the role required to execute it using `updateAccessRole()` function
|
215
|
+
For example, to be able to provide an access to the transferOwnership(address) function, you could do
|
206
216
|
```javascript
|
207
217
|
const ROLE_TRANSFER_OWNERSHIP_MANAGER = 0x00010000;
|
208
218
|
await adapter.updateAccessRole("transferOwnership(address)", ROLE_TRANSFER_OWNERSHIP_MANAGER);
|
209
|
-
|
219
|
+
```
|
210
220
|
|
211
|
-
4.
|
212
|
-
|
213
|
-
|
221
|
+
4. Provide the roles to the corresponding operators as you would usually do with AccessControl
|
222
|
+
For example, if you wish an address 0x00000000000000000000000000000000000Ff1CE to grant an access to the
|
223
|
+
transferOwnership(address) function on the target, you could do
|
214
224
|
```javascript
|
215
225
|
const operator = "0x00000000000000000000000000000000000Ff1CE";
|
216
226
|
await adapter.updateRole(operator, ROLE_TRANSFER_OWNERSHIP_MANAGER);
|
217
227
|
```
|
218
228
|
|
219
|
-
5.
|
220
|
-
|
229
|
+
5. Transfer the ownership of the target contract to the deployed AccessControl Adapter contract
|
230
|
+
Note that you can also do steps 2-4 after the step 5
|
221
231
|
|
222
232
|
#### Usage Flow
|
223
233
|
|
@@ -225,16 +235,16 @@ Prerequisite: installed AccessControl Adapter with the access to at least one re
|
|
225
235
|
function configured
|
226
236
|
|
227
237
|
To execute the restricted access function on the target contract via the AccessControl Adapter
|
228
|
-
1.
|
229
|
-
|
230
|
-
|
238
|
+
1. Use target contract ABI to construct a low-level function call calldata
|
239
|
+
For example, to construct the transferOwnership() function calldata to transfer the ownership to the
|
240
|
+
0x00000000000000000000000000000000DEAdc0De address, you could do
|
231
241
|
```javascript
|
232
242
|
const to = "0x00000000000000000000000000000000DEAdc0De";
|
233
243
|
const calldata = target.contract.methods.transferOwnership(to).encodeABI();
|
234
244
|
```
|
235
245
|
|
236
|
-
2.
|
237
|
-
|
246
|
+
2. Execute a low-level function call on the AccessControl Adapter contract using the constructed calldata
|
247
|
+
For example, to execute the transferOwnership() function (prepared in step 1), you could do
|
238
248
|
```javascript
|
239
249
|
await web3.eth.sendTransaction({
|
240
250
|
from: operator,
|
@@ -243,9 +253,20 @@ To execute the restricted access function on the target contract via the AccessC
|
|
243
253
|
}
|
244
254
|
```
|
245
255
|
|
246
|
-
3.
|
247
|
-
|
248
|
-
|
256
|
+
3. It is also ok to add an ether to the transaction by adding a value field to the `sendTransaction` call,
|
257
|
+
as well as sending plain ether transfer transaction, as long as target contract has payable functions,
|
258
|
+
and/or has a default payable receiver
|
259
|
+
|
260
|
+
## Evaluating Currently Enabled Features and Roles on the Deployed Contract
|
261
|
+
|
262
|
+
1. To evaluate currently enabled features use
|
263
|
+
* `features()` function, or
|
264
|
+
* `getRole(this)` function, replacing `this` with the deployed contract address
|
265
|
+
2. To evaluate currently enabled permissions for a **particular** address use
|
266
|
+
* `getRole(address)` function
|
267
|
+
3. To find **all** the addresses having any permissions, track the `RoleUpdated()` event and evaluate the history
|
268
|
+
of `assiged` roles for every `operator` address
|
269
|
+
* Alternatively, use the [tool](ui.html) which automates the process
|
249
270
|
|
250
271
|
## Contributing
|
251
272
|
Please see the [Contribution Guide](./CONTRIBUTING.md) document to get understanding on how to report issues,
|
package/artifacts/contracts/OwnableToAccessControlAdapter.sol/OwnableToAccessControlAdapter.json
CHANGED
@@ -19,6 +19,11 @@
|
|
19
19
|
"stateMutability": "nonpayable",
|
20
20
|
"type": "constructor"
|
21
21
|
},
|
22
|
+
{
|
23
|
+
"inputs": [],
|
24
|
+
"name": "AccessDenied",
|
25
|
+
"type": "error"
|
26
|
+
},
|
22
27
|
{
|
23
28
|
"anonymous": false,
|
24
29
|
"inputs": [
|
@@ -188,68 +193,6 @@
|
|
188
193
|
"stateMutability": "view",
|
189
194
|
"type": "function"
|
190
195
|
},
|
191
|
-
{
|
192
|
-
"inputs": [
|
193
|
-
{
|
194
|
-
"internalType": "uint256",
|
195
|
-
"name": "required",
|
196
|
-
"type": "uint256"
|
197
|
-
}
|
198
|
-
],
|
199
|
-
"name": "isFeatureEnabled",
|
200
|
-
"outputs": [
|
201
|
-
{
|
202
|
-
"internalType": "bool",
|
203
|
-
"name": "",
|
204
|
-
"type": "bool"
|
205
|
-
}
|
206
|
-
],
|
207
|
-
"stateMutability": "view",
|
208
|
-
"type": "function"
|
209
|
-
},
|
210
|
-
{
|
211
|
-
"inputs": [
|
212
|
-
{
|
213
|
-
"internalType": "address",
|
214
|
-
"name": "operator",
|
215
|
-
"type": "address"
|
216
|
-
},
|
217
|
-
{
|
218
|
-
"internalType": "uint256",
|
219
|
-
"name": "required",
|
220
|
-
"type": "uint256"
|
221
|
-
}
|
222
|
-
],
|
223
|
-
"name": "isOperatorInRole",
|
224
|
-
"outputs": [
|
225
|
-
{
|
226
|
-
"internalType": "bool",
|
227
|
-
"name": "",
|
228
|
-
"type": "bool"
|
229
|
-
}
|
230
|
-
],
|
231
|
-
"stateMutability": "view",
|
232
|
-
"type": "function"
|
233
|
-
},
|
234
|
-
{
|
235
|
-
"inputs": [
|
236
|
-
{
|
237
|
-
"internalType": "uint256",
|
238
|
-
"name": "required",
|
239
|
-
"type": "uint256"
|
240
|
-
}
|
241
|
-
],
|
242
|
-
"name": "isSenderInRole",
|
243
|
-
"outputs": [
|
244
|
-
{
|
245
|
-
"internalType": "bool",
|
246
|
-
"name": "",
|
247
|
-
"type": "bool"
|
248
|
-
}
|
249
|
-
],
|
250
|
-
"stateMutability": "view",
|
251
|
-
"type": "function"
|
252
|
-
},
|
253
196
|
{
|
254
197
|
"inputs": [],
|
255
198
|
"name": "target",
|
@@ -335,8 +278,8 @@
|
|
335
278
|
"type": "receive"
|
336
279
|
}
|
337
280
|
],
|
338
|
-
"bytecode": "
|
339
|
-
"deployedBytecode": "
|
281
|
+
"bytecode": "0x608060405234801561001057600080fd5b50604051610a23380380610a2383398101604081905261002f9161012f565b80600061003f82600019806100bb565b61004a3082806100bb565b50506001600160a01b0382166100955760405162461bcd60e51b815260206004820152600c60248201526b7a65726f206164647265737360a01b604482015260640160405180910390fd5b50600180546001600160a01b0319166001600160a01b0392909216919091179055610162565b6001600160a01b0383166000818152602081815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b80516001600160a01b038116811461012a57600080fd5b919050565b6000806040838503121561014257600080fd5b61014b83610113565b915061015960208401610113565b90509250929050565b6108b2806101716000396000f3fe6080604052600436106100a05760003560e01c8063491d261111610064578063491d2611146101d35780635defb40d146101f3578063ae5b102e14610213578063ae682e2e14610233578063d4b839921461024b578063d5bb7f6714610283576100bf565b806309c5eabe146100ff5780630e82fe25146101285780632b5214161461016357806334e48c9e14610185578063442767331461019d576100bf565b366100bf576100bd604051806020016040528060008152506102a3565b005b6100bd6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506102a392505050565b61011261010d36600461064c565b6102a3565b60405161011f91906106ed565b60405180910390f35b34801561013457600080fd5b5061015561014336600461071d565b60026020526000908152604090205481565b60405190815260200161011f565b34801561016f57600080fd5b5030600090815260208190526040902054610155565b34801561019157600080fd5b50610155600160fd1b81565b3480156101a957600080fd5b506101556101b836600461074f565b6001600160a01b031660009081526020819052604090205490565b3480156101df57600080fd5b506100bd6101ee36600461076a565b610411565b3480156101ff57600080fd5b506100bd61020e366004610794565b610477565b34801561021f57600080fd5b506100bd61022e3660046107ed565b61048c565b34801561023f57600080fd5b50610155600160ff1b81565b34801561025757600080fd5b5060015461026b906001600160a01b031681565b6040516001600160a01b03909116815260200161011f565b34801561028f57600080fd5b506100bd61029e366004610809565b6104f5565b602081015181516060919015610323576001600160e01b03198116600090815260026020526040812054908190036103185760405162461bcd60e51b81526020600482015260136024820152721858d8d95cdcc81c9bdb19481b9bdd081cd95d606a1b60448201526064015b60405180910390fd5b61032181610502565b505b60015460405160009182916001600160a01b03909116903490610347908890610822565b60006040518083038185875af1925050503d8060008114610384576040519150601f19603f3d011682016040523d82523d6000602084013e610389565b606091505b5091509150816103ce5760405162461bcd60e51b815260206004820152601060248201526f195e1958dd5d1a5bdb8819985a5b195960821b604482015260640161030f565b7f57a62eca76fc623c92f161d2a4b851851ece707135ce2af1eec256d660571b6d8386836040516104019392919061083e565b60405180910390a1949350505050565b61041e600160fd1b610502565b6001600160e01b03198216600081815260026020908152604091829020849055815192835282018390527fdb8ed917742b49e83acd1322bcaa8f18b1e5f78a70784c43ea14db7ab50e628d910160405180910390a15050565b610488828051906020012082610411565b5050565b610499600160ff1b610502565b61048882826104f0336104c1876001600160a01b031660009081526020819052604090205490565b6001600160a01b0391909116600090815260208190526040902054600019808818821618908716919091171690565b610513565b6104ff308261048c565b50565b6104ff61050e8261056b565b61057d565b6001600160a01b0383166000818152602081815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b6000610577338361059b565b92915050565b806104ff57604051634ca8886760e01b815260040160405180910390fd5b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156105f1576105f16105c0565b604051601f8501601f19908116603f01168101908282118183101715610619576106196105c0565b8160405280935085815286868601111561063257600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561065e57600080fd5b813567ffffffffffffffff81111561067557600080fd5b8201601f8101841361068657600080fd5b610695848235602084016105d6565b949350505050565b60005b838110156106b85781810151838201526020016106a0565b50506000910152565b600081518084526106d981602086016020860161069d565b601f01601f19169290920160200192915050565b6020815260006105b960208301846106c1565b80356001600160e01b03198116811461071857600080fd5b919050565b60006020828403121561072f57600080fd5b6105b982610700565b80356001600160a01b038116811461071857600080fd5b60006020828403121561076157600080fd5b6105b982610738565b6000806040838503121561077d57600080fd5b61078683610700565b946020939093013593505050565b600080604083850312156107a757600080fd5b823567ffffffffffffffff8111156107be57600080fd5b8301601f810185136107cf57600080fd5b6107de858235602084016105d6565b95602094909401359450505050565b6000806040838503121561080057600080fd5b61078683610738565b60006020828403121561081b57600080fd5b5035919050565b6000825161083481846020870161069d565b9190910192915050565b63ffffffff60e01b8416815260606020820152600061086060608301856106c1565b828103604084015261087281856106c1565b969550505050505056fea26469706673582212201ba377eb6a91d1e61a05796e2c3f7b98c258168e3db52e709dd2c3a003d3eb7864736f6c63430008150033",
|
282
|
+
"deployedBytecode": "0x6080604052600436106100a05760003560e01c8063491d261111610064578063491d2611146101d35780635defb40d146101f3578063ae5b102e14610213578063ae682e2e14610233578063d4b839921461024b578063d5bb7f6714610283576100bf565b806309c5eabe146100ff5780630e82fe25146101285780632b5214161461016357806334e48c9e14610185578063442767331461019d576100bf565b366100bf576100bd604051806020016040528060008152506102a3565b005b6100bd6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506102a392505050565b61011261010d36600461064c565b6102a3565b60405161011f91906106ed565b60405180910390f35b34801561013457600080fd5b5061015561014336600461071d565b60026020526000908152604090205481565b60405190815260200161011f565b34801561016f57600080fd5b5030600090815260208190526040902054610155565b34801561019157600080fd5b50610155600160fd1b81565b3480156101a957600080fd5b506101556101b836600461074f565b6001600160a01b031660009081526020819052604090205490565b3480156101df57600080fd5b506100bd6101ee36600461076a565b610411565b3480156101ff57600080fd5b506100bd61020e366004610794565b610477565b34801561021f57600080fd5b506100bd61022e3660046107ed565b61048c565b34801561023f57600080fd5b50610155600160ff1b81565b34801561025757600080fd5b5060015461026b906001600160a01b031681565b6040516001600160a01b03909116815260200161011f565b34801561028f57600080fd5b506100bd61029e366004610809565b6104f5565b602081015181516060919015610323576001600160e01b03198116600090815260026020526040812054908190036103185760405162461bcd60e51b81526020600482015260136024820152721858d8d95cdcc81c9bdb19481b9bdd081cd95d606a1b60448201526064015b60405180910390fd5b61032181610502565b505b60015460405160009182916001600160a01b03909116903490610347908890610822565b60006040518083038185875af1925050503d8060008114610384576040519150601f19603f3d011682016040523d82523d6000602084013e610389565b606091505b5091509150816103ce5760405162461bcd60e51b815260206004820152601060248201526f195e1958dd5d1a5bdb8819985a5b195960821b604482015260640161030f565b7f57a62eca76fc623c92f161d2a4b851851ece707135ce2af1eec256d660571b6d8386836040516104019392919061083e565b60405180910390a1949350505050565b61041e600160fd1b610502565b6001600160e01b03198216600081815260026020908152604091829020849055815192835282018390527fdb8ed917742b49e83acd1322bcaa8f18b1e5f78a70784c43ea14db7ab50e628d910160405180910390a15050565b610488828051906020012082610411565b5050565b610499600160ff1b610502565b61048882826104f0336104c1876001600160a01b031660009081526020819052604090205490565b6001600160a01b0391909116600090815260208190526040902054600019808818821618908716919091171690565b610513565b6104ff308261048c565b50565b6104ff61050e8261056b565b61057d565b6001600160a01b0383166000818152602081815260409182902084905581518581529081018490527fe9be537308880e0f56b7d7cfd7abf85f14c4934486d138f848b92a0cbaf659b4910160405180910390a2505050565b6000610577338361059b565b92915050565b806104ff57604051634ca8886760e01b815260040160405180910390fd5b6001600160a01b038216600090815260208190526040812054821682145b9392505050565b634e487b7160e01b600052604160045260246000fd5b600067ffffffffffffffff808411156105f1576105f16105c0565b604051601f8501601f19908116603f01168101908282118183101715610619576106196105c0565b8160405280935085815286868601111561063257600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121561065e57600080fd5b813567ffffffffffffffff81111561067557600080fd5b8201601f8101841361068657600080fd5b610695848235602084016105d6565b949350505050565b60005b838110156106b85781810151838201526020016106a0565b50506000910152565b600081518084526106d981602086016020860161069d565b601f01601f19169290920160200192915050565b6020815260006105b960208301846106c1565b80356001600160e01b03198116811461071857600080fd5b919050565b60006020828403121561072f57600080fd5b6105b982610700565b80356001600160a01b038116811461071857600080fd5b60006020828403121561076157600080fd5b6105b982610738565b6000806040838503121561077d57600080fd5b61078683610700565b946020939093013593505050565b600080604083850312156107a757600080fd5b823567ffffffffffffffff8111156107be57600080fd5b8301601f810185136107cf57600080fd5b6107de858235602084016105d6565b95602094909401359450505050565b6000806040838503121561080057600080fd5b61078683610738565b60006020828403121561081b57600080fd5b5035919050565b6000825161083481846020870161069d565b9190910192915050565b63ffffffff60e01b8416815260606020820152600061086060608301856106c1565b828103604084015261087281856106c1565b969550505050505056fea26469706673582212201ba377eb6a91d1e61a05796e2c3f7b98c258168e3db52e709dd2c3a003d3eb7864736f6c63430008150033",
|
340
283
|
"linkReferences": {},
|
341
284
|
"deployedLinkReferences": {}
|
342
285
|
}
|