Skip to content

Commit 85c97fe

Browse files
author
Ryan
committed
feat: added StructBuilder library
1 parent b789fcb commit 85c97fe

3 files changed

Lines changed: 1215 additions & 0 deletions

File tree

src/StructBuilder.sol

Lines changed: 331 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,331 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import {IAllowanceTransfer} from "permit2/interfaces/IAllowanceTransfer.sol";
5+
import {ISignatureTransfer} from "permit2/interfaces/ISignatureTransfer.sol";
6+
7+
/// @title StructBuilder
8+
library StructBuilder {
9+
error EmptyArray();
10+
11+
error IndexOutOfBounds();
12+
13+
error InvalidParameter(string);
14+
15+
error LengthMismatch();
16+
17+
error MissingRequiredField(string);
18+
19+
// PermitSingle
20+
21+
function init(address spender, uint256 sigDeadline)
22+
internal
23+
pure
24+
returns (IAllowanceTransfer.PermitSingle memory permit)
25+
{
26+
permit.spender = spender;
27+
permit.sigDeadline = sigDeadline;
28+
}
29+
30+
function set(IAllowanceTransfer.PermitSingle memory permit, IAllowanceTransfer.PermitDetails memory params)
31+
internal
32+
pure
33+
returns (IAllowanceTransfer.PermitSingle memory)
34+
{
35+
permit.details = params;
36+
return permit;
37+
}
38+
39+
function set(
40+
IAllowanceTransfer.PermitSingle memory permit,
41+
address token,
42+
uint256 amount,
43+
uint256 expiration,
44+
uint256 nonce
45+
) internal pure returns (IAllowanceTransfer.PermitSingle memory) {
46+
return set(permit, asPermitDetails(token, amount, expiration, nonce));
47+
}
48+
49+
function validate(IAllowanceTransfer.PermitSingle memory permit)
50+
internal
51+
pure
52+
returns (IAllowanceTransfer.PermitSingle memory)
53+
{
54+
if (permit.spender == address(0)) revert MissingRequiredField("spender");
55+
if (permit.sigDeadline == 0) revert MissingRequiredField("sigDeadline");
56+
if (permit.details.token == address(0)) revert MissingRequiredField("details");
57+
return permit;
58+
}
59+
60+
// PermitBatch
61+
62+
function init(address spender, uint256 sigDeadline, uint256 capacity)
63+
internal
64+
pure
65+
returns (IAllowanceTransfer.PermitBatch memory permit)
66+
{
67+
permit.details = new IAllowanceTransfer.PermitDetails[](capacity);
68+
permit.spender = spender;
69+
permit.sigDeadline = sigDeadline;
70+
}
71+
72+
function set(IAllowanceTransfer.PermitBatch memory permit, IAllowanceTransfer.PermitDetails[] memory params)
73+
internal
74+
pure
75+
returns (IAllowanceTransfer.PermitBatch memory)
76+
{
77+
if (params.length == 0) revert EmptyArray();
78+
permit.details = params;
79+
return permit;
80+
}
81+
82+
function set(
83+
IAllowanceTransfer.PermitBatch memory permit,
84+
address[] memory tokens,
85+
uint256[] memory amounts,
86+
uint256[] memory expirations,
87+
uint256[] memory nonces
88+
) internal pure returns (IAllowanceTransfer.PermitBatch memory) {
89+
return set(permit, asPermitDetails(tokens, amounts, expirations, nonces));
90+
}
91+
92+
function set(
93+
IAllowanceTransfer.PermitBatch memory permit,
94+
uint256 index,
95+
IAllowanceTransfer.PermitDetails memory params
96+
) internal pure returns (IAllowanceTransfer.PermitBatch memory) {
97+
if (index >= permit.details.length) revert IndexOutOfBounds();
98+
permit.details[index] = params;
99+
return permit;
100+
}
101+
102+
function set(
103+
IAllowanceTransfer.PermitBatch memory permit,
104+
uint256 index,
105+
address token,
106+
uint256 amount,
107+
uint256 expiration,
108+
uint256 nonce
109+
) internal pure returns (IAllowanceTransfer.PermitBatch memory) {
110+
return set(permit, index, asPermitDetails(token, amount, expiration, nonce));
111+
}
112+
113+
function add(IAllowanceTransfer.PermitBatch memory permit, IAllowanceTransfer.PermitDetails memory params)
114+
internal
115+
pure
116+
returns (IAllowanceTransfer.PermitBatch memory)
117+
{
118+
IAllowanceTransfer.PermitDetails[] memory details = permit.details;
119+
assembly ("memory-safe") {
120+
mstore(details, add(mload(details), 1))
121+
}
122+
123+
details[details.length - 1] = params;
124+
permit.details = details;
125+
126+
return permit;
127+
}
128+
129+
function add(
130+
IAllowanceTransfer.PermitBatch memory permit,
131+
address token,
132+
uint256 amount,
133+
uint256 expiration,
134+
uint256 nonce
135+
) internal pure returns (IAllowanceTransfer.PermitBatch memory) {
136+
return add(permit, asPermitDetails(token, amount, expiration, nonce));
137+
}
138+
139+
function validate(IAllowanceTransfer.PermitBatch memory permit)
140+
internal
141+
pure
142+
returns (IAllowanceTransfer.PermitBatch memory)
143+
{
144+
if (permit.spender == address(0)) revert MissingRequiredField("spender");
145+
if (permit.sigDeadline == 0) revert MissingRequiredField("sigDeadline");
146+
if (permit.details.length == 0) revert MissingRequiredField("details");
147+
for (uint256 i; i < permit.details.length; ++i) {
148+
if (permit.details[i].token == address(0)) revert MissingRequiredField("details");
149+
}
150+
return permit;
151+
}
152+
153+
// PermitTransferFrom
154+
155+
function init(uint256 nonce, uint256 deadline)
156+
internal
157+
pure
158+
returns (ISignatureTransfer.PermitTransferFrom memory permit)
159+
{
160+
permit.nonce = nonce;
161+
permit.deadline = deadline;
162+
}
163+
164+
function set(ISignatureTransfer.PermitTransferFrom memory permit, ISignatureTransfer.TokenPermissions memory params)
165+
internal
166+
pure
167+
returns (ISignatureTransfer.PermitTransferFrom memory)
168+
{
169+
permit.permitted = params;
170+
return permit;
171+
}
172+
173+
function set(ISignatureTransfer.PermitTransferFrom memory permit, address token, uint256 amount)
174+
internal
175+
pure
176+
returns (ISignatureTransfer.PermitTransferFrom memory)
177+
{
178+
return set(permit, asTokenPermissions(token, amount));
179+
}
180+
181+
function validate(ISignatureTransfer.PermitTransferFrom memory permit)
182+
internal
183+
pure
184+
returns (ISignatureTransfer.PermitTransferFrom memory)
185+
{
186+
if (permit.deadline == 0) revert MissingRequiredField("deadline");
187+
if (permit.permitted.token == address(0)) revert MissingRequiredField("permitted");
188+
return permit;
189+
}
190+
191+
// PermitBatchTransferFrom
192+
193+
function init(uint256 nonce, uint256 deadline, uint256 capacity)
194+
internal
195+
pure
196+
returns (ISignatureTransfer.PermitBatchTransferFrom memory permit)
197+
{
198+
permit.nonce = nonce;
199+
permit.deadline = deadline;
200+
permit.permitted = new ISignatureTransfer.TokenPermissions[](capacity);
201+
}
202+
203+
function set(
204+
ISignatureTransfer.PermitBatchTransferFrom memory permit,
205+
ISignatureTransfer.TokenPermissions[] memory params
206+
) internal pure returns (ISignatureTransfer.PermitBatchTransferFrom memory) {
207+
if (params.length == 0) revert EmptyArray();
208+
permit.permitted = params;
209+
return permit;
210+
}
211+
212+
function set(
213+
ISignatureTransfer.PermitBatchTransferFrom memory permit,
214+
address[] memory tokens,
215+
uint256[] memory amounts
216+
) internal pure returns (ISignatureTransfer.PermitBatchTransferFrom memory) {
217+
return set(permit, asTokenPermissions(tokens, amounts));
218+
}
219+
220+
function set(
221+
ISignatureTransfer.PermitBatchTransferFrom memory permit,
222+
uint256 index,
223+
ISignatureTransfer.TokenPermissions memory params
224+
) internal pure returns (ISignatureTransfer.PermitBatchTransferFrom memory) {
225+
if (index >= permit.permitted.length) revert IndexOutOfBounds();
226+
permit.permitted[index] = params;
227+
return permit;
228+
}
229+
230+
function set(ISignatureTransfer.PermitBatchTransferFrom memory permit, uint256 index, address token, uint256 amount)
231+
internal
232+
pure
233+
returns (ISignatureTransfer.PermitBatchTransferFrom memory)
234+
{
235+
return set(permit, index, asTokenPermissions(token, amount));
236+
}
237+
238+
function add(
239+
ISignatureTransfer.PermitBatchTransferFrom memory permit,
240+
ISignatureTransfer.TokenPermissions memory params
241+
) internal pure returns (ISignatureTransfer.PermitBatchTransferFrom memory) {
242+
ISignatureTransfer.TokenPermissions[] memory permitted = permit.permitted;
243+
assembly ("memory-safe") {
244+
mstore(permitted, add(mload(permitted), 1))
245+
}
246+
247+
permitted[permitted.length - 1] = params;
248+
permit.permitted = permitted;
249+
250+
return permit;
251+
}
252+
253+
function add(ISignatureTransfer.PermitBatchTransferFrom memory permit, address token, uint256 amount)
254+
internal
255+
pure
256+
returns (ISignatureTransfer.PermitBatchTransferFrom memory)
257+
{
258+
return add(permit, asTokenPermissions(token, amount));
259+
}
260+
261+
function validate(ISignatureTransfer.PermitBatchTransferFrom memory permit)
262+
internal
263+
pure
264+
returns (ISignatureTransfer.PermitBatchTransferFrom memory)
265+
{
266+
if (permit.deadline == 0) revert MissingRequiredField("deadline");
267+
if (permit.permitted.length == 0) revert MissingRequiredField("permitted");
268+
for (uint256 i; i < permit.permitted.length; ++i) {
269+
if (permit.permitted[i].token == address(0)) revert MissingRequiredField("permitted");
270+
}
271+
return permit;
272+
}
273+
274+
function asPermitDetails(address token, uint256 amount, uint256 expiration, uint256 nonce)
275+
internal
276+
pure
277+
returns (IAllowanceTransfer.PermitDetails memory)
278+
{
279+
if (token == address(0)) revert InvalidParameter("token");
280+
if (amount > type(uint160).max) revert InvalidParameter("amount");
281+
if (expiration > type(uint48).max) revert InvalidParameter("expiration");
282+
if (nonce > type(uint48).max) revert InvalidParameter("nonce");
283+
284+
return IAllowanceTransfer.PermitDetails({
285+
token: token,
286+
amount: uint160(amount),
287+
expiration: uint48(expiration),
288+
nonce: uint48(nonce)
289+
});
290+
}
291+
292+
function asPermitDetails(
293+
address[] memory tokens,
294+
uint256[] memory amounts,
295+
uint256[] memory expirations,
296+
uint256[] memory nonces
297+
) internal pure returns (IAllowanceTransfer.PermitDetails[] memory details) {
298+
uint256 n = tokens.length;
299+
if (n == 0) revert EmptyArray();
300+
if (n != amounts.length || n != expirations.length || n != nonces.length) revert LengthMismatch();
301+
302+
details = new IAllowanceTransfer.PermitDetails[](n);
303+
for (uint256 i; i < n; ++i) {
304+
details[i] = asPermitDetails(tokens[i], amounts[i], expirations[i], nonces[i]);
305+
}
306+
}
307+
308+
function asTokenPermissions(address token, uint256 amount)
309+
internal
310+
pure
311+
returns (ISignatureTransfer.TokenPermissions memory)
312+
{
313+
if (token == address(0)) revert InvalidParameter("token");
314+
return ISignatureTransfer.TokenPermissions({token: token, amount: amount});
315+
}
316+
317+
function asTokenPermissions(address[] memory tokens, uint256[] memory amounts)
318+
internal
319+
pure
320+
returns (ISignatureTransfer.TokenPermissions[] memory permitted)
321+
{
322+
uint256 n = tokens.length;
323+
if (n == 0) revert EmptyArray();
324+
if (n != amounts.length) revert LengthMismatch();
325+
326+
permitted = new ISignatureTransfer.TokenPermissions[](n);
327+
for (uint256 i; i < n; ++i) {
328+
permitted[i] = asTokenPermissions(tokens[i], amounts[i]);
329+
}
330+
}
331+
}

0 commit comments

Comments
 (0)