-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathBaseFeeDistributor.sol
202 lines (169 loc) · 7.37 KB
/
BaseFeeDistributor.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
// SPDX-FileCopyrightText: 2023 P2P Validator <[email protected]>
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "../@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "../@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";
import "../feeDistributorFactory/IFeeDistributorFactory.sol";
import "../assetRecovering/OwnableTokenRecoverer.sol";
import "../access/OwnableWithOperator.sol";
import "./IFeeDistributor.sol";
import "./FeeDistributorErrors.sol";
import "../structs/P2pStructs.sol";
import "../lib/P2pAddressLib.sol";
import "./Erc4337Account.sol";
/// @title Common logic for all FeeDistributor types
abstract contract BaseFeeDistributor is Erc4337Account, OwnableTokenRecoverer, OwnableWithOperator, ReentrancyGuard, ERC165, IFeeDistributor {
/// @notice FeeDistributorFactory address
IFeeDistributorFactory internal immutable i_factory;
/// @notice P2P fee recipient address
address payable internal immutable i_service;
/// @notice Client rewards recipient address and basis points
FeeRecipient internal s_clientConfig;
/// @notice Referrer rewards recipient address and basis points
FeeRecipient internal s_referrerConfig;
/// @notice If caller not client, revert
modifier onlyClient() {
address clientAddress = s_clientConfig.recipient;
if (clientAddress != msg.sender) {
revert FeeDistributor__CallerNotClient(msg.sender, clientAddress);
}
_;
}
/// @notice If caller not factory, revert
modifier onlyFactory() {
if (msg.sender != address(i_factory)) {
revert FeeDistributor__NotFactoryCalled(msg.sender, i_factory);
}
_;
}
/// @dev Set values that are constant, common for all the clients, known at the initial deploy time.
/// @param _factory address of FeeDistributorFactory
/// @param _service address of the service (P2P) fee recipient
constructor(
address _factory,
address payable _service
) {
if (!ERC165Checker.supportsInterface(_factory, type(IFeeDistributorFactory).interfaceId)) {
revert FeeDistributor__NotFactory(_factory);
}
if (_service == address(0)) {
revert FeeDistributor__ZeroAddressService();
}
i_factory = IFeeDistributorFactory(_factory);
i_service = _service;
bool serviceCanReceiveEther = P2pAddressLib._sendValue(_service, 0);
if (!serviceCanReceiveEther) {
revert FeeDistributor__ServiceCannotReceiveEther(_service);
}
}
/// @inheritdoc IFeeDistributor
function initialize(
FeeRecipient calldata _clientConfig,
FeeRecipient calldata _referrerConfig
) external onlyFactory {
if (_clientConfig.recipient == address(0)) {
revert FeeDistributor__ZeroAddressClient();
}
if (_clientConfig.recipient == i_service) {
revert FeeDistributor__ClientAddressEqualsService(_clientConfig.recipient);
}
if (s_clientConfig.recipient != address(0)) {
revert FeeDistributor__ClientAlreadySet(s_clientConfig.recipient);
}
if (_clientConfig.basisPoints > 10000) {
revert FeeDistributor__InvalidClientBasisPoints(_clientConfig.basisPoints);
}
if (_referrerConfig.recipient != address(0)) {// if there is a referrer
if (_referrerConfig.recipient == i_service) {
revert FeeDistributor__ReferrerAddressEqualsService(_referrerConfig.recipient);
}
if (_referrerConfig.recipient == _clientConfig.recipient) {
revert FeeDistributor__ReferrerAddressEqualsClient(_referrerConfig.recipient);
}
if (_clientConfig.basisPoints + _referrerConfig.basisPoints > 10000) {
revert FeeDistributor__ClientPlusReferralBasisPointsExceed10000(
_clientConfig.basisPoints,
_referrerConfig.basisPoints
);
}
// set referrer config
s_referrerConfig = _referrerConfig;
} else {// if there is no referrer
if (_referrerConfig.basisPoints != 0) {
revert FeeDistributor__ReferrerBasisPointsMustBeZeroIfAddressIsZero(_referrerConfig.basisPoints);
}
}
// set client config
s_clientConfig = _clientConfig;
emit FeeDistributor__Initialized(
_clientConfig.recipient,
_clientConfig.basisPoints,
_referrerConfig.recipient,
_referrerConfig.basisPoints
);
bool clientCanReceiveEther = P2pAddressLib._sendValue(_clientConfig.recipient, 0);
if (!clientCanReceiveEther) {
revert FeeDistributor__ClientCannotReceiveEther(_clientConfig.recipient);
}
if (_referrerConfig.recipient != address(0)) {// if there is a referrer
bool referrerCanReceiveEther = P2pAddressLib._sendValue(_referrerConfig.recipient, 0);
if (!referrerCanReceiveEther) {
revert FeeDistributor__ReferrerCannotReceiveEther(_referrerConfig.recipient);
}
}
}
/// @notice Accept ether from transactions
receive() external payable {
// only accept ether in an instance, not in a template
if (s_clientConfig.recipient == address(0)) {
revert FeeDistributor__ClientNotSet();
}
}
/// @inheritdoc IFeeDistributor
function increaseDepositedCount(uint32 _validatorCountToAdd) external virtual {
// Do nothing by default. Can be overridden.
}
/// @inheritdoc IFeeDistributor
function voluntaryExit(bytes[] calldata _pubkeys) public virtual onlyClient {
emit FeeDistributor__VoluntaryExit(_pubkeys);
}
/// @inheritdoc IFeeDistributor
function factory() external view returns (address) {
return address(i_factory);
}
/// @inheritdoc IFeeDistributor
function service() external view returns (address) {
return i_service;
}
/// @inheritdoc IFeeDistributor
function client() public view override(Erc4337Account, IFeeDistributor) returns (address) {
return s_clientConfig.recipient;
}
/// @inheritdoc IFeeDistributor
function clientBasisPoints() external view returns (uint256) {
return s_clientConfig.basisPoints;
}
/// @inheritdoc IFeeDistributor
function referrer() external view returns (address) {
return s_referrerConfig.recipient;
}
/// @inheritdoc IFeeDistributor
function referrerBasisPoints() external view returns (uint256) {
return s_referrerConfig.basisPoints;
}
/// @inheritdoc IFeeDistributor
function eth2WithdrawalCredentialsAddress() external virtual view returns (address);
/// @inheritdoc ERC165
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IFeeDistributor).interfaceId || super.supportsInterface(interfaceId);
}
/// @inheritdoc IOwnable
function owner() public view override(Erc4337Account, OwnableBase, Ownable) returns (address) {
return i_factory.owner();
}
/// @inheritdoc IOwnableWithOperator
function operator() public view override(Erc4337Account, OwnableWithOperator) returns (address) {
return super.operator();
}
}