-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSplit.sol
More file actions
169 lines (138 loc) · 5.49 KB
/
Copy pathSplit.sol
File metadata and controls
169 lines (138 loc) · 5.49 KB
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
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.11;
// Base
import "./openzeppelin-presets/finance/PaymentSplitterUpgradeable.sol";
import "./interfaces/IThirdwebContract.sol";
// Meta-tx
import "./openzeppelin-presets/metatx/ERC2771ContextUpgradeable.sol";
// Access
import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
// Utils
import "@openzeppelin/contracts-upgradeable/utils/MulticallUpgradeable.sol";
import "./lib/FeeType.sol";
contract Split is
IThirdwebContract,
Initializable,
MulticallUpgradeable,
ERC2771ContextUpgradeable,
AccessControlEnumerableUpgradeable,
PaymentSplitterUpgradeable
{
bytes32 private constant MODULE_TYPE = bytes32("Split");
uint128 private constant VERSION = 1;
/// @dev Max bps in the thirdweb system
uint128 private constant MAX_BPS = 10_000;
/// @dev Contract level metadata.
string public contractURI;
constructor() initializer {}
/// @dev Performs the job of the constructor.
/// @dev shares_ are scaled by 10,000 to prevent precision loss when including fees
function initialize(
address _defaultAdmin,
string memory _contractURI,
address[] memory _trustedForwarders,
address[] memory _payees,
uint256[] memory _shares
) external initializer {
// Initialize inherited contracts: most base -> most derived
__ERC2771Context_init(_trustedForwarders);
__PaymentSplitter_init(_payees, _shares);
contractURI = _contractURI;
_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
}
/// @dev Returns the module type of the contract.
function contractType() external pure returns (bytes32) {
return MODULE_TYPE;
}
/// @dev Returns the version of the contract.
function contractVersion() external pure returns (uint8) {
return uint8(VERSION);
}
/**
* @dev Triggers a transfer to `account` of the amount of Ether they are owed, according to their percentage of the
* total shares and their previous withdrawals.
*/
function release(address payable account) public virtual override {
uint256 payment = _release(account);
require(payment != 0, "PaymentSplitter: account is not due payment");
}
/**
* @dev Triggers a transfer to `account` of the amount of `token` tokens they are owed, according to their
* percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20
* contract.
*/
function release(IERC20Upgradeable token, address account) public virtual override {
uint256 payment = _release(token, account);
require(payment != 0, "PaymentSplitter: account is not due payment");
}
/// @dev Returns the amount of Ether that `account` is owed, according to their percentage of the total shares and returns the payment
function _release(address payable account) internal returns (uint256) {
require(shares(account) > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = address(this).balance + totalReleased();
uint256 payment = _pendingPayment(account, totalReceived, released(account));
if (payment == 0) {
return 0;
}
_released[account] += payment;
_totalReleased += payment;
AddressUpgradeable.sendValue(account, payment);
emit PaymentReleased(account, payment);
return payment;
}
/// @dev Returns the amount of `token` that `account` is owed, according to their percentage of the total shares and returns the payment
function _release(IERC20Upgradeable token, address account) internal returns (uint256) {
require(shares(account) > 0, "PaymentSplitter: account has no shares");
uint256 totalReceived = token.balanceOf(address(this)) + totalReleased(token);
uint256 payment = _pendingPayment(account, totalReceived, released(token, account));
if (payment == 0) {
return 0;
}
_erc20Released[token][account] += payment;
_erc20TotalReleased[token] += payment;
SafeERC20Upgradeable.safeTransfer(token, account, payment);
emit ERC20PaymentReleased(token, account, payment);
return payment;
}
/**
* @dev Release the owed amount of token to all of the payees.
*/
function distribute() public virtual {
uint256 count = payeeCount();
for (uint256 i = 0; i < count; i++) {
_release(payable(payee(i)));
}
}
/**
* @dev Release owed amount of the `token` to all of the payees.
*/
function distribute(IERC20Upgradeable token) public virtual {
uint256 count = payeeCount();
for (uint256 i = 0; i < count; i++) {
_release(token, payee(i));
}
}
/// @dev See ERC2771
function _msgSender()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}
/// @dev See ERC2771
function _msgData()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (bytes calldata)
{
return ERC2771ContextUpgradeable._msgData();
}
/// @dev Sets contract URI for the contract-level metadata of the contract.
function setContractURI(string calldata _uri) external onlyRole(DEFAULT_ADMIN_ROLE) {
contractURI = _uri;
}
}