@1inch/solidity-utils 2.0.25 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
|
|
3
|
+
pragma solidity ^0.8.0;
|
|
4
|
+
pragma abicoder v1;
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
interface IERC20MetadataUppercase {
|
|
8
|
+
function NAME() external view returns (string memory); // solhint-disable-line func-name-mixedcase
|
|
9
|
+
function SYMBOL() external view returns (string memory); // solhint-disable-line func-name-mixedcase
|
|
10
|
+
}
|
|
@@ -16,6 +16,8 @@ library ECDSA {
|
|
|
16
16
|
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
|
|
17
17
|
// these malleable signatures as well.
|
|
18
18
|
uint256 private constant _S_BOUNDARY = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0 + 1;
|
|
19
|
+
uint256 private constant _COMPACT_S_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
|
|
20
|
+
uint256 private constant _COMPACT_V_SHIFT = 255;
|
|
19
21
|
|
|
20
22
|
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal view returns(address signer) {
|
|
21
23
|
/// @solidity memory-safe-assembly
|
|
@@ -37,12 +39,12 @@ library ECDSA {
|
|
|
37
39
|
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns(address signer) {
|
|
38
40
|
/// @solidity memory-safe-assembly
|
|
39
41
|
assembly { // solhint-disable-line no-inline-assembly
|
|
40
|
-
let s :=
|
|
42
|
+
let s := and(vs, _COMPACT_S_MASK)
|
|
41
43
|
if lt(s, _S_BOUNDARY) {
|
|
42
44
|
let ptr := mload(0x40)
|
|
43
45
|
|
|
44
46
|
mstore(ptr, hash)
|
|
45
|
-
mstore(add(ptr, 0x20), add(27, shr(
|
|
47
|
+
mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))
|
|
46
48
|
mstore(add(ptr, 0x40), r)
|
|
47
49
|
mstore(add(ptr, 0x60), s)
|
|
48
50
|
mstore(0, 0)
|
|
@@ -52,6 +54,13 @@ library ECDSA {
|
|
|
52
54
|
}
|
|
53
55
|
}
|
|
54
56
|
|
|
57
|
+
/// WARNING!!!
|
|
58
|
+
/// There is a known signature malleability issue with two representations of signatures!
|
|
59
|
+
/// Even though this function is able to verify both standard 65-byte and compact 64-byte EIP-2098 signatures
|
|
60
|
+
/// one should never use raw signatures for any kind of invalidation logic in their code.
|
|
61
|
+
/// As the standard and compact representations are interchangeable any invalidation logic that relies on
|
|
62
|
+
/// signature uniqueness will get rekt.
|
|
63
|
+
/// More info: https://github.com/OpenZeppelin/openzeppelin-contracts/security/advisories/GHSA-4h98-2769-gh6h
|
|
55
64
|
function recover(bytes32 hash, bytes calldata signature) internal view returns(address signer) {
|
|
56
65
|
/// @solidity memory-safe-assembly
|
|
57
66
|
assembly { // solhint-disable-line no-inline-assembly
|
|
@@ -67,9 +76,9 @@ library ECDSA {
|
|
|
67
76
|
case 64 {
|
|
68
77
|
// memory[ptr+0x20:ptr+0x80] = (v, r, s)
|
|
69
78
|
let vs := calldataload(add(signature.offset, 0x20))
|
|
70
|
-
mstore(add(ptr, 0x20), add(27, shr(
|
|
79
|
+
mstore(add(ptr, 0x20), add(27, shr(_COMPACT_V_SHIFT, vs)))
|
|
71
80
|
calldatacopy(add(ptr, 0x40), signature.offset, 0x20)
|
|
72
|
-
mstore(add(ptr, 0x60),
|
|
81
|
+
mstore(add(ptr, 0x60), and(vs, _COMPACT_S_MASK))
|
|
73
82
|
}
|
|
74
83
|
default {
|
|
75
84
|
ptr := 0
|
|
@@ -172,7 +181,7 @@ library ECDSA {
|
|
|
172
181
|
mstore(add(ptr, 0x44), 64)
|
|
173
182
|
mstore(add(ptr, 0x64), r)
|
|
174
183
|
mstore(add(ptr, 0x84), vs)
|
|
175
|
-
if staticcall(gas(), signer, ptr,
|
|
184
|
+
if staticcall(gas(), signer, ptr, 0xa4, 0, 0x20) {
|
|
176
185
|
success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))
|
|
177
186
|
}
|
|
178
187
|
}
|
|
@@ -191,8 +200,8 @@ library ECDSA {
|
|
|
191
200
|
mstore(add(ptr, 0x24), 0x40)
|
|
192
201
|
mstore(add(ptr, 0x44), 65)
|
|
193
202
|
mstore(add(ptr, 0x64), r)
|
|
194
|
-
mstore(add(ptr, 0x84),
|
|
195
|
-
mstore8(add(ptr, 0xa4), add(27, shr(
|
|
203
|
+
mstore(add(ptr, 0x84), and(vs, _COMPACT_S_MASK))
|
|
204
|
+
mstore8(add(ptr, 0xa4), add(27, shr(_COMPACT_V_SHIFT, vs)))
|
|
196
205
|
if staticcall(gas(), signer, ptr, 0xa5, 0, 0x20) {
|
|
197
206
|
success := and(eq(selector, mload(0)), eq(returndatasize(), 0x20))
|
|
198
207
|
}
|
|
@@ -5,14 +5,10 @@ pragma abicoder v1;
|
|
|
5
5
|
|
|
6
6
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
7
7
|
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
|
|
8
|
+
import "../interfaces/IERC20MetadataUppercase.sol";
|
|
8
9
|
import "./SafeERC20.sol";
|
|
9
10
|
import "./StringUtil.sol";
|
|
10
11
|
|
|
11
|
-
interface IERC20MetadataUppercase {
|
|
12
|
-
function NAME() external view returns (string memory); // solhint-disable-line func-name-mixedcase
|
|
13
|
-
function SYMBOL() external view returns (string memory); // solhint-disable-line func-name-mixedcase
|
|
14
|
-
}
|
|
15
|
-
|
|
16
12
|
library UniERC20 {
|
|
17
13
|
using SafeERC20 for IERC20;
|
|
18
14
|
|
|
@@ -21,7 +17,9 @@ library UniERC20 {
|
|
|
21
17
|
error NotEnoughValue();
|
|
22
18
|
error FromIsNotSender();
|
|
23
19
|
error ToIsNotThis();
|
|
20
|
+
error ETHTransferFailed();
|
|
24
21
|
|
|
22
|
+
uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
|
|
25
23
|
IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
|
|
26
24
|
IERC20 private constant _ZERO_ADDRESS = IERC20(address(0));
|
|
27
25
|
|
|
@@ -37,18 +35,21 @@ library UniERC20 {
|
|
|
37
35
|
}
|
|
38
36
|
}
|
|
39
37
|
|
|
38
|
+
/// @dev note that this function does nothing in case of zero amount
|
|
40
39
|
function uniTransfer(IERC20 token, address payable to, uint256 amount) internal {
|
|
41
40
|
if (amount > 0) {
|
|
42
41
|
if (isETH(token)) {
|
|
43
42
|
if (address(this).balance < amount) revert InsufficientBalance();
|
|
44
|
-
//
|
|
45
|
-
to.
|
|
43
|
+
// solhint-disable-next-line avoid-low-level-calls
|
|
44
|
+
(bool success, ) = to.call{value: amount, gas: _RAW_CALL_GAS_LIMIT}("");
|
|
45
|
+
if (!success) revert ETHTransferFailed();
|
|
46
46
|
} else {
|
|
47
47
|
token.safeTransfer(to, amount);
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/// @dev note that this function does nothing in case of zero amount
|
|
52
53
|
function uniTransferFrom(IERC20 token, address payable from, address to, uint256 amount) internal {
|
|
53
54
|
if (amount > 0) {
|
|
54
55
|
if (isETH(token)) {
|
|
@@ -57,8 +58,11 @@ library UniERC20 {
|
|
|
57
58
|
if (to != address(this)) revert ToIsNotThis();
|
|
58
59
|
if (msg.value > amount) {
|
|
59
60
|
// Return remainder if exist
|
|
60
|
-
|
|
61
|
-
|
|
61
|
+
unchecked {
|
|
62
|
+
// solhint-disable-next-line avoid-low-level-calls
|
|
63
|
+
(bool success, ) = from.call{value: msg.value - amount, gas: _RAW_CALL_GAS_LIMIT}("");
|
|
64
|
+
if (!success) revert ETHTransferFailed();
|
|
65
|
+
}
|
|
62
66
|
}
|
|
63
67
|
} else {
|
|
64
68
|
token.safeTransferFrom(from, to, amount);
|
|
@@ -80,6 +84,8 @@ library UniERC20 {
|
|
|
80
84
|
token.forceApprove(to, amount);
|
|
81
85
|
}
|
|
82
86
|
|
|
87
|
+
/// 20K gas is provided to account for possible implementations of name/symbol
|
|
88
|
+
/// (token implementation might be behind proxy or store the value in storage)
|
|
83
89
|
function _uniDecode(IERC20 token, bytes4 lowerCaseSelector, bytes4 upperCaseSelector) private view returns(string memory result) {
|
|
84
90
|
if (isETH(token)) {
|
|
85
91
|
return "ETH";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@1inch/solidity-utils",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"main": "dist/src/index.js",
|
|
5
5
|
"types": "dist/src/index.d.ts",
|
|
6
6
|
"repository": {
|
|
@@ -27,49 +27,49 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@metamask/eth-sig-util": "4.0.1",
|
|
30
|
-
"@openzeppelin/contracts": "4.
|
|
31
|
-
"@openzeppelin/test-helpers": "0.5.
|
|
30
|
+
"@openzeppelin/contracts": "4.7.3",
|
|
31
|
+
"@openzeppelin/test-helpers": "0.5.16",
|
|
32
32
|
"bn.js": "5.2.1",
|
|
33
33
|
"chai": "4.3.6",
|
|
34
34
|
"chai-as-promised": "7.1.1",
|
|
35
35
|
"chai-bn": "0.3.1",
|
|
36
36
|
"ethereumjs-util": "7.1.5",
|
|
37
|
-
"web3-utils": "1.
|
|
37
|
+
"web3-utils": "1.8.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@nomiclabs/hardhat-truffle5": "2.0.
|
|
40
|
+
"@nomiclabs/hardhat-truffle5": "2.0.7",
|
|
41
41
|
"@nomiclabs/hardhat-web3": "2.0.0",
|
|
42
|
-
"@typechain/hardhat": "
|
|
42
|
+
"@typechain/hardhat": "6.1.3",
|
|
43
43
|
"@typechain/truffle-v5": "7.0.0",
|
|
44
|
-
"@types/chai": "4.3.
|
|
44
|
+
"@types/chai": "4.3.3",
|
|
45
45
|
"@types/chai-as-promised": "7.1.5",
|
|
46
46
|
"@types/eth-sig-util": "2.1.1",
|
|
47
47
|
"@types/ethereumjs-util": "6.1.0",
|
|
48
48
|
"@types/mocha": "9.1.1",
|
|
49
|
-
"@types/node": "18.
|
|
50
|
-
"@typescript-eslint/eslint-plugin": "5.
|
|
51
|
-
"@typescript-eslint/parser": "5.
|
|
49
|
+
"@types/node": "18.7.18",
|
|
50
|
+
"@typescript-eslint/eslint-plugin": "5.38.0",
|
|
51
|
+
"@typescript-eslint/parser": "5.38.0",
|
|
52
52
|
"acquit": "1.2.1",
|
|
53
|
-
"commander": "9.
|
|
53
|
+
"commander": "9.4.0",
|
|
54
54
|
"create-ts-index": "1.14.0",
|
|
55
55
|
"cross-spawn": "7.0.3",
|
|
56
|
-
"dotenv": "16.0.
|
|
57
|
-
"eslint": "8.
|
|
56
|
+
"dotenv": "16.0.2",
|
|
57
|
+
"eslint": "8.23.1",
|
|
58
58
|
"eslint-config-standard": "17.0.0",
|
|
59
59
|
"eslint-plugin-import": "2.26.0",
|
|
60
|
-
"eslint-plugin-n": "15.2.
|
|
61
|
-
"eslint-plugin-promise": "6.0.
|
|
60
|
+
"eslint-plugin-n": "15.2.5",
|
|
61
|
+
"eslint-plugin-promise": "6.0.1",
|
|
62
62
|
"eslint-plugin-standard": "5.0.0",
|
|
63
63
|
"ethereumjs-wallet": "1.0.2",
|
|
64
|
-
"hardhat": "2.
|
|
65
|
-
"hardhat-gas-reporter": "1.0.
|
|
64
|
+
"hardhat": "2.11.2",
|
|
65
|
+
"hardhat-gas-reporter": "1.0.9",
|
|
66
66
|
"rimraf": "3.0.2",
|
|
67
67
|
"shx": "0.3.4",
|
|
68
68
|
"solhint": "3.3.7",
|
|
69
|
-
"solidity-coverage": "0.
|
|
70
|
-
"ts-node": "10.
|
|
71
|
-
"typechain": "7.0.
|
|
72
|
-
"typescript": "4.
|
|
69
|
+
"solidity-coverage": "0.8.2",
|
|
70
|
+
"ts-node": "10.9.1",
|
|
71
|
+
"typechain": "7.0.1",
|
|
72
|
+
"typescript": "4.8.3"
|
|
73
73
|
},
|
|
74
74
|
"bin": {
|
|
75
75
|
"solidity-utils-docify": "utils/docify.utils.js",
|