-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathERC721RoyaltyComposer.sol
131 lines (111 loc) · 3.95 KB
/
ERC721RoyaltyComposer.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
// SPDX-License-Identifier: MIT
/// @title Objective Royalty Composer ERC721 Extension (openzeppelin)
/// @author Dean van Dugteren (https://github.com/deanpress)
/// @notice Extends an ERC721 contract with the Objective Contracts Filter
pragma solidity ^0.8.0;
// Import this file to use console.log
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
interface IORC {
function filterAddress(address to) external view;
function isORC() external pure returns (bool);
function isAddressOrced(address to) external view returns (bool);
}
interface IERC20 {
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
}
abstract contract ERC721RoyaltyComposer is ERC721 {
bool public orcPaused;
IORC public orc; // Objective Royalty Composer
uint256 public orcPremium;
IERC20 private weth;
struct PremiumData {
uint256 latestUpdateTime;
uint64 minInterval;
uint64 maxIncreasePercent;
}
PremiumData public premiumData;
address public royaltyRecipient;
error NotEnoughWethAllowanceForPremium(uint256 allowance, uint256 required);
constructor(
address orcAddress,
address wethAddress,
uint256 premium,
uint64 minInterval,
uint64 maxIncreasePercent
) {
orc = IORC(orcAddress);
weth = IERC20(wethAddress);
royaltyRecipient = address(this);
orcPremium = premium;
premiumData = PremiumData(minInterval, maxIncreasePercent, 0);
if (!orc.isORC()) revert("Not a valid ORC address");
}
/// @dev Filters destination address with ORC
modifier filterAddress(address to) {
if (!orcPaused) {
orc.filterAddress(to);
}
_;
}
// Adds a WETH charge to the sender if the receiver is a contract that bypasses royalties
function _chargePremiumIfNeeded(address to) internal {
// Nested if statements save gas
if (orcPremium > 0) {
if (orc.isAddressOrced(to)) {
if (!weth.transferFrom(msg.sender, to, orcPremium))
revert NotEnoughWethAllowanceForPremium(
weth.allowance(msg.sender, address(this)),
orcPremium
);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId
) internal virtual override {
_chargePremiumIfNeeded(to);
super._beforeTokenTransfer(from, to, tokenId);
}
function _pauseFilter() internal virtual {
orcPaused = true;
}
function _unpauseFilter() internal virtual {
orcPaused = false;
}
function _setPremium(uint256 _premium) internal virtual {
// Only allow orcPremium to update if the timestamp is greater than the latestIncreaseTime + minInterval
if (
block.timestamp >
premiumData.latestUpdateTime + premiumData.minInterval
) {
// Check that _premium is not greater than the max increase percentage for orcPremium
if (
_premium <=
orcPremium +
((orcPremium * 1 ether) * premiumData.maxIncreasePercent) /
100 /
1 ether
) {
orcPremium = _premium;
premiumData.latestUpdateTime = block.timestamp;
} else {
revert("ORC: Premium is greater than the max allowed increase");
}
} else {
revert("ORC: Premium update interval has not been reached");
}
}
function _setRoyaltyRecipient(address _to) internal virtual {
royaltyRecipient = _to;
}
}