t-isol 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 ADDED
@@ -0,0 +1,15 @@
1
+ # 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.
package/bun.lock ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "workspaces": {
4
+ "": {
5
+ "name": "isol",
6
+ "dependencies": {
7
+ "@openzeppelin/contracts": "^5.4.0",
8
+ },
9
+ "devDependencies": {
10
+ "@types/bun": "latest",
11
+ },
12
+ "peerDependencies": {
13
+ "typescript": "^5",
14
+ },
15
+ },
16
+ },
17
+ "packages": {
18
+ "@openzeppelin/contracts": ["@openzeppelin/contracts@5.4.0", "", {}, "sha512-eCYgWnLg6WO+X52I16TZt8uEjbtdkgLC0SUX/xnAksjjrQI4Xfn4iBRoI5j55dmlOhDv1Y7BoR3cU7e3WWhC6A=="],
19
+
20
+ "@types/bun": ["@types/bun@1.3.5", "", { "dependencies": { "bun-types": "1.3.5" } }, "sha512-RnygCqNrd3srIPEWBd5LFeUYG7plCoH2Yw9WaZGyNmdTEei+gWaHqydbaIRkIkcbXwhBT94q78QljxN0Sk838w=="],
21
+
22
+ "@types/node": ["@types/node@25.0.3", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-W609buLVRVmeW693xKfzHeIV6nJGGz98uCPfeXI1ELMLXVeKYZ9m15fAMSaUPBHYLGFsVRcMmSCksQOrZV9BYA=="],
23
+
24
+ "bun-types": ["bun-types@1.3.5", "", { "dependencies": { "@types/node": "*" } }, "sha512-inmAYe2PFLs0SUbFOWSVD24sg1jFlMPxOjOSSCYqUgn4Hsc3rDc7dFvfVYjFPNHtov6kgUeulV4SxbuIV/stPw=="],
25
+
26
+ "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
27
+
28
+ "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="],
29
+ }
30
+ }
@@ -0,0 +1,63 @@
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 Emitted when a transfer with authorization is executed
14
+ event TransferWithAuthorize(address indexed from, address indexed to, uint256 value, uint256 timeMFG, uint256 timeEXP, bytes32 indexed nonce, bytes auth);
15
+
16
+ /// @notice Emitted when a transferFrom with authorization is executed
17
+ event TransferFromWithAuthorize(address indexed from, address indexed to, uint256 value, uint256 timeMFG, uint256 timeEXP, bytes32 indexed nonce);
18
+
19
+ /// @notice Emitted when a burn with authorization is executed
20
+ event BurnWithAuthorize(address indexed from, uint256 value, uint256 timeMFG, uint256 timeEXP, bytes32 indexed nonce);
21
+
22
+ /// @notice Returns whether a nonce has been used for a given authorizer
23
+ /// @param authorizer the account that signed the authorization
24
+ /// @param nonce the nonce to check
25
+ /// @return true if the nonce was already used/consumed, false otherwise
26
+ function authorizeState(
27
+ address authorizer,
28
+ bytes32 nonce
29
+ ) external view returns (bool);
30
+
31
+ /// @notice Execute a "transfer with authorization" - typically any relayer may submit
32
+ function transferWithAuthorize(
33
+ address from,
34
+ address to,
35
+ uint256 value,
36
+ uint256 timeMFG,
37
+ uint256 timeEXP,
38
+ bytes32 nonce,
39
+ bytes calldata auth
40
+ ) external;
41
+
42
+ /// @notice Execute a "transferFrom with authorization" - typically any relayer may submit
43
+ function transferFromWithAuthorize(
44
+ address from,
45
+ address to,
46
+ uint256 value,
47
+ uint256 timeMFG,
48
+ uint256 timeEXP,
49
+ bytes32 nonce,
50
+ bytes calldata auth
51
+ ) external;
52
+
53
+ /// @notice Execute a "burn with authorization" - typically any relayer may submit
54
+ function burnWithAuthorize(
55
+ address from,
56
+ // address to,
57
+ uint256 value,
58
+ uint256 timeMFG,
59
+ uint256 timeEXP,
60
+ bytes32 nonce,
61
+ bytes calldata auth
62
+ ) external;
63
+ }
@@ -0,0 +1,131 @@
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 `_verifyX..` 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 TRANSFER_TYPEHASH =
19
+ keccak256("TransferWithAuthorize(address from, address to, uint256 value, uint256 timeMFG, uint256 timeEXP, bytes32 nonce)");
20
+
21
+ bytes32 public constant TRANSFERFROM_TYPEHASH =
22
+ keccak256("TransferFromWithAuthorize(address from, address to, uint256 value, uint256 timeMFG, uint256 timeEXP, bytes32 nonce)");
23
+
24
+ bytes32 public constant BURN_TYPEHASH =
25
+ keccak256("BurnWithAuthorize(address from, address to, uint256 value, uint256 timeMFG, uint256 timeEXP, 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 (auth) for TransferWithAuthorize and return the recovered signer
54
+ function _verifyTransfer(
55
+ address from,
56
+ address to,
57
+ uint256 value,
58
+ uint256 timeMFG,
59
+ uint256 timeEXP,
60
+ bytes32 nonce,
61
+ bytes calldata auth
62
+ ) internal returns (address signer) {
63
+ require(block.timestamp >= timeMFG, "TransferAuthorize: timestamp");
64
+ require(block.timestamp <= timeEXP, "TransferAuthorize: expired");
65
+ bytes32 structHash = keccak256(
66
+ abi.encode(
67
+ TRANSFER_TYPEHASH,
68
+ from,
69
+ to,
70
+ value,
71
+ timeMFG,
72
+ timeEXP,
73
+ nonce
74
+ )
75
+ );
76
+ signer = ECDSA.recover(_hashTypedDataV4(structHash), auth);
77
+ emit TransferWithAuthorize(from, to, value, timeMFG, timeEXP, nonce, auth);
78
+ }
79
+
80
+ /// @dev Verify an EIP-712 typed signature (auth) for TransferFromWithAuthorize and return the recovered signer
81
+ function _verifyTransferFrom(
82
+ address from,
83
+ address to,
84
+ uint256 value,
85
+ uint256 timeMFG,
86
+ uint256 timeEXP,
87
+ bytes32 nonce,
88
+ bytes calldata auth
89
+ ) internal view returns (address signer) {
90
+ require(block.timestamp >= timeMFG, "TransferAuthorize: not yet time");
91
+ require(block.timestamp <= timeEXP, "TransferAuthorize: expired");
92
+ bytes32 structHash = keccak256(
93
+ abi.encode(
94
+ TRANSFERFROM_TYPEHASH,
95
+ from,
96
+ to,
97
+ value,
98
+ timeMFG,
99
+ timeEXP,
100
+ nonce
101
+ )
102
+ );
103
+ signer = ECDSA.recover(_hashTypedDataV4(structHash), auth);
104
+ }
105
+
106
+ /// @dev Verify an EIP-712 typed signature (auth) for BurnWithAuthorize and return the recovered signer
107
+ function _verifyBurn(
108
+ address from,
109
+ // address to,
110
+ uint256 value,
111
+ uint256 timeMFG,
112
+ uint256 timeEXP,
113
+ bytes32 nonce,
114
+ bytes calldata auth
115
+ ) internal view returns (address signer) {
116
+ require(block.timestamp >= timeMFG, "TransferAuthorize: not yet time");
117
+ require(block.timestamp <= timeEXP, "TransferAuthorize: expired");
118
+ bytes32 structHash = keccak256(
119
+ abi.encode(
120
+ BURN_TYPEHASH,
121
+ from,
122
+ // to,
123
+ value,
124
+ timeMFG,
125
+ timeEXP,
126
+ nonce
127
+ )
128
+ );
129
+ signer = ECDSA.recover(_hashTypedDataV4(structHash), auth);
130
+ }
131
+ }
@@ -0,0 +1,102 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5
+ import "../TransferAuthorize.sol";
6
+ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
7
+ import "@openzeppelin/contracts/access/Ownable.sol";
8
+
9
+ /// @title ERC20xTransferWithAuthorize
10
+ /// @notice ERC20 extension that supports EIP-712 based `transferWithAuthorize` and `receiveWithAuthorize` flows
11
+ /// @dev `receiveWithAuthorize` restricts the caller to the `to` address (recipient submits the proof). `transferWithAuthorize` is open to relayers.
12
+ abstract contract ERC20xTransferWithAuthorize is ERC20, TransferAuthorize, ReentrancyGuard, Ownable {
13
+ constructor(
14
+ string memory name,
15
+ string memory symbol,
16
+ uint256 initialSupply,
17
+ string memory domainName,
18
+ string memory domainVersion
19
+ )
20
+ ERC20(name, symbol)
21
+ TransferAuthorize(domainName, domainVersion)
22
+ Ownable(msg.sender)
23
+ {
24
+ _mint(msg.sender, initialSupply * 10 ** decimals());
25
+ }
26
+
27
+ /// @notice Relayer-triggered transfer using an off-chain signature by `from`.
28
+ /// @dev This allows anyone (a relayer) to submit the signed authorization on-chain.
29
+ function transferWithAuthorize(
30
+ address from,
31
+ address to,
32
+ uint256 value,
33
+ uint256 validAfter,
34
+ uint256 validBefore,
35
+ bytes32 nonce,
36
+ bytes calldata signature
37
+ ) external override nonReentrant {
38
+ address signer = _verifyTransfer(
39
+ from,
40
+ to,
41
+ value,
42
+ validAfter,
43
+ validBefore,
44
+ nonce,
45
+ signature
46
+ );
47
+ require(signer == from, "ERC20TransferAuthorize: invalid signature");
48
+ _useAuthorize(from, nonce);
49
+ _transfer(from, to, value);
50
+ }
51
+
52
+ /// @notice Relayer-triggered transfer using an off-chain signature by `from`.
53
+ /// @dev This allows anyone (a relayer) to submit the signed authorization on-chain.
54
+ function transferFromWithAuthorize(
55
+ address from,
56
+ address to,
57
+ uint256 value,
58
+ uint256 validAfter,
59
+ uint256 validBefore,
60
+ bytes32 nonce,
61
+ bytes calldata signature
62
+ ) external override nonReentrant {
63
+ address signer = _verifyTransferFrom(
64
+ from,
65
+ to,
66
+ value,
67
+ validAfter,
68
+ validBefore,
69
+ nonce,
70
+ signature
71
+ );
72
+ require(signer == from, "ERC20TransferAuthorize: invalid signature");
73
+ _useAuthorize(from, nonce);
74
+ _spendAllowance(from, to, value);
75
+ _transfer(from, to, value);
76
+ }
77
+
78
+ /// @notice Relayer-triggered transfer using an off-chain signature by `from`.
79
+ /// @dev This allows anyone (a relayer) to submit the signed authorization on-chain.
80
+ function burnWithAuthorize(
81
+ address from,
82
+ // address to,
83
+ uint256 value,
84
+ uint256 validAfter,
85
+ uint256 validBefore,
86
+ bytes32 nonce,
87
+ bytes calldata signature
88
+ ) external override nonReentrant {
89
+ address signer = _verifyBurn(
90
+ from,
91
+ // to,
92
+ value,
93
+ validAfter,
94
+ validBefore,
95
+ nonce,
96
+ signature
97
+ );
98
+ require(signer == from, "ERC20TransferAuthorize: invalid signature");
99
+ _useAuthorize(from, nonce);
100
+ _burn(from, value);
101
+ }
102
+ }
package/docs/README.md ADDED
@@ -0,0 +1 @@
1
+ This is a [Vocs](https://vocs.dev) project bootstrapped with the Vocs CLI.