forked from limitbreakinc/creator-token-standards
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ERC20C.sol
153 lines (134 loc) · 6.14 KB
/
ERC20C.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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import "../utils/AutomaticValidatorTransferApproval.sol";
import "../utils/CreatorTokenBase.sol";
import "../token/erc20/ERC20OpenZeppelin.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {TOKEN_TYPE_ERC20} from "@limitbreak/permit-c/Constants.sol";
/**
* @title ERC20C
* @author Limit Break, Inc.
* @notice Extends OpenZeppelin's ERC20 implementation with Creator Token functionality, which
* allows the contract owner to update the transfer validation logic by managing a security policy in
* an external transfer validation security policy registry. See {CreatorTokenTransferValidator}.
*/
abstract contract ERC20C is ERC165, ERC20OpenZeppelin, CreatorTokenBase, AutomaticValidatorTransferApproval {
/**
* @notice Overrides behavior of allowance such that if a spender is not explicitly approved,
* the contract owner can optionally auto-approve the 20-C transfer validator for transfers.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256 _allowance) {
_allowance = super.allowance(owner, spender);
if (_allowance == 0) {
if (autoApproveTransfersFromValidator) {
if (spender == address(getTransferValidator())) {
_allowance = type(uint256).max;
}
}
}
}
/**
* @notice Indicates whether the contract implements the specified interface.
* @dev Overrides supportsInterface in ERC165.
* @param interfaceId The interface id
* @return true if the contract implements the specified interface, false otherwise
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
interfaceId == type(IERC20).interfaceId ||
interfaceId == type(IERC20Metadata).interfaceId ||
interfaceId == type(ICreatorToken).interfaceId ||
interfaceId == type(ICreatorTokenLegacy).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @notice Returns the function selector for the transfer validator's validation function to be called
* @notice for transaction simulation.
*/
function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256,uint256)"));
isViewFunction = false;
}
/// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic
function _beforeTokenTransfer(
address from,
address to,
uint256 amount) internal virtual override {
_validateBeforeTransfer(from, to, 0, amount);
}
/// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic
function _afterTokenTransfer(
address from,
address to,
uint256 amount) internal virtual override {
_validateAfterTransfer(from, to, 0, amount);
}
function _tokenType() internal pure override returns(uint16) {
return uint16(TOKEN_TYPE_ERC20);
}
}
/**
* @title ERC20CInitializable
* @author Limit Break, Inc.
* @notice Initializable implementation of ERC20C to allow for EIP-1167 proxy clones.
*/
abstract contract ERC20CInitializable is ERC165, ERC20OpenZeppelinInitializable, CreatorTokenBase, AutomaticValidatorTransferApproval {
function initializeERC20(string memory name_, string memory symbol_, uint8 decimals_) public override {
super.initializeERC20(name_, symbol_, decimals_);
_emitDefaultTransferValidator();
_registerTokenType(getTransferValidator());
}
/**
* @notice Overrides behavior of allowance such that if a spender is not explicitly approved,
* the contract owner can optionally auto-approve the 20-C transfer validator for transfers.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256 _allowance) {
_allowance = super.allowance(owner, spender);
if (_allowance == 0) {
if (autoApproveTransfersFromValidator) {
if (spender == address(getTransferValidator())) {
_allowance = type(uint256).max;
}
}
}
}
/**
* @notice Indicates whether the contract implements the specified interface.
* @dev Overrides supportsInterface in ERC165.
* @param interfaceId The interface id
* @return true if the contract implements the specified interface, false otherwise
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return
interfaceId == type(IERC20).interfaceId ||
interfaceId == type(IERC20Metadata).interfaceId ||
interfaceId == type(ICreatorToken).interfaceId ||
interfaceId == type(ICreatorTokenLegacy).interfaceId ||
super.supportsInterface(interfaceId);
}
/**
* @notice Returns the function selector for the transfer validator's validation function to be called
* @notice for transaction simulation.
*/
function getTransferValidationFunction() external pure returns (bytes4 functionSignature, bool isViewFunction) {
functionSignature = bytes4(keccak256("validateTransfer(address,address,address,uint256,uint256)"));
isViewFunction = false;
}
/// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logic
function _beforeTokenTransfer(
address from,
address to,
uint256 amount) internal virtual override {
_validateBeforeTransfer(from, to, 0, amount);
}
/// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logic
function _afterTokenTransfer(
address from,
address to,
uint256 amount) internal virtual override {
_validateAfterTransfer(from, to, 0, amount);
}
function _tokenType() internal pure override returns(uint16) {
return uint16(TOKEN_TYPE_ERC20);
}
}