Skip to content

Commit 58fc3d3

Browse files
committed
improve readme
1 parent 7f4650a commit 58fc3d3

File tree

5 files changed

+56
-22
lines changed

5 files changed

+56
-22
lines changed

README.md

+13-22
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,32 @@
11
# Smart contract layers
22

3-
This is proof of concept repository intented to demonstrate the ability of layered approach in smart contract development to encapsulate security tasks to the layers that act as middleware.
3+
This is proof of concept repository intended to demonstrate the ability of layered approach in smart contract development to encapsulate security tasks to the layers that act as middleware.
44

55
## Concept
66

77
Provide a wrapper(s) to the contract only entry point (i.e. `fallback()`) access management.
88

9-
Make each wrapper eligible to receive complete information data (`msg.*` fields) via standartized API. Rely on wrappers to revert transactions per their internal logic conditions.
9+
Make each wrapper eligible to receive complete information data (`msg.*` fields) via standardized API. Rely on wrappers to revert transactions per their internal logic conditions.
1010

1111
<img width="633" alt="image" src="https://github.com/peersky/smart-contract-layers/assets/61459744/b87bf5ef-3b65-4a4a-9ae1-3be2df7f60a8">
1212

1313
### Layer contracts
1414

15-
Layer contracts are separate middlewares that are agnostic from a particular protected contract and can accept a configuration from the caller as well as message fields and analyze them. If layer is failing to validate inputs it must revert.
15+
Layer contracts are separate middlewares that are agnostic from a particular protected contract and can accept a configuration from the caller as well as message fields and analyze them. If layer is failing to validate inputs it must revert.
1616

17-
Such architectural decision allows for each layer to be managed by independedent security provider. Such can be upgraded and managed orthogonally and accomodate large amount of secured contracts.
17+
Such architectural decision allows for each layer to be managed by independent security provider. Such can be upgraded and managed orthogonally and accommodate large amount of secured contracts.
18+
19+
#### Initialization
20+
21+
![init](./docs/initialize.png)
22+
23+
#### Operation
24+
25+
![init](./docs/operate.png)
1826

1927
## Implementation
2028

21-
In this proof of concept a simple rate limiter is implemented which limits number of transactions a method can be called during one block, reducing ability to drain contract funds.
29+
In this proof of concept a simple rate limiter is implemented which limits number of transactions a method can be called during one block, reducing ability to drain contract funds.
2230

2331
[LayeredProxy](https://github.com/peersky/smart-contract-layers/blob/main/src/LayeredProxy.sol) contract is modified version of TransparentUpgradeableProxy which adds a layered pattern that is defined by [LibAccessLayer](https://github.com/peersky/smart-contract-layers/blob/main/src/LibAccessLayers.sol) in form of a [modifier](https://github.com/peersky/smart-contract-layers/blob/main/src/AccessLayers.sol)
2432

@@ -27,20 +35,3 @@ Contract protecting the implementation only needs to implement a [ILayer](https:
2735
Drainer contract calls victim number of times defined by Drainer function input.
2836

2937
In the particular implementation rate is limited to 10 transactions per block and can be tested by `pnpm test`
30-
31-
### Benchmarking
32-
33-
Given by hardhat compiler with settings as per hardhat.config.ts. Rate limits adjusted for each column (not testing reverted gas consumption).
34-
Tested consumption of Drainer `drain(address payable victim, uint256 cycles)` function.
35-
36-
Benchmark is given for RateLimiting functionality assuming that drain function can have different `cycles` argument
37-
38-
| First Header | gas used (cycles=1) | delta from fixture |
39-
| --------------------------------------- | ------------------- | ------------------ |
40-
| No Layer modifier (fixture consumption) | 31,231 | 0 |
41-
| Layer modifier installed (no layers) | 33,869 | + 2 638 |
42-
| 1 Layer call added (Interface only) | **50,310** | **+ 19 079** |
43-
| 1 Layer call added (Rate limiter x1) | 75,476 | + 44 244 |
44-
| 2 Layer call added (Rate limiter x2) | 117,024 | + 85 793 |
45-
46-
_\*Bold numbers show cost to call layer contract protection wrapper that has no internal processing overhead._

docs/initialize.png

81.7 KB
Loading

docs/initialize.zenuml

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
2+
TargetContract.initialize(layers){
3+
LibAccessLayers.setLayers(layers)
4+
{
5+
for ("all layers") {
6+
addLayer(address,layerConfigData)
7+
}
8+
return
9+
}
10+
return success
11+
12+
}
13+
14+

docs/operate.png

268 KB
Loading

docs/operate.zenuml

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
2+
TargetContract.fallback(msg) {
3+
LibAccessLayers.beforeCall(selector, sender, data, value) {
4+
for ("all layers") {
5+
new ILayer(layerAddress)
6+
// Layer can Revert if validation fails
7+
ILayer.beforeCallValidation(layerConfig, msg)
8+
{
9+
return beforeCallReturnValue
10+
}
11+
12+
}
13+
return beforeCallReturnValues
14+
}
15+
// [font-bold]
16+
Implementation.delegateCall(msg.data)
17+
LibAccessLayers.afterCall(selector, sender, data, value,beforeCallReturnValues) {
18+
for ("all layers reverse") {
19+
new ILayer(layerAddress)
20+
// Layer can revert if validation fails after transaction
21+
ILayer.afterCallValidation(layerConfig, msg,beforeCallResult)
22+
23+
24+
}
25+
return
26+
}
27+
return success
28+
29+
}

0 commit comments

Comments
 (0)