Skip to content

Commit 6b614ea

Browse files
KyrylRaritkulovaArvolear
authored
Maintenance (#138)
* Moved APoolFactory from pool-factory directory * Deleted OwnableCompoundRateKeeper preset * Deleted redundant presets and modules * moved presets to one folder * added storage backet for APoolContractsRegistry * Updated naming * added storage backets for contracts * fixed typo * added getter for a storage variable * Linting * update readme * update readme * pretty * pretty 2.0 * moved DiamondERC165 to utils * returned AInitializableStorage * changed version to 3.0.0 * Marked more function as virtual * revert: Marked more function as virtual * fix --------- Co-authored-by: aritkulova <[email protected]> Co-authored-by: Artem Chystiakov <[email protected]>
1 parent 9da2d48 commit 6b614ea

File tree

50 files changed

+2016
-3038
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2016
-3038
lines changed

README.md

+84-67
Original file line numberDiff line numberDiff line change
@@ -7,83 +7,100 @@
77

88
# Solarity Solidity Library
99

10-
Solidity modules and utilities that **go far beyond mediocre solidity**.
11-
12-
- Implementation of the [**Contracts Registry**](https://eips.ethereum.org/EIPS/eip-6224) pattern
13-
- State-of-the-art cryptography primitives (**ECDSA over 256-bit, 384-bit, and 512-bit curves**, **RSASSA-PSS**)
14-
- Advanced data structures (**Vector**, **DynamicSet**, **PriorityQueue**, **AVLTree**)
15-
- ZK-friendly [**Cartesian Merkle Tree**](https://medium.com/@Arvolear/cartesian-merkle-tree-the-new-breed-a30b005ecf27), [**Sparse Merkle Tree**](https://docs.iden3.io/publications/pdfs/Merkle-Tree.pdf), and [**Incremental Merkle Tree**](https://github.com/runtimeverification/deposit-contract-verification/blob/master/deposit-contract-verification.pdf) implementations
16-
- Versatile access control smart contracts (**Merkle whitelists**, **RBAC**)
17-
- Enhanced and simplified [**Diamond**](https://eips.ethereum.org/EIPS/eip-2535) pattern
18-
- Flexible finance instruments (**Staking**, **Vesting**)
19-
- Robust UniswapV2 and UniswapV3 oracles
20-
- Lightweight SBT implementation
21-
- Hyperoptimized **uint512** BigInt library
22-
- Utilities to ease work with memory, types, ERC20 decimals, arrays, sets, and ZK proofs
10+
Solidity contracts and utilities that **go far beyond mediocre solidity**.
11+
12+
## Contracts
13+
14+
```ml
15+
contracts
16+
├── access
17+
│ ├── AMerkleWhitelisted — "Whitelists via Merkle proofs"
18+
│ ├── AMultiOwnable — "Multiple owners with the equal access level"
19+
│ ├── ARBAC — "A powerful implementation of a true RBAC"
20+
│ └── extensions
21+
│ └── ARBACGroupable — "Groupable extension of ARBAC"
22+
├── contracts—registry
23+
│ ├── AContractsRegistry — "Reference registry implementation of ERC-6224 pattern"
24+
│ ├── ADependant — "Reference dependant implementation of ERC-6224 pattern"
25+
│ └── pools
26+
│ ├── APoolContractsRegistry — "Adaptation of ERC-6224 for factory-like contracts"
27+
│ └── APoolFactory — "Factory implementation for a pooled registry"
28+
├── diamond
29+
│ ├── ADiamondStorage — "The storage part of ERC-2535 diamond"
30+
│ ├── Diamond — "Revised ERC-2535 diamond implementation"
31+
│ └── utils
32+
│ ├── AInitializableStorage — "Initializable logic for diamond facets"
33+
│ └── DiamondERC165 — "ERC-165 introspection for diamond facets"
34+
├── finance
35+
│ ├── compound—rate—keeper
36+
│ │ └── ACompoundRateKeeper — "Complex percentage calculator used in lending protocols"
37+
│ ├── staking
38+
│ │ ├── AStaking — "Flexible rewards staking implementation"
39+
│ │ └── AValueDistributor — "Efficient distribution algorithm implementation"
40+
│ └── vesting
41+
│ └── AVesting — "Linear and exponential vesting implementation"
42+
├── libs
43+
│ ├── arrays
44+
│ │ ├── ArrayHelper — "Common functions to work with arrays"
45+
│ │ ├── Paginator — "Return array slices from view function"
46+
│ │ └── SetHelper — "Array abstraction over sets"
47+
│ ├── bn
48+
│ │ └── U512 — "A hyperoptimized uint512 implementation"
49+
│ ├── crypto
50+
│ │ ├── ECDSA256 — "ECDSA verification over any 256-bit curves"
51+
│ │ ├── ECDSA384 — "ECDSA verification over any 384-bit curves"
52+
│ │ ├── ECDSA512 — "ECDSA verification over any 512-bit curves"
53+
│ │ └── RSASSAPSS — "RSASSA-PSS verification with MGF1"
54+
│ ├── data—structures
55+
│ │ ├── AvlTree — "AVL tree implementation with an iterator traversal"
56+
│ │ ├── CartesianMerkleTree — "CMT reference implementation"
57+
│ │ ├── DynamicSet — "Set for strings and bytes"
58+
│ │ ├── IncrementalMerkleTree — "IMT implementation with flexible tree height"
59+
│ │ ├── PriorityQueue — "Max queue heap implementation"
60+
│ │ ├── SparseMerkleTree — "SMT optimized implementation"
61+
│ │ └── memory
62+
│ │ └── Vector — "A pushable memory array"
63+
│ ├── utils
64+
│ │ ├── DecimalsConverter — "Simplify interaction with ERC-20 decimals"
65+
│ │ ├── MemoryUtils — "Functions for memory manipulation"
66+
│ │ ├── ReturnDataProxy — "Bypass extra returndata copy when returning data"
67+
│ │ └── Typecaster — "Cast between various Solidity types"
68+
│ └── zkp
69+
│ ├── Groth16VerifierHelper — "Simplify integration with Groth16 proofs"
70+
│ └── PlonkVerifierHelper — "Simplify integration with Plonk proofs"
71+
├── oracles
72+
│ ├── AUniswapV2Oracle — "Uniswap V2 oracle with custom TWAP"
73+
│ └── UniswapV3Oracle — "Uniswap V3 oracle with a clean interface"
74+
├── proxy
75+
│ └── adminable
76+
│ ├── AdminableProxy — "A slight modification of a transparent proxy"
77+
│ └── AdminableProxyUpgrader — "A slight modification of a proxy admin"
78+
├── tokens
79+
│ └── ASBT — "A minimal implementation of an SBT"
80+
├── utils
81+
│ ├── ABlockGuard — "Protect against flashloans"
82+
│ └── Globals — "Some commonly used constants"
83+
├── presets — "Presets for the library contracts"
84+
├── interfaces — "Interfaces for the library contracts"
85+
└── mock — "Mocks for testing purposes"
86+
```
2387

2488
Built with courage and aspiration to perfection.
2589

26-
## Overview
90+
> [!TIP]
91+
> The library is designed to work cohesively with [hardhat-zkit](https://github.com/dl-solarity/hardhat-zkit) and [circom-lib](https://github.com/dl-solarity/circom-lib) packages.
2792
28-
### Installation
93+
## Installation
2994

30-
```console
31-
$ npm install @solarity/solidity-lib
95+
```bash
96+
npm install @solarity/solidity-lib
3297
```
3398

3499
The latest stable version is always in the `master` branch.
35100

36-
### Documentation
37-
38-
Check out the project's [documentation](https://docs.solarity.dev) with broad explanations and usage examples of every module. Full `natspec` guides are also available in the source code.
39-
40-
## Usage
41-
42-
You will find the smart contracts in the `/contracts` directory. Feel free to play around and check the project's structure.
43-
44-
Once the [npm package](https://www.npmjs.com/package/@solarity/solidity-lib) is installed, one can use the library just like that:
45-
46-
```solidity
47-
pragma solidity ^0.8.21;
48-
49-
import {AMultiOwnable} from "@solarity/solidity-lib/access/AMultiOwnable.sol";
50-
import {TypeCaster} from "@solarity/solidity-lib/libs/utils/TypeCaster.sol";
51-
import {CartesianMerkleTree} from "@solarity/solidity-lib/libs/data-structures/CartesianMerkleTree.sol";
52-
import {Groth16VerifierHelper} from "@solarity/solidity-lib/libs/zkp/Groth16VerifierHelper.sol";
53-
54-
contract Example is AMultiOwnable {
55-
using CartesianMerkleTree for CartesianMerkleTree.UintCMT;
56-
using Groth16VerifierHelper for address;
57-
58-
CartesianMerkleTree.UintCMT internal _uintTreaple;
59-
address internal _treapleVerifier;
101+
## Documentation
60102

61-
function __Example_init(address treapleVerifier_) initializer {
62-
__AMultiOwnable_init();
63-
_uintTreaple.initialize(40);
64-
_treapleVerifier = treapleVerifier_;
65-
}
66-
67-
function addToTree(uint256 key_) external onlyOwner {
68-
_uintTreaple.add(key_);
69-
}
70-
71-
function getMerkleProof(uint256 key_) external view returns (CartesianMerkleTree.Proof memory) {
72-
return _uintTreaple.getProof(key_, 0);
73-
}
74-
75-
function verifyZKProof(Groth16VerifierHelper.ProofPoints memory proof_) external view {
76-
uint256[] memory pubSignals_ = TypeCaster.asSingletonArray(_uintTreaple.getRoot());
77-
78-
require(_treapleVerifier.verifyProof(proof_, pubSignals_), "ZKP verification failed");
79-
}
80-
}
81-
```
82-
83-
This example showcases the basic usage of a `CartesianMerkleTree` with ZK proofs. The contract's `MultiOwner` may add elements to the tree to then privately prove their existence. Also, the `Groth16VerifierHelper` library is used to simplify the interaction with the ZK verifier.
84-
85-
> [!TIP]
86-
> The library is designed to work cohesively with [hardhat-zkit](https://github.com/dl-solarity/hardhat-zkit) and [circom-lib](https://github.com/dl-solarity/circom-lib) packages.
103+
Check out the project's [documentation](https://docs.solarity.dev) with broad explanations and usage examples of every contract. Full `natspec` guides are also available in the source code.
87104

88105
## Contribution
89106

contracts/contracts-registry/AContractsRegistry.sol

+64-24
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,15 @@ import {ADependant} from "./ADependant.sol";
3838
* Users may also fetch all the contracts present in the system as they are now located in a single place.
3939
*/
4040
abstract contract AContractsRegistry is Initializable {
41-
AdminableProxyUpgrader private _proxyUpgrader;
41+
struct AContractsRegistryStorage {
42+
AdminableProxyUpgrader proxyUpgrader;
43+
mapping(string name => address contractAddress) contracts;
44+
mapping(address contractAddress => bool isProxy) isProxy;
45+
}
4246

43-
mapping(string => address) private _contracts;
44-
mapping(address => bool) private _isProxy;
47+
// bytes32(uint256(keccak256("solarity.contract.AContractsRegistry")) - 1)
48+
bytes32 private constant A_CONTRACTS_REGISTRY_STORAGE =
49+
0x769f3b456cd81d706504548e533f55ce8f4cb7a5f9b80697cfd5d8146de0ca61;
4550

4651
event ContractAdded(string name, address contractAddress);
4752
event ProxyContractAdded(string name, address contractAddress, address implementation);
@@ -56,7 +61,9 @@ abstract contract AContractsRegistry is Initializable {
5661
* @notice The initialization function
5762
*/
5863
function __AContractsRegistry_init() internal onlyInitializing {
59-
_proxyUpgrader = new AdminableProxyUpgrader(address(this));
64+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
65+
66+
$.proxyUpgrader = new AdminableProxyUpgrader(address(this));
6067
}
6168

6269
/**
@@ -65,7 +72,9 @@ abstract contract AContractsRegistry is Initializable {
6572
* @return the address of the contract
6673
*/
6774
function getContract(string memory name_) public view returns (address) {
68-
address contractAddress_ = _contracts[name_];
75+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
76+
77+
address contractAddress_ = $.contracts[name_];
6978

7079
_checkIfMappingExist(contractAddress_, name_);
7180

@@ -78,15 +87,19 @@ abstract contract AContractsRegistry is Initializable {
7887
* @return true if the contract is present in the registry
7988
*/
8089
function hasContract(string memory name_) public view returns (bool) {
81-
return _contracts[name_] != address(0);
90+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
91+
92+
return $.contracts[name_] != address(0);
8293
}
8394

8495
/**
8596
* @notice The function that returns the admin of the added proxy contracts
8697
* @return the proxy admin address
8798
*/
8899
function getProxyUpgrader() public view returns (address) {
89-
return address(_proxyUpgrader);
100+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
101+
102+
return address($.proxyUpgrader);
90103
}
91104

92105
/**
@@ -95,12 +108,14 @@ abstract contract AContractsRegistry is Initializable {
95108
* @return the implementation address
96109
*/
97110
function getImplementation(string memory name_) public view returns (address) {
98-
address contractProxy_ = _contracts[name_];
111+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
112+
113+
address contractProxy_ = $.contracts[name_];
99114

100115
if (contractProxy_ == address(0)) revert NoMappingExists(name_);
101-
if (!_isProxy[contractProxy_]) revert NotAProxy(name_, contractProxy_);
116+
if (!$.isProxy[contractProxy_]) revert NotAProxy(name_, contractProxy_);
102117

103-
return _proxyUpgrader.getImplementation(contractProxy_);
118+
return $.proxyUpgrader.getImplementation(contractProxy_);
104119
}
105120

106121
/**
@@ -120,7 +135,9 @@ abstract contract AContractsRegistry is Initializable {
120135
string memory name_,
121136
bytes memory data_
122137
) internal virtual {
123-
address contractAddress_ = _contracts[name_];
138+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
139+
140+
address contractAddress_ = $.contracts[name_];
124141

125142
_checkIfMappingExist(contractAddress_, name_);
126143

@@ -152,12 +169,14 @@ abstract contract AContractsRegistry is Initializable {
152169
address newImplementation_,
153170
bytes memory data_
154171
) internal virtual {
155-
address contractToUpgrade_ = _contracts[name_];
172+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
173+
174+
address contractToUpgrade_ = $.contracts[name_];
156175

157176
if (contractToUpgrade_ == address(0)) revert NoMappingExists(name_);
158-
if (!_isProxy[contractToUpgrade_]) revert NotAProxy(name_, contractToUpgrade_);
177+
if (!$.isProxy[contractToUpgrade_]) revert NotAProxy(name_, contractToUpgrade_);
159178

160-
_proxyUpgrader.upgrade(contractToUpgrade_, newImplementation_, data_);
179+
$.proxyUpgrader.upgrade(contractToUpgrade_, newImplementation_, data_);
161180

162181
emit ProxyContractUpgraded(name_, newImplementation_);
163182
}
@@ -171,7 +190,9 @@ abstract contract AContractsRegistry is Initializable {
171190
function _addContract(string memory name_, address contractAddress_) internal virtual {
172191
if (contractAddress_ == address(0)) revert ZeroAddressProvided(name_);
173192

174-
_contracts[name_] = contractAddress_;
193+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
194+
195+
$.contracts[name_] = contractAddress_;
175196

176197
emit ContractAdded(name_, contractAddress_);
177198
}
@@ -200,10 +221,12 @@ abstract contract AContractsRegistry is Initializable {
200221
) internal virtual {
201222
if (contractAddress_ == address(0)) revert ZeroAddressProvided(name_);
202223

203-
address proxyAddr_ = _deployProxy(contractAddress_, address(_proxyUpgrader), data_);
224+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
225+
226+
address proxyAddr_ = _deployProxy(contractAddress_, address($.proxyUpgrader), data_);
204227

205-
_contracts[name_] = proxyAddr_;
206-
_isProxy[proxyAddr_] = true;
228+
$.contracts[name_] = proxyAddr_;
229+
$.isProxy[proxyAddr_] = true;
207230

208231
emit ProxyContractAdded(name_, proxyAddr_, contractAddress_);
209232
}
@@ -221,13 +244,15 @@ abstract contract AContractsRegistry is Initializable {
221244
) internal virtual {
222245
if (contractAddress_ == address(0)) revert ZeroAddressProvided(name_);
223246

224-
_contracts[name_] = contractAddress_;
225-
_isProxy[contractAddress_] = true;
247+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
248+
249+
$.contracts[name_] = contractAddress_;
250+
$.isProxy[contractAddress_] = true;
226251

227252
emit ProxyContractAdded(
228253
name_,
229254
contractAddress_,
230-
_proxyUpgrader.getImplementation(contractAddress_)
255+
$.proxyUpgrader.getImplementation(contractAddress_)
231256
);
232257
}
233258

@@ -236,12 +261,14 @@ abstract contract AContractsRegistry is Initializable {
236261
* @param name_ the associated name with the contract
237262
*/
238263
function _removeContract(string memory name_) internal virtual {
239-
address contractAddress_ = _contracts[name_];
264+
AContractsRegistryStorage storage $ = _getAContractsRegistryStorage();
265+
266+
address contractAddress_ = $.contracts[name_];
240267

241268
_checkIfMappingExist(contractAddress_, name_);
242269

243-
delete _isProxy[contractAddress_];
244-
delete _contracts[name_];
270+
delete $.isProxy[contractAddress_];
271+
delete $.contracts[name_];
245272

246273
emit ContractRemoved(name_);
247274
}
@@ -264,4 +291,17 @@ abstract contract AContractsRegistry is Initializable {
264291
function _checkIfMappingExist(address contractAddress_, string memory name_) internal pure {
265292
if (contractAddress_ == address(0)) revert NoMappingExists(name_);
266293
}
294+
295+
/**
296+
* @dev Returns a pointer to the storage namespace
297+
*/
298+
function _getAContractsRegistryStorage()
299+
private
300+
pure
301+
returns (AContractsRegistryStorage storage $)
302+
{
303+
assembly {
304+
$.slot := A_CONTRACTS_REGISTRY_STORAGE
305+
}
306+
}
267307
}

0 commit comments

Comments
 (0)