test-isol-01 0.0.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.
- package/README.md +15 -0
- package/contracts/ERC3009/ERC3009.sol +67 -0
- package/contracts/ERC3009/IERC3009.sol +35 -0
- package/contracts/adapter/ITransferAuthorize.sol +76 -0
- package/contracts/adapter/TransferAuthorize.sol +97 -0
- package/contracts/adapter copy/ITransferAuthorize.sol +35 -0
- package/contracts/adapter copy/TransferAuthorize.sol +67 -0
- package/contracts/extensions/ERC20TransferAuth.sol +71 -0
- package/contracts/extensions/TransferWithAuthorize.sol +88 -0
- package/contracts/extensions/erc20/ERC20TransferWithAuthorize.sol +122 -0
- package/contracts/extensions/erc20/ERC20WrappedWithAuthorize.sol +51 -0
- package/contracts/extensions copy/ERC20TransferAuth.sol +71 -0
- package/contracts/extensions copy/erc20/ERC20TransferWithAuthorize.sol +71 -0
- package/contracts/token/ERC20/extensions/ERC20WithAuthorization.sol +71 -0
- package/contracts/token/ERC20/extensions/SendWithAuthorization.sol +71 -0
- package/index.ts +1 -0
- package/package.json +15 -0
- package/tsconfig.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# test-isol
|
|
2
|
+
|
|
3
|
+
To install dependencies:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
bun install
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
To run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
bun run index.ts
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This project was created using `bun init` in bun v1.3.0. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
|
|
5
|
+
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
|
6
|
+
import "./IERC3009.sol";
|
|
7
|
+
|
|
8
|
+
abstract contract ERC3009 is IERC3009, EIP712 {
|
|
9
|
+
using ECDSA for bytes32;
|
|
10
|
+
|
|
11
|
+
constructor(string memory name, string memory version)
|
|
12
|
+
EIP712(name, version)
|
|
13
|
+
{}
|
|
14
|
+
|
|
15
|
+
mapping(address => mapping(bytes32 => bool)) private _authorizationState;
|
|
16
|
+
|
|
17
|
+
bytes32 public constant RECEIVE_WITH_AUTHORIZATION_TYPEHASH =
|
|
18
|
+
keccak256("ReceiveWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
19
|
+
|
|
20
|
+
bytes32 public constant TRANSFER_WITH_AUTHORIZATION_TYPEHASH =
|
|
21
|
+
keccak256("TransferWithAuthorization(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
22
|
+
|
|
23
|
+
function authorizationState(address authorizer, bytes32 nonce)
|
|
24
|
+
public
|
|
25
|
+
view
|
|
26
|
+
override
|
|
27
|
+
returns (bool)
|
|
28
|
+
{
|
|
29
|
+
return _authorizationState[authorizer][nonce];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function _useAuthorization(address authorizer, bytes32 nonce) internal {
|
|
33
|
+
require(!_authorizationState[authorizer][nonce], "ERC3009: authorization already used");
|
|
34
|
+
_authorizationState[authorizer][nonce] = true;
|
|
35
|
+
emit AuthorizationUsed(authorizer, nonce);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function _verify(
|
|
39
|
+
bytes32 typehash,
|
|
40
|
+
address from,
|
|
41
|
+
address to,
|
|
42
|
+
uint256 value,
|
|
43
|
+
uint256 validAfter,
|
|
44
|
+
uint256 validBefore,
|
|
45
|
+
bytes32 nonce,
|
|
46
|
+
uint8 v,
|
|
47
|
+
bytes32 r,
|
|
48
|
+
bytes32 s
|
|
49
|
+
) internal view returns (address signer) {
|
|
50
|
+
require(block.timestamp > validAfter, "ERC3009: not yet valid");
|
|
51
|
+
require(block.timestamp < validBefore, "ERC3009: expired");
|
|
52
|
+
|
|
53
|
+
bytes32 structHash = keccak256(
|
|
54
|
+
abi.encode(
|
|
55
|
+
typehash,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
signer = _hashTypedDataV4(structHash).recover(v, r, s);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
interface IERC3009 {
|
|
5
|
+
event AuthorizationUsed(address indexed authorizer, bytes32 indexed nonce);
|
|
6
|
+
|
|
7
|
+
function authorizationState(address authorizer, bytes32 nonce)
|
|
8
|
+
external
|
|
9
|
+
view
|
|
10
|
+
returns (bool);
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorization(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external;
|
|
23
|
+
|
|
24
|
+
function transferWithAuthorization(
|
|
25
|
+
address from,
|
|
26
|
+
address to,
|
|
27
|
+
uint256 value,
|
|
28
|
+
uint256 validAfter,
|
|
29
|
+
uint256 validBefore,
|
|
30
|
+
bytes32 nonce,
|
|
31
|
+
uint8 v,
|
|
32
|
+
bytes32 r,
|
|
33
|
+
bytes32 s
|
|
34
|
+
) external;
|
|
35
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
/// @title ITransferAuthorize
|
|
5
|
+
/// @notice Interface for EIP-712 based transfer/receive authorizations (signed approvals)
|
|
6
|
+
/// @dev Events and function signatures used by TransferAuthorize/implementations
|
|
7
|
+
interface ITransferAuthorize {
|
|
8
|
+
/// @notice Emitted when an authorization (nonce) has been consumed for an authorizer
|
|
9
|
+
/// @param authorizer the account that signed the authorization
|
|
10
|
+
/// @param nonce unique nonce used by the authorization
|
|
11
|
+
event AuthorizeUsed(address indexed authorizer, bytes32 indexed nonce);
|
|
12
|
+
|
|
13
|
+
/// @notice Returns whether a nonce has been used for a given authorizer
|
|
14
|
+
/// @param authorizer the account that signed the authorization
|
|
15
|
+
/// @param nonce the nonce to check
|
|
16
|
+
/// @return true if the nonce was already used/consumed, false otherwise
|
|
17
|
+
function authorizeState(
|
|
18
|
+
address authorizer,
|
|
19
|
+
bytes32 nonce
|
|
20
|
+
) external view returns (bool);
|
|
21
|
+
|
|
22
|
+
/// @notice Execute a "receive with authorization" - typically the recipient must call this
|
|
23
|
+
/// @dev See implementation for access constraints (e.g. only `to` may call)
|
|
24
|
+
function receiveWithAuthorize(
|
|
25
|
+
address from,
|
|
26
|
+
address to,
|
|
27
|
+
uint256 value,
|
|
28
|
+
uint256 validAfter,
|
|
29
|
+
uint256 validBefore,
|
|
30
|
+
bytes32 nonce,
|
|
31
|
+
uint8 v,
|
|
32
|
+
bytes32 r,
|
|
33
|
+
bytes32 s
|
|
34
|
+
) external;
|
|
35
|
+
|
|
36
|
+
/// @notice Execute a "transfer with authorization" - typically any relayer may submit
|
|
37
|
+
function transferWithAuthorize(
|
|
38
|
+
address from,
|
|
39
|
+
address to,
|
|
40
|
+
uint256 value,
|
|
41
|
+
uint256 validAfter,
|
|
42
|
+
uint256 validBefore,
|
|
43
|
+
bytes32 nonce,
|
|
44
|
+
uint8 v,
|
|
45
|
+
bytes32 r,
|
|
46
|
+
bytes32 s
|
|
47
|
+
) external;
|
|
48
|
+
|
|
49
|
+
// ++
|
|
50
|
+
/// @notice Execute a "approve with authorization" - typically any relayer may submit
|
|
51
|
+
function approveWithSignature(
|
|
52
|
+
address from,
|
|
53
|
+
address to,
|
|
54
|
+
uint256 value,
|
|
55
|
+
uint256 validAfter,
|
|
56
|
+
uint256 validBefore,
|
|
57
|
+
bytes32 nonce,
|
|
58
|
+
uint8 v,
|
|
59
|
+
bytes32 r,
|
|
60
|
+
bytes32 s
|
|
61
|
+
) external;
|
|
62
|
+
|
|
63
|
+
/// @notice Standard ERC20 approve
|
|
64
|
+
// function approve(address spender, uint256 amount) external returns (bool);
|
|
65
|
+
|
|
66
|
+
/// @notice Approve with signature (EIP-2612 style)
|
|
67
|
+
// function approveWithSignature(
|
|
68
|
+
// address owner,
|
|
69
|
+
// address spender,
|
|
70
|
+
// uint256 value,
|
|
71
|
+
// uint256 deadline,
|
|
72
|
+
// uint8 v,
|
|
73
|
+
// bytes32 r,
|
|
74
|
+
// bytes32 s
|
|
75
|
+
// ) external;
|
|
76
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
|
|
5
|
+
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
|
6
|
+
import "./ITransferAuthorize.sol";
|
|
7
|
+
|
|
8
|
+
/// @title TransferAuthorize
|
|
9
|
+
/// @notice Abstract helper implementing EIP-712 verification and nonce tracking for off-chain signed authorizations
|
|
10
|
+
/// @dev Implementations should call `_verify` and `_useAuthorize` before performing state changes
|
|
11
|
+
abstract contract TransferAuthorize is ITransferAuthorize, EIP712 {
|
|
12
|
+
using ECDSA for bytes32;
|
|
13
|
+
|
|
14
|
+
/// @dev mapping to track used nonces per authorizer: authorizer => nonce => used
|
|
15
|
+
mapping(address => mapping(bytes32 => bool)) private _authorizeState;
|
|
16
|
+
|
|
17
|
+
/// @dev EIP-712 type hashes for the two supported authorization structures
|
|
18
|
+
bytes32 public constant RECEIVE_TYPEHASH =
|
|
19
|
+
keccak256("ReceiveWithAuthorize(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
20
|
+
|
|
21
|
+
bytes32 public constant TRANSFER_TYPEHASH =
|
|
22
|
+
keccak256("TransferWithAuthorize(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
23
|
+
|
|
24
|
+
bytes32 public constant APPROVE_TYPEHASH =
|
|
25
|
+
keccak256("ApproveWithAuthorize(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
26
|
+
|
|
27
|
+
/// @param name EIP-712 domain name
|
|
28
|
+
/// @param version EIP-712 domain version
|
|
29
|
+
constructor(string memory name, string memory version) EIP712(name, version) {}
|
|
30
|
+
|
|
31
|
+
/// @notice Check whether a nonce has been used for an authorizer
|
|
32
|
+
/// @param authorizer signer address
|
|
33
|
+
/// @param nonce nonce value
|
|
34
|
+
/// @return true if used
|
|
35
|
+
function authorizeState(address authorizer, bytes32 nonce)
|
|
36
|
+
public
|
|
37
|
+
view
|
|
38
|
+
override
|
|
39
|
+
returns (bool)
|
|
40
|
+
{
|
|
41
|
+
return _authorizeState[authorizer][nonce];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// @dev Mark an authorization (authorizer + nonce) as used. Emits AuthorizeUsed.
|
|
45
|
+
/// @param authorizer the signer of the authorization
|
|
46
|
+
/// @param nonce the nonce used in the signed authorization
|
|
47
|
+
function _useAuthorize(address authorizer, bytes32 nonce) internal {
|
|
48
|
+
require(!_authorizeState[authorizer][nonce], "TransferAuthorize: authorization already used");
|
|
49
|
+
_authorizeState[authorizer][nonce] = true;
|
|
50
|
+
emit AuthorizeUsed(authorizer, nonce);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// @dev Verify an EIP-712 typed signature and return the recovered signer
|
|
54
|
+
/// @param typehash the type hash for the struct (RECEIVE_TYPEHASH or TRANSFER_TYPEHASH)
|
|
55
|
+
/// @param from authorizer (the account that signed)
|
|
56
|
+
/// @param to recipient
|
|
57
|
+
/// @param value amount
|
|
58
|
+
/// @param validAfter earliest valid timestamp (inclusive)
|
|
59
|
+
/// @param validBefore latest valid timestamp (inclusive)
|
|
60
|
+
/// @param nonce nonce value
|
|
61
|
+
/// @param v signature v
|
|
62
|
+
/// @param r signature r
|
|
63
|
+
/// @param s signature s
|
|
64
|
+
/// @return signer recovered address
|
|
65
|
+
function _verify(
|
|
66
|
+
bytes32 typehash,
|
|
67
|
+
address from,
|
|
68
|
+
address to,
|
|
69
|
+
uint256 value,
|
|
70
|
+
uint256 validAfter,
|
|
71
|
+
uint256 validBefore,
|
|
72
|
+
bytes32 nonce,
|
|
73
|
+
uint8 v,
|
|
74
|
+
bytes32 r,
|
|
75
|
+
bytes32 s
|
|
76
|
+
) internal view returns (address signer) {
|
|
77
|
+
// Validate time: require validAfter <= validBefore
|
|
78
|
+
require(block.timestamp > validAfter, "TransferAuthorize: not yet valid");
|
|
79
|
+
require(block.timestamp < validBefore, "TransferAuthorize: expired");
|
|
80
|
+
|
|
81
|
+
// Hash the struct per EIP-712
|
|
82
|
+
bytes32 structHash = keccak256(
|
|
83
|
+
abi.encode(
|
|
84
|
+
typehash,
|
|
85
|
+
from,
|
|
86
|
+
to,
|
|
87
|
+
value,
|
|
88
|
+
validAfter,
|
|
89
|
+
validBefore,
|
|
90
|
+
nonce
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
// Recover the signer from the domain-separated digest
|
|
95
|
+
signer = _hashTypedDataV4(structHash).recover(v, r, s);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
interface ITransferAuthorize {
|
|
5
|
+
event AuthorizeUsed(address indexed authorizer, bytes32 indexed nonce);
|
|
6
|
+
|
|
7
|
+
function authorizeState(address authorizer, bytes32 nonce)
|
|
8
|
+
external
|
|
9
|
+
view
|
|
10
|
+
returns (bool);
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorize(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external;
|
|
23
|
+
|
|
24
|
+
function transferWithAuthorize(
|
|
25
|
+
address from,
|
|
26
|
+
address to,
|
|
27
|
+
uint256 value,
|
|
28
|
+
uint256 validAfter,
|
|
29
|
+
uint256 validBefore,
|
|
30
|
+
bytes32 nonce,
|
|
31
|
+
uint8 v,
|
|
32
|
+
bytes32 r,
|
|
33
|
+
bytes32 s
|
|
34
|
+
) external;
|
|
35
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
|
|
5
|
+
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
|
6
|
+
import "./ITransferAuthorize.sol";
|
|
7
|
+
|
|
8
|
+
abstract contract TransferAuthorize is ITransferAuthorize, EIP712 {
|
|
9
|
+
using ECDSA for bytes32;
|
|
10
|
+
|
|
11
|
+
constructor(string memory name, string memory version)
|
|
12
|
+
EIP712(name, version)
|
|
13
|
+
{}
|
|
14
|
+
|
|
15
|
+
mapping(address => mapping(bytes32 => bool)) private _authorizeState;
|
|
16
|
+
|
|
17
|
+
bytes32 public constant RECEIVE_TYPEHASH =
|
|
18
|
+
keccak256("ReceiveWithAuthorize(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
19
|
+
|
|
20
|
+
bytes32 public constant TRANSFER_TYPEHASH =
|
|
21
|
+
keccak256("TransferWithAuthorize(address from,address to,uint256 value,uint256 validAfter,uint256 validBefore,bytes32 nonce)");
|
|
22
|
+
|
|
23
|
+
function authorizeState(address authorizer, bytes32 nonce)
|
|
24
|
+
public
|
|
25
|
+
view
|
|
26
|
+
override
|
|
27
|
+
returns (bool)
|
|
28
|
+
{
|
|
29
|
+
return _authorizeState[authorizer][nonce];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function _useAuthorize(address authorizer, bytes32 nonce) internal {
|
|
33
|
+
require(!_authorizeState[authorizer][nonce], "TransferAuthorize: authorization already used");
|
|
34
|
+
_authorizeState[authorizer][nonce] = true;
|
|
35
|
+
emit AuthorizeUsed(authorizer, nonce);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function _verify(
|
|
39
|
+
bytes32 typehash,
|
|
40
|
+
address from,
|
|
41
|
+
address to,
|
|
42
|
+
uint256 value,
|
|
43
|
+
uint256 validAfter,
|
|
44
|
+
uint256 validBefore,
|
|
45
|
+
bytes32 nonce,
|
|
46
|
+
uint8 v,
|
|
47
|
+
bytes32 r,
|
|
48
|
+
bytes32 s
|
|
49
|
+
) internal view returns (address signer) {
|
|
50
|
+
require(block.timestamp >= validAfter, "TransferAuthorize: not yet valid");
|
|
51
|
+
require(block.timestamp <= validBefore, "TransferAuthorize: expired");
|
|
52
|
+
|
|
53
|
+
bytes32 structHash = keccak256(
|
|
54
|
+
abi.encode(
|
|
55
|
+
typehash,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce
|
|
62
|
+
)
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
signer = _hashTypedDataV4(structHash).recover(v, r, s);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import ".././adapter/TransferAuth.sol";
|
|
6
|
+
|
|
7
|
+
abstract contract ERC20TransferAuth is ERC20, TransferAuth {
|
|
8
|
+
constructor(string memory name, string memory version)
|
|
9
|
+
TransferAuth(name, version)
|
|
10
|
+
{}
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorization(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external override {
|
|
23
|
+
require(msg.sender == to, "ERC20TransferAuth: caller != payee");
|
|
24
|
+
|
|
25
|
+
address signer = _verify(
|
|
26
|
+
RECEIVE_WITH_AUTHORIZATION_TYPEHASH,
|
|
27
|
+
from,
|
|
28
|
+
to,
|
|
29
|
+
value,
|
|
30
|
+
validAfter,
|
|
31
|
+
validBefore,
|
|
32
|
+
nonce,
|
|
33
|
+
v,
|
|
34
|
+
r,
|
|
35
|
+
s
|
|
36
|
+
);
|
|
37
|
+
require(signer == from, "ERC20TransferAuth: invalid signature");
|
|
38
|
+
|
|
39
|
+
_useAuthorization(from, nonce);
|
|
40
|
+
_transfer(from, to, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function transferWithAuthorization(
|
|
44
|
+
address from,
|
|
45
|
+
address to,
|
|
46
|
+
uint256 value,
|
|
47
|
+
uint256 validAfter,
|
|
48
|
+
uint256 validBefore,
|
|
49
|
+
bytes32 nonce,
|
|
50
|
+
uint8 v,
|
|
51
|
+
bytes32 r,
|
|
52
|
+
bytes32 s
|
|
53
|
+
) external override {
|
|
54
|
+
address signer = _verify(
|
|
55
|
+
TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce,
|
|
62
|
+
v,
|
|
63
|
+
r,
|
|
64
|
+
s
|
|
65
|
+
);
|
|
66
|
+
require(signer == from, "ERC20TransferAuth: invalid signature");
|
|
67
|
+
|
|
68
|
+
_useAuthorization(from, nonce);
|
|
69
|
+
_transfer(from, to, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import ".././adapter/TransferAuthorize.sol";
|
|
6
|
+
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
|
7
|
+
|
|
8
|
+
/// @title TransferWithAuthorize
|
|
9
|
+
/// @notice ERC20 extension that supports EIP-712 based `transferWithAuthorize` and `receiveWithAuthorize` flows
|
|
10
|
+
/// @dev `receiveWithAuthorize` restricts the caller to the `to` address (recipient submits the proof). `transferWithAuthorize` is open to relayers.
|
|
11
|
+
abstract contract TransferWithAuthorize is ERC20, TransferAuthorize, ReentrancyGuard {
|
|
12
|
+
/// @param name EIP-712 domain name
|
|
13
|
+
/// @param version EIP-712 domain version
|
|
14
|
+
constructor(string memory name, string memory version)
|
|
15
|
+
TransferAuthorize(name, version)
|
|
16
|
+
{}
|
|
17
|
+
|
|
18
|
+
/// @notice Recipient-triggered transfer using an off-chain signature by `from`.
|
|
19
|
+
/// @dev The caller must be the recipient `to` to match the semantics of "receive with authorization".
|
|
20
|
+
function receiveWithAuthorize(
|
|
21
|
+
address from,
|
|
22
|
+
address to,
|
|
23
|
+
uint256 value,
|
|
24
|
+
uint256 validAfter,
|
|
25
|
+
uint256 validBefore,
|
|
26
|
+
bytes32 nonce,
|
|
27
|
+
uint8 v,
|
|
28
|
+
bytes32 r,
|
|
29
|
+
bytes32 s
|
|
30
|
+
) external override nonReentrant {
|
|
31
|
+
// Only the recipient should be able to call this helper
|
|
32
|
+
require(msg.sender == to, "ERC20TransferAuthorize: caller must sender");
|
|
33
|
+
|
|
34
|
+
// Recover signer and validate
|
|
35
|
+
address signer = _verify(
|
|
36
|
+
RECEIVE_TYPEHASH,
|
|
37
|
+
from,
|
|
38
|
+
to,
|
|
39
|
+
value,
|
|
40
|
+
validAfter,
|
|
41
|
+
validBefore,
|
|
42
|
+
nonce,
|
|
43
|
+
v,
|
|
44
|
+
r,
|
|
45
|
+
s
|
|
46
|
+
);
|
|
47
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
48
|
+
|
|
49
|
+
// Mark nonce as used
|
|
50
|
+
_useAuthorize(from, nonce);
|
|
51
|
+
// Execute the token transfer
|
|
52
|
+
_transfer(from, to, value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// @notice Relayer-triggered transfer using an off-chain signature by `from`.
|
|
56
|
+
/// @dev This allows anyone (a relayer) to submit the signed authorization on-chain.
|
|
57
|
+
function transferWithAuthorize(
|
|
58
|
+
address from,
|
|
59
|
+
address to,
|
|
60
|
+
uint256 value,
|
|
61
|
+
uint256 validAfter,
|
|
62
|
+
uint256 validBefore,
|
|
63
|
+
bytes32 nonce,
|
|
64
|
+
uint8 v,
|
|
65
|
+
bytes32 r,
|
|
66
|
+
bytes32 s
|
|
67
|
+
) external override nonReentrant {
|
|
68
|
+
// Recover signer and validate
|
|
69
|
+
address signer = _verify(
|
|
70
|
+
TRANSFER_TYPEHASH,
|
|
71
|
+
from,
|
|
72
|
+
to,
|
|
73
|
+
value,
|
|
74
|
+
validAfter,
|
|
75
|
+
validBefore,
|
|
76
|
+
nonce,
|
|
77
|
+
v,
|
|
78
|
+
r,
|
|
79
|
+
s
|
|
80
|
+
);
|
|
81
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
82
|
+
|
|
83
|
+
// Mark nonce as used
|
|
84
|
+
_useAuthorize(from, nonce);
|
|
85
|
+
// Execute the token transfer
|
|
86
|
+
_transfer(from, to, value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import "../../adapter/TransferAuthorize.sol";
|
|
6
|
+
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
|
7
|
+
|
|
8
|
+
/// @title ERC20TransferWithAuthorize
|
|
9
|
+
/// @notice ERC20 extension that supports EIP-712 based `transferWithAuthorize` and `receiveWithAuthorize` flows
|
|
10
|
+
/// @dev `receiveWithAuthorize` restricts the caller to the `to` address (recipient submits the proof). `transferWithAuthorize` is open to relayers.
|
|
11
|
+
abstract contract ERC20TransferWithAuthorize is ERC20, TransferAuthorize, ReentrancyGuard {
|
|
12
|
+
/// @param name EIP-712 domain name
|
|
13
|
+
/// @param version EIP-712 domain version
|
|
14
|
+
constructor(string memory name, string memory version)
|
|
15
|
+
TransferAuthorize(name, version)
|
|
16
|
+
{}
|
|
17
|
+
|
|
18
|
+
/// @notice Recipient-triggered transfer using an off-chain signature by `from`.
|
|
19
|
+
/// @dev The caller must be the recipient `to` to match the semantics of "receive with authorization".
|
|
20
|
+
function receiveWithAuthorize(
|
|
21
|
+
address from,
|
|
22
|
+
address to,
|
|
23
|
+
uint256 value,
|
|
24
|
+
uint256 validAfter,
|
|
25
|
+
uint256 validBefore,
|
|
26
|
+
bytes32 nonce,
|
|
27
|
+
uint8 v,
|
|
28
|
+
bytes32 r,
|
|
29
|
+
bytes32 s
|
|
30
|
+
) external nonReentrant {
|
|
31
|
+
// Only the recipient should be able to call this helper
|
|
32
|
+
require(msg.sender == to, "ERC20TransferAuthorize: caller must sender");
|
|
33
|
+
|
|
34
|
+
// Recover signer and validate
|
|
35
|
+
address signer = _verify(
|
|
36
|
+
RECEIVE_TYPEHASH,
|
|
37
|
+
from,
|
|
38
|
+
to,
|
|
39
|
+
value,
|
|
40
|
+
validAfter,
|
|
41
|
+
validBefore,
|
|
42
|
+
nonce,
|
|
43
|
+
v,
|
|
44
|
+
r,
|
|
45
|
+
s
|
|
46
|
+
);
|
|
47
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
48
|
+
|
|
49
|
+
// Mark nonce as used
|
|
50
|
+
_useAuthorize(from, nonce);
|
|
51
|
+
// Execute the token transfer
|
|
52
|
+
_transfer(from, to, value);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// @notice Relayer-triggered transfer using an off-chain signature by `from`.
|
|
56
|
+
/// @dev This allows anyone (a relayer) to submit the signed authorization on-chain.
|
|
57
|
+
function transferWithAuthorize(
|
|
58
|
+
address from,
|
|
59
|
+
address to,
|
|
60
|
+
uint256 value,
|
|
61
|
+
uint256 validAfter,
|
|
62
|
+
uint256 validBefore,
|
|
63
|
+
bytes32 nonce,
|
|
64
|
+
uint8 v,
|
|
65
|
+
bytes32 r,
|
|
66
|
+
bytes32 s
|
|
67
|
+
) external nonReentrant {
|
|
68
|
+
// Recover signer and validate
|
|
69
|
+
address signer = _verify(
|
|
70
|
+
TRANSFER_TYPEHASH,
|
|
71
|
+
from,
|
|
72
|
+
to,
|
|
73
|
+
value,
|
|
74
|
+
validAfter,
|
|
75
|
+
validBefore,
|
|
76
|
+
nonce,
|
|
77
|
+
v,
|
|
78
|
+
r,
|
|
79
|
+
s
|
|
80
|
+
);
|
|
81
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
82
|
+
|
|
83
|
+
// Mark nonce as used
|
|
84
|
+
_useAuthorize(from, nonce);
|
|
85
|
+
// Execute the token transfer
|
|
86
|
+
_transfer(from, to, value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// @notice Relayer-triggered transfer using an off-chain signature by `from`.
|
|
90
|
+
/// @dev This allows anyone (a relayer) to submit the signed authorization on-chain.
|
|
91
|
+
function approveWithAuthorize(
|
|
92
|
+
address from,
|
|
93
|
+
address to,
|
|
94
|
+
uint256 value,
|
|
95
|
+
uint256 validAfter,
|
|
96
|
+
uint256 validBefore,
|
|
97
|
+
bytes32 nonce,
|
|
98
|
+
uint8 v,
|
|
99
|
+
bytes32 r,
|
|
100
|
+
bytes32 s
|
|
101
|
+
) external nonReentrant {
|
|
102
|
+
// Recover signer and validate
|
|
103
|
+
address signer = _verify(
|
|
104
|
+
APPROVE_TYPEHASH,
|
|
105
|
+
from,
|
|
106
|
+
to,
|
|
107
|
+
value,
|
|
108
|
+
validAfter,
|
|
109
|
+
validBefore,
|
|
110
|
+
nonce,
|
|
111
|
+
v,
|
|
112
|
+
r,
|
|
113
|
+
s
|
|
114
|
+
);
|
|
115
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
116
|
+
|
|
117
|
+
// Mark nonce as used
|
|
118
|
+
_useAuthorize(from, nonce);
|
|
119
|
+
// Execute the token approval
|
|
120
|
+
_approve(from, to, value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import { IERC20, ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import { ERC20Wrapper } from "@openzeppelin/contracts/token/ERC20/extensions/ERC20Wrapper.sol";
|
|
6
|
+
import { ERC20TransferWithAuthorize } from "./ERC20TransferWithAuthorize.sol";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @title ERC20WrappedWithAuthorize
|
|
10
|
+
* @notice ERC20 wrapper that allows wrapping any existing ERC20 token
|
|
11
|
+
* and adds EIP-712 off-chain authorization functions.
|
|
12
|
+
* @dev Inherits ERC20, ERC20Wrapper, and ERC20TransferWithAuthorize:
|
|
13
|
+
* - ERC20: standard token functionality
|
|
14
|
+
* - ERC20Wrapper: depositFor/withdrawTo underlying tokens
|
|
15
|
+
* - ERC20TransferWithAuthorize: transferWithAuthorize and receiveWithAuthorize
|
|
16
|
+
*/
|
|
17
|
+
abstract contract ERC20WrappedWithAuthorize is ERC20, ERC20Wrapper, ERC20TransferWithAuthorize {
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @notice Construct a wrapped ERC20 with authorization support
|
|
21
|
+
* @param _underlyingToken Address of the ERC20 token to wrap. Users deposit this token to receive the wrapped token.
|
|
22
|
+
* @param _name Name of the wrapped token (ERC20 metadata and EIP-712 domain name)
|
|
23
|
+
* @param _symbol Symbol of the wrapped token (ERC20 metadata)
|
|
24
|
+
* @param _version Version string for EIP-712 domain (e.g. "1")
|
|
25
|
+
*/
|
|
26
|
+
constructor(
|
|
27
|
+
address _underlyingToken,
|
|
28
|
+
string memory _name,
|
|
29
|
+
string memory _symbol,
|
|
30
|
+
string memory _version
|
|
31
|
+
)
|
|
32
|
+
ERC20(_name, _symbol)
|
|
33
|
+
ERC20Wrapper(IERC20(_underlyingToken))
|
|
34
|
+
ERC20TransferWithAuthorize(_name, _version)
|
|
35
|
+
{}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @notice Returns the token decimals
|
|
39
|
+
* @dev Overrides both ERC20 and ERC20Wrapper decimals function
|
|
40
|
+
* @return uint8 decimals of the token (usually matches underlying token)
|
|
41
|
+
*/
|
|
42
|
+
function decimals()
|
|
43
|
+
public
|
|
44
|
+
view
|
|
45
|
+
virtual
|
|
46
|
+
override(ERC20, ERC20Wrapper)
|
|
47
|
+
returns (uint8)
|
|
48
|
+
{
|
|
49
|
+
return super.decimals();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import ".././adapter/TransferAuth.sol";
|
|
6
|
+
|
|
7
|
+
abstract contract ERC20TransferAuth is ERC20, TransferAuth {
|
|
8
|
+
constructor(string memory name, string memory version)
|
|
9
|
+
TransferAuth(name, version)
|
|
10
|
+
{}
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorization(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external override {
|
|
23
|
+
require(msg.sender == to, "ERC20TransferAuth: caller != payee");
|
|
24
|
+
|
|
25
|
+
address signer = _verify(
|
|
26
|
+
RECEIVE_WITH_AUTHORIZATION_TYPEHASH,
|
|
27
|
+
from,
|
|
28
|
+
to,
|
|
29
|
+
value,
|
|
30
|
+
validAfter,
|
|
31
|
+
validBefore,
|
|
32
|
+
nonce,
|
|
33
|
+
v,
|
|
34
|
+
r,
|
|
35
|
+
s
|
|
36
|
+
);
|
|
37
|
+
require(signer == from, "ERC20TransferAuth: invalid signature");
|
|
38
|
+
|
|
39
|
+
_useAuthorization(from, nonce);
|
|
40
|
+
_transfer(from, to, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function transferWithAuthorization(
|
|
44
|
+
address from,
|
|
45
|
+
address to,
|
|
46
|
+
uint256 value,
|
|
47
|
+
uint256 validAfter,
|
|
48
|
+
uint256 validBefore,
|
|
49
|
+
bytes32 nonce,
|
|
50
|
+
uint8 v,
|
|
51
|
+
bytes32 r,
|
|
52
|
+
bytes32 s
|
|
53
|
+
) external override {
|
|
54
|
+
address signer = _verify(
|
|
55
|
+
TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce,
|
|
62
|
+
v,
|
|
63
|
+
r,
|
|
64
|
+
s
|
|
65
|
+
);
|
|
66
|
+
require(signer == from, "ERC20TransferAuth: invalid signature");
|
|
67
|
+
|
|
68
|
+
_useAuthorization(from, nonce);
|
|
69
|
+
_transfer(from, to, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.0;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import "../../adapter/TransferAuthorize.sol";
|
|
6
|
+
|
|
7
|
+
abstract contract ERC20TransferWithAuthorize is ERC20, TransferAuthorize {
|
|
8
|
+
constructor(string memory name, string memory version)
|
|
9
|
+
TransferAuthorize(name, version)
|
|
10
|
+
{}
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorize(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external override {
|
|
23
|
+
require(msg.sender == to, "ERC20TransferAuthorize: caller must sender");
|
|
24
|
+
|
|
25
|
+
address signer = _verify(
|
|
26
|
+
RECEIVE_TYPEHASH,
|
|
27
|
+
from,
|
|
28
|
+
to,
|
|
29
|
+
value,
|
|
30
|
+
validAfter,
|
|
31
|
+
validBefore,
|
|
32
|
+
nonce,
|
|
33
|
+
v,
|
|
34
|
+
r,
|
|
35
|
+
s
|
|
36
|
+
);
|
|
37
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
38
|
+
|
|
39
|
+
_useAuthorize(from, nonce);
|
|
40
|
+
_transfer(from, to, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function transferWithAuthorize(
|
|
44
|
+
address from,
|
|
45
|
+
address to,
|
|
46
|
+
uint256 value,
|
|
47
|
+
uint256 validAfter,
|
|
48
|
+
uint256 validBefore,
|
|
49
|
+
bytes32 nonce,
|
|
50
|
+
uint8 v,
|
|
51
|
+
bytes32 r,
|
|
52
|
+
bytes32 s
|
|
53
|
+
) external override {
|
|
54
|
+
address signer = _verify(
|
|
55
|
+
TRANSFER_TYPEHASH,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce,
|
|
62
|
+
v,
|
|
63
|
+
r,
|
|
64
|
+
s
|
|
65
|
+
);
|
|
66
|
+
require(signer == from, "ERC20TransferAuthorize: invalid signature");
|
|
67
|
+
|
|
68
|
+
_useAuthorize(from, nonce);
|
|
69
|
+
_transfer(from, to, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import "../../../ERC3009/ERC3009.sol";
|
|
6
|
+
|
|
7
|
+
abstract contract ERC20WithAuthorization is ERC20, ERC3009 {
|
|
8
|
+
constructor(string memory name, string memory version)
|
|
9
|
+
ERC3009(name, version)
|
|
10
|
+
{}
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorization(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external override {
|
|
23
|
+
require(msg.sender == to, "ERC20WithAuthorization: caller != payee");
|
|
24
|
+
|
|
25
|
+
address signer = _verify(
|
|
26
|
+
RECEIVE_WITH_AUTHORIZATION_TYPEHASH,
|
|
27
|
+
from,
|
|
28
|
+
to,
|
|
29
|
+
value,
|
|
30
|
+
validAfter,
|
|
31
|
+
validBefore,
|
|
32
|
+
nonce,
|
|
33
|
+
v,
|
|
34
|
+
r,
|
|
35
|
+
s
|
|
36
|
+
);
|
|
37
|
+
require(signer == from, "ERC20WithAuthorization: invalid signature");
|
|
38
|
+
|
|
39
|
+
_useAuthorization(from, nonce);
|
|
40
|
+
_transfer(from, to, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function transferWithAuthorization(
|
|
44
|
+
address from,
|
|
45
|
+
address to,
|
|
46
|
+
uint256 value,
|
|
47
|
+
uint256 validAfter,
|
|
48
|
+
uint256 validBefore,
|
|
49
|
+
bytes32 nonce,
|
|
50
|
+
uint8 v,
|
|
51
|
+
bytes32 r,
|
|
52
|
+
bytes32 s
|
|
53
|
+
) external override {
|
|
54
|
+
address signer = _verify(
|
|
55
|
+
TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce,
|
|
62
|
+
v,
|
|
63
|
+
r,
|
|
64
|
+
s
|
|
65
|
+
);
|
|
66
|
+
require(signer == from, "ERC20WithAuthorization: invalid signature");
|
|
67
|
+
|
|
68
|
+
_useAuthorization(from, nonce);
|
|
69
|
+
_transfer(from, to, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.19;
|
|
3
|
+
|
|
4
|
+
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|
5
|
+
import "../../../ERC3009/ERC3009.sol";
|
|
6
|
+
|
|
7
|
+
abstract contract SendWithAuthorization is ERC20, ERC3009 {
|
|
8
|
+
constructor(string memory name, string memory version)
|
|
9
|
+
ERC3009(name, version)
|
|
10
|
+
{}
|
|
11
|
+
|
|
12
|
+
function receiveWithAuthorization(
|
|
13
|
+
address from,
|
|
14
|
+
address to,
|
|
15
|
+
uint256 value,
|
|
16
|
+
uint256 validAfter,
|
|
17
|
+
uint256 validBefore,
|
|
18
|
+
bytes32 nonce,
|
|
19
|
+
uint8 v,
|
|
20
|
+
bytes32 r,
|
|
21
|
+
bytes32 s
|
|
22
|
+
) external override {
|
|
23
|
+
require(msg.sender == to, "ERC20WithAuthorization: caller != payee");
|
|
24
|
+
|
|
25
|
+
address signer = _verify(
|
|
26
|
+
RECEIVE_WITH_AUTHORIZATION_TYPEHASH,
|
|
27
|
+
from,
|
|
28
|
+
to,
|
|
29
|
+
value,
|
|
30
|
+
validAfter,
|
|
31
|
+
validBefore,
|
|
32
|
+
nonce,
|
|
33
|
+
v,
|
|
34
|
+
r,
|
|
35
|
+
s
|
|
36
|
+
);
|
|
37
|
+
require(signer == from, "ERC20WithAuthorization: invalid signature");
|
|
38
|
+
|
|
39
|
+
_useAuthorization(from, nonce);
|
|
40
|
+
_transfer(from, to, value);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function transferWithAuthorization(
|
|
44
|
+
address from,
|
|
45
|
+
address to,
|
|
46
|
+
uint256 value,
|
|
47
|
+
uint256 validAfter,
|
|
48
|
+
uint256 validBefore,
|
|
49
|
+
bytes32 nonce,
|
|
50
|
+
uint8 v,
|
|
51
|
+
bytes32 r,
|
|
52
|
+
bytes32 s
|
|
53
|
+
) external override {
|
|
54
|
+
address signer = _verify(
|
|
55
|
+
TRANSFER_WITH_AUTHORIZATION_TYPEHASH,
|
|
56
|
+
from,
|
|
57
|
+
to,
|
|
58
|
+
value,
|
|
59
|
+
validAfter,
|
|
60
|
+
validBefore,
|
|
61
|
+
nonce,
|
|
62
|
+
v,
|
|
63
|
+
r,
|
|
64
|
+
s
|
|
65
|
+
);
|
|
66
|
+
require(signer == from, "ERC20WithAuthorization: invalid signature");
|
|
67
|
+
|
|
68
|
+
_useAuthorization(from, nonce);
|
|
69
|
+
_transfer(from, to, value);
|
|
70
|
+
}
|
|
71
|
+
}
|
package/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
console.log("Hello via Bun!");
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "test-isol-01",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"module": "index.ts",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"devDependencies": {
|
|
7
|
+
"@types/bun": "latest"
|
|
8
|
+
},
|
|
9
|
+
"peerDependencies": {
|
|
10
|
+
"typescript": "^5"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@openzeppelin/contracts": "^5.4.0"
|
|
14
|
+
}
|
|
15
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
// Environment setup & latest features
|
|
4
|
+
"lib": ["ESNext"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"module": "Preserve",
|
|
7
|
+
"moduleDetection": "force",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"allowJs": true,
|
|
10
|
+
|
|
11
|
+
// Bundler mode
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"verbatimModuleSyntax": true,
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
// Best practices
|
|
18
|
+
"strict": true,
|
|
19
|
+
"skipLibCheck": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
"noUncheckedIndexedAccess": true,
|
|
22
|
+
"noImplicitOverride": true,
|
|
23
|
+
|
|
24
|
+
// Some stricter flags (disabled by default)
|
|
25
|
+
"noUnusedLocals": false,
|
|
26
|
+
"noUnusedParameters": false,
|
|
27
|
+
"noPropertyAccessFromIndexSignature": false
|
|
28
|
+
}
|
|
29
|
+
}
|