-
Notifications
You must be signed in to change notification settings - Fork 15
/
Copy pathToken6.sol
162 lines (144 loc) · 5.8 KB
/
Token6.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
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "../../number/types/UFixed6.sol";
/// @dev Token6
type Token6 is address;
using Token6Lib for Token6 global;
type Token6Storage is bytes32;
using Token6StorageLib for Token6Storage global;
/**
* @title Token6Lib
* @notice Library to manage 6-decimal ERC20s that is compliant with the fixed-decimal types.
*/
library Token6Lib {
using SafeERC20 for IERC20;
Token6 public constant ZERO = Token6.wrap(address(0));
/**
* @notice Returns whether a token is the zero address
* @param self Token to check for
* @return Whether the token is the zero address
*/
function isZero(Token6 self) internal pure returns (bool) {
return Token6.unwrap(self) == Token6.unwrap(ZERO);
}
/**
* @notice Returns whether the two tokens are equal
* @param a First token to compare
* @param b Second token to compare
* @return Whether the two tokens are equal
*/
function eq(Token6 a, Token6 b) internal pure returns (bool) {
return Token6.unwrap(a) == Token6.unwrap(b);
}
/**
* @notice Approves `grantee` to spend infinite tokens from the caller
* @dev Uses `approve` rather than `safeApprove` since the race condition
* in safeApprove does not apply when going to an infinite approval
* @param self Token to grant approval
* @param self Token to grant approval
* @param grantee Address to allow spending
*/
function approve(Token6 self, address grantee) internal {
IERC20(Token6.unwrap(self)).approve(grantee, type(uint256).max);
}
/**
* @notice Approves `grantee` to spend `amount` tokens from the caller
* @dev There are important race conditions to be aware of when using this function
with values other than 0. This will revert if moving from non-zero to non-zero amounts
See https://github.com/OpenZeppelin/openzeppelin-contracts/blob/a55b7d13722e7ce850b626da2313f3e66ca1d101/contracts/token/ERC20/IERC20.sol#L57
* @param self Token to grant approval
* @param self Token to grant approval
* @param grantee Address to allow spending
* @param amount Amount of tokens to approve to spend
*/
function approve(Token6 self, address grantee, UFixed6 amount) internal {
IERC20(Token6.unwrap(self)).safeApprove(grantee, UFixed6.unwrap(amount));
}
/**
* @notice Transfers all held tokens from the caller to the `recipient`
* @param self Token to transfer
* @param recipient Address to receive the tokens
*/
function push(Token6 self, address recipient) internal {
push(self, recipient, balanceOf(self, address(this)));
}
/**
* @notice Transfers `amount` tokens from the caller to the `recipient`
* @param self Token to transfer
* @param recipient Address to transfer tokens to
* @param amount Amount of tokens to transfer
*/
function push(Token6 self, address recipient, UFixed6 amount) internal {
IERC20(Token6.unwrap(self)).safeTransfer(recipient, UFixed6.unwrap(amount));
}
/**
* @notice Transfers `amount` tokens from the `benefactor` to the caller
* @dev Reverts if trying to pull Ether
* @param self Token to transfer
* @param benefactor Address to transfer tokens from
* @param amount Amount of tokens to transfer
*/
function pull(Token6 self, address benefactor, UFixed6 amount) internal {
IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, address(this), UFixed6.unwrap(amount));
}
/**
* @notice Transfers `amount` tokens from the `benefactor` to `recipient`
* @dev Reverts if trying to pull Ether
* @param self Token to transfer
* @param benefactor Address to transfer tokens from
* @param recipient Address to transfer tokens to
* @param amount Amount of tokens to transfer
*/
function pullTo(Token6 self, address benefactor, address recipient, UFixed6 amount) internal {
IERC20(Token6.unwrap(self)).safeTransferFrom(benefactor, recipient, UFixed6.unwrap(amount));
}
/**
* @notice Returns the name of the token
* @param self Token to check for
* @return Token name
*/
function name(Token6 self) internal view returns (string memory) {
return IERC20Metadata(Token6.unwrap(self)).name();
}
/**
* @notice Returns the symbol of the token
* @param self Token to check for
* @return Token symbol
*/
function symbol(Token6 self) internal view returns (string memory) {
return IERC20Metadata(Token6.unwrap(self)).symbol();
}
/**
* @notice Returns the `self` token balance of the caller
* @param self Token to check for
* @return Token balance of the caller
*/
function balanceOf(Token6 self) internal view returns (UFixed6) {
return balanceOf(self, address(this));
}
/**
* @notice Returns the `self` token balance of `account`
* @param self Token to check for
* @param account Account to check
* @return Token balance of the account
*/
function balanceOf(Token6 self, address account) internal view returns (UFixed6) {
return UFixed6.wrap(IERC20(Token6.unwrap(self)).balanceOf(account));
}
}
library Token6StorageLib {
function read(Token6Storage self) internal view returns (Token6 value) {
assembly ("memory-safe") {
value := sload(self)
}
}
function store(Token6Storage self, Token6 value) internal {
assembly ("memory-safe") {
sstore(self, value)
}
}
}