-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCEINamespacedLib.sol
65 lines (53 loc) · 1.89 KB
/
CEINamespacedLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IChecksEffectsInteractions} from "./ICEI.sol";
/**
* Re-entrancy example using a library to implement logic and
* [EIP7201](https://eips.ethereum.org/EIPS/eip-7201) namespaced storage.
*
* Libaries enable better code modularity by decoupling state & logic
* and avoiding the complexity of inheritance.
* Namespaced storage pattern is commonly used by proxies & diamond pattern contracts to
* avoid storage collisions.
*
* Same as basic re-entrancy example [CEI.sol](./CEI.sol) with the following changes:
* 1. Convert logic to library
* 2. Convert storage to be namespaced
*
*/
library ChecksEffectsInteractionsNamespacedLib {
bytes32 constant CEI_STORAGE =
keccak256(abi.encode(uint256(keccak256("cei.storage")) - 1)) &
~bytes32(uint256(0xff));
/// @custom:storage-location erc7201:cei.storage
struct CEIStorage {
mapping(address => uint) balances;
}
function getData() internal pure returns (CEIStorage storage ds) {
bytes32 position = CEI_STORAGE;
assembly {
ds.slot := position
}
}
function _deposit() internal {
mapping(address => uint) storage balances = getData().balances;
balances[msg.sender] = msg.value;
}
function _withdraw(uint amount) internal {
mapping(address => uint) storage balances = getData().balances;
// WARNING: Re-entrancy here
payable(msg.sender).call{value: amount}("");
require(balances[msg.sender] >= amount);
balances[msg.sender] -= amount;
}
}
contract ChecksEffectsInteractionsNamespacedLibContract is
IChecksEffectsInteractions
{
function deposit() public payable {
ChecksEffectsInteractionsNamespacedLib._deposit();
}
function withdraw(uint amount) public {
ChecksEffectsInteractionsNamespacedLib._withdraw(amount);
}
}