@rootzero/contracts 0.6.0 → 0.6.2
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/blocks/Cursors.sol +73 -0
- package/blocks/Keys.sol +10 -0
- package/blocks/Schema.sol +13 -0
- package/commands/Base.sol +14 -7
- package/package.json +1 -1
- package/utils/Assets.sol +25 -0
package/blocks/Cursors.sol
CHANGED
|
@@ -260,6 +260,29 @@ library Cursors {
|
|
|
260
260
|
return create64(Keys.Bounty, bytes32(bounty), relayer);
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
+
/// @notice Encode a MINIMUMS block.
|
|
264
|
+
/// @param a First minimum amount.
|
|
265
|
+
/// @param b Second minimum amount.
|
|
266
|
+
/// @return Encoded MINIMUMS block bytes.
|
|
267
|
+
function toMinimumsBlock(uint a, uint b) internal pure returns (bytes memory) {
|
|
268
|
+
return create64(Keys.Minimums, bytes32(a), bytes32(b));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/// @notice Encode a MAXIMUMS block.
|
|
272
|
+
/// @param a First maximum amount.
|
|
273
|
+
/// @param b Second maximum amount.
|
|
274
|
+
/// @return Encoded MAXIMUMS block bytes.
|
|
275
|
+
function toMaximumsBlock(uint a, uint b) internal pure returns (bytes memory) {
|
|
276
|
+
return create64(Keys.Maximums, bytes32(a), bytes32(b));
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/// @notice Encode a FEE block.
|
|
280
|
+
/// @param amount Fee amount.
|
|
281
|
+
/// @return Encoded FEE block bytes.
|
|
282
|
+
function toFeeBlock(uint amount) internal pure returns (bytes memory) {
|
|
283
|
+
return create32(Keys.Fee, bytes32(amount));
|
|
284
|
+
}
|
|
285
|
+
|
|
263
286
|
/// @notice Encode a BALANCE block.
|
|
264
287
|
/// @param asset Asset identifier.
|
|
265
288
|
/// @param meta Asset metadata slot.
|
|
@@ -401,6 +424,26 @@ library Cursors {
|
|
|
401
424
|
value.amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
402
425
|
}
|
|
403
426
|
|
|
427
|
+
/// @notice Consume a MINIMUMS block and return the two minimum amounts.
|
|
428
|
+
/// @param cur Cursor; advanced past the block.
|
|
429
|
+
/// @return a First minimum amount.
|
|
430
|
+
/// @return b Second minimum amount.
|
|
431
|
+
function unpackMinimums(Cur memory cur) internal pure returns (uint a, uint b) {
|
|
432
|
+
uint abs = consume(cur, Keys.Minimums, 64, 64);
|
|
433
|
+
a = uint(bytes32(msg.data[abs:abs + 32]));
|
|
434
|
+
b = uint(bytes32(msg.data[abs + 32:abs + 64]));
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/// @notice Consume a MAXIMUMS block and return the two maximum amounts.
|
|
438
|
+
/// @param cur Cursor; advanced past the block.
|
|
439
|
+
/// @return a First maximum amount.
|
|
440
|
+
/// @return b Second maximum amount.
|
|
441
|
+
function unpackMaximums(Cur memory cur) internal pure returns (uint a, uint b) {
|
|
442
|
+
uint abs = consume(cur, Keys.Maximums, 64, 64);
|
|
443
|
+
a = uint(bytes32(msg.data[abs:abs + 32]));
|
|
444
|
+
b = uint(bytes32(msg.data[abs + 32:abs + 64]));
|
|
445
|
+
}
|
|
446
|
+
|
|
404
447
|
/// @notice Consume a MAXIMUM block and return its fields as separate values.
|
|
405
448
|
/// @param cur Cursor; advanced past the block.
|
|
406
449
|
/// @return asset Asset identifier.
|
|
@@ -468,6 +511,26 @@ library Cursors {
|
|
|
468
511
|
amount = uint(bytes32(msg.data[abs:abs + 32]));
|
|
469
512
|
}
|
|
470
513
|
|
|
514
|
+
/// @notice Consume a FEE block and return the amount.
|
|
515
|
+
/// @param cur Cursor; advanced past the block.
|
|
516
|
+
/// @return amount Fee amount.
|
|
517
|
+
function unpackFee(Cur memory cur) internal pure returns (uint amount) {
|
|
518
|
+
uint abs = consume(cur, Keys.Fee, 32, 32);
|
|
519
|
+
amount = uint(bytes32(msg.data[abs:abs + 32]));
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/// @notice Consume a BOUNDS block and return the signed min and max values.
|
|
523
|
+
/// @param cur Cursor; advanced past the block.
|
|
524
|
+
/// @return min Lower signed bound.
|
|
525
|
+
/// @return max Upper signed bound.
|
|
526
|
+
function unpackBounds(Cur memory cur) internal pure returns (int min, int max) {
|
|
527
|
+
uint abs = consume(cur, Keys.Bounds, 64, 64);
|
|
528
|
+
assembly ("memory-safe") {
|
|
529
|
+
min := calldataload(abs)
|
|
530
|
+
max := calldataload(add(abs, 0x20))
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
471
534
|
/// @notice Consume an ASSET block and return the asset descriptor fields.
|
|
472
535
|
/// @param cur Cursor; advanced past the block.
|
|
473
536
|
/// @return asset Asset identifier.
|
|
@@ -538,6 +601,16 @@ library Cursors {
|
|
|
538
601
|
cur.i = next;
|
|
539
602
|
}
|
|
540
603
|
|
|
604
|
+
/// @notice Consume a PATH block and return the raw payload as a calldata slice.
|
|
605
|
+
/// The payload length is variable; the returned slice covers the entire payload.
|
|
606
|
+
/// @param cur Cursor; advanced past the block.
|
|
607
|
+
/// @return data Raw path payload bytes.
|
|
608
|
+
function unpackPath(Cur memory cur) internal pure returns (bytes calldata data) {
|
|
609
|
+
(uint abs, uint next) = expect(cur, cur.i, Keys.Path, 0, 0);
|
|
610
|
+
data = msg.data[abs:cur.offset + next];
|
|
611
|
+
cur.i = next;
|
|
612
|
+
}
|
|
613
|
+
|
|
541
614
|
/// @notice Consume a ROUTE block with a single uint payload.
|
|
542
615
|
/// @param cur Cursor; advanced past the block.
|
|
543
616
|
/// @return value Decoded uint value.
|
package/blocks/Keys.sol
CHANGED
|
@@ -14,14 +14,24 @@ library Keys {
|
|
|
14
14
|
bytes4 constant Custody = bytes4(keccak256("custody(uint host, bytes32 asset, bytes32 meta, uint amount)"));
|
|
15
15
|
/// @dev Minimum acceptable output — (bytes32 asset, bytes32 meta, uint amount)
|
|
16
16
|
bytes4 constant Minimum = bytes4(keccak256("minimum(bytes32 asset, bytes32 meta, uint amount)"));
|
|
17
|
+
/// @dev Pair of minimum amounts — (uint a, uint b)
|
|
18
|
+
bytes4 constant Minimums = bytes4(keccak256("minimums(uint a, uint b)"));
|
|
17
19
|
/// @dev Maximum allowable spend — (bytes32 asset, bytes32 meta, uint amount)
|
|
18
20
|
bytes4 constant Maximum = bytes4(keccak256("maximum(bytes32 asset, bytes32 meta, uint amount)"));
|
|
21
|
+
/// @dev Pair of maximum amounts — (uint a, uint b)
|
|
22
|
+
bytes4 constant Maximums = bytes4(keccak256("maximums(uint a, uint b)"));
|
|
23
|
+
/// @dev Signed min/max bounds — (int min, int max)
|
|
24
|
+
bytes4 constant Bounds = bytes4(keccak256("bounds(int min, int max)"));
|
|
25
|
+
/// @dev Fee amount — (uint amount)
|
|
26
|
+
bytes4 constant Fee = bytes4(keccak256("fee(uint amount)"));
|
|
19
27
|
/// @dev Hard stop / iteration sentinel — ()
|
|
20
28
|
bytes4 constant Break = bytes4(keccak256("break()"));
|
|
21
29
|
/// @dev Bundle wrapper — (bytes data); payload is an embedded block stream
|
|
22
30
|
bytes4 constant Bundle = bytes4(keccak256("bundle(bytes data)"));
|
|
23
31
|
/// @dev Extensible routing field — (bytes data); layout is command-defined
|
|
24
32
|
bytes4 constant Route = bytes4(keccak256("route(bytes data)"));
|
|
33
|
+
/// @dev Opaque path payload — (bytes data); e.g. a Uniswap path encoding
|
|
34
|
+
bytes4 constant Path = bytes4(keccak256("path(bytes data)"));
|
|
25
35
|
/// @dev Plain scalar amount — (uint amount)
|
|
26
36
|
bytes4 constant Quantity = bytes4(keccak256("quantity(uint amount)"));
|
|
27
37
|
/// @dev Ratio or rate value — (uint value)
|
package/blocks/Schema.sol
CHANGED
|
@@ -12,9 +12,14 @@ library Schemas {
|
|
|
12
12
|
string constant Balance = "balance(bytes32 asset, bytes32 meta, uint amount)";
|
|
13
13
|
string constant Custody = "custody(uint host, bytes32 asset, bytes32 meta, uint amount)";
|
|
14
14
|
string constant Minimum = "minimum(bytes32 asset, bytes32 meta, uint amount)";
|
|
15
|
+
string constant Minimums = "minimums(uint a, uint b)";
|
|
15
16
|
string constant Maximum = "maximum(bytes32 asset, bytes32 meta, uint amount)";
|
|
17
|
+
string constant Maximums = "maximums(uint a, uint b)";
|
|
18
|
+
string constant Bounds = "bounds(int min, int max)";
|
|
19
|
+
string constant Fee = "fee(uint amount)";
|
|
16
20
|
string constant Break = "break()";
|
|
17
21
|
string constant Route = "route(bytes data)";
|
|
22
|
+
string constant Path = "path(bytes data)";
|
|
18
23
|
string constant RouteEmpty = "route()";
|
|
19
24
|
string constant Quantity = "quantity(uint amount)";
|
|
20
25
|
string constant Rate = "rate(uint value)";
|
|
@@ -91,6 +96,14 @@ library Sizes {
|
|
|
91
96
|
uint constant Auth = 157;
|
|
92
97
|
/// @dev BALANCE block: 8 header + 32 asset + 32 meta + 32 amount = 104 bytes
|
|
93
98
|
uint constant Balance = 104;
|
|
99
|
+
/// @dev MINIMUMS block: 8 header + 32 a + 32 b = 72 bytes
|
|
100
|
+
uint constant Minimums = 72;
|
|
101
|
+
/// @dev MAXIMUMS block: 8 header + 32 a + 32 b = 72 bytes
|
|
102
|
+
uint constant Maximums = 72;
|
|
103
|
+
/// @dev BOUNDS block: 8 header + 32 min + 32 max = 72 bytes
|
|
104
|
+
uint constant Bounds = 72;
|
|
105
|
+
/// @dev FEE block: 8 header + 32 amount = 40 bytes
|
|
106
|
+
uint constant Fee = 40;
|
|
94
107
|
/// @dev BOUNTY block: 8 header + 32 amount + 32 relayer = 72 bytes
|
|
95
108
|
uint constant Bounty = 72;
|
|
96
109
|
/// @dev CUSTODY block: 8 header + 32 host + 32 asset + 32 meta + 32 amount = 136 bytes
|
package/commands/Base.sol
CHANGED
|
@@ -74,19 +74,26 @@ abstract contract CommandPayable is CommandBase {
|
|
|
74
74
|
/// Override `settleValue` to implement refund or forwarding behavior instead.
|
|
75
75
|
error UnusedValue(uint remaining);
|
|
76
76
|
|
|
77
|
-
/// @notice
|
|
78
|
-
///
|
|
79
|
-
/// `UnusedValue(remaining)`. Override this hook to refund or redirect
|
|
80
|
-
/// unused value for specific payable commands.
|
|
77
|
+
/// @notice Drains the command budget and settles any remaining native value.
|
|
78
|
+
/// @dev Calls the amount-based `settleValue` hook only when some value remains.
|
|
81
79
|
/// @param account Caller's account identifier for the current invocation.
|
|
82
80
|
/// @param budget Mutable native-value budget used during command execution.
|
|
83
81
|
function settleValue(
|
|
84
82
|
bytes32 account,
|
|
85
83
|
Budget memory budget
|
|
86
|
-
) internal
|
|
87
|
-
account;
|
|
84
|
+
) internal {
|
|
88
85
|
uint remaining = Values.drain(budget);
|
|
89
|
-
if (remaining != 0)
|
|
86
|
+
if (remaining != 0) settleValue(account, remaining);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/// @notice Handles leftover native value after a payable command has finished.
|
|
90
|
+
/// @dev Override this hook to refund or redirect unused value for a command.
|
|
91
|
+
/// The default implementation rejects any leftover amount.
|
|
92
|
+
/// @param account Caller's account identifier for the current invocation.
|
|
93
|
+
/// @param remaining Unspent native value left in the budget, in wei.
|
|
94
|
+
function settleValue(bytes32 account, uint remaining) internal virtual {
|
|
95
|
+
account;
|
|
96
|
+
revert UnusedValue(remaining);
|
|
90
97
|
}
|
|
91
98
|
}
|
|
92
99
|
|
package/package.json
CHANGED
package/utils/Assets.sol
CHANGED
|
@@ -62,6 +62,31 @@ library Assets {
|
|
|
62
62
|
return bytes1(asset) == 0x20 ? asset : keccak256(bytes.concat(asset, meta));
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
+
/// @notice Return true when two local ERC-20 assets are already in canonical token-address order.
|
|
66
|
+
/// Useful for pair-style integrations that require a stable token ordering
|
|
67
|
+
/// regardless of the caller's input order.
|
|
68
|
+
/// Reverts if either asset is not a local ERC-20 asset.
|
|
69
|
+
/// @param a First ERC-20 asset identifier.
|
|
70
|
+
/// @param b Second ERC-20 asset identifier.
|
|
71
|
+
/// @return ordered Whether `a`'s token address is lower than `b`'s token address.
|
|
72
|
+
function isSortedErc20(bytes32 a, bytes32 b) internal view returns (bool ordered) {
|
|
73
|
+
return erc20Addr(a) < erc20Addr(b);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/// @notice Extract the token addresses for two local ERC-20 assets and report whether they are already ordered.
|
|
77
|
+
/// The returned addresses preserve the original input order.
|
|
78
|
+
/// Reverts if either asset is not a local ERC-20 asset.
|
|
79
|
+
/// @param a First ERC-20 asset identifier.
|
|
80
|
+
/// @param b Second ERC-20 asset identifier.
|
|
81
|
+
/// @return addrA Token address extracted from `a`.
|
|
82
|
+
/// @return addrB Token address extracted from `b`.
|
|
83
|
+
/// @return ordered Whether `addrA` is lower than `addrB`.
|
|
84
|
+
function erc20Addrs(bytes32 a, bytes32 b) internal view returns (address addrA, address addrB, bool ordered) {
|
|
85
|
+
addrA = erc20Addr(a);
|
|
86
|
+
addrB = erc20Addr(b);
|
|
87
|
+
ordered = addrA < addrB;
|
|
88
|
+
}
|
|
89
|
+
|
|
65
90
|
/// @notice Extract the ERC-20 contract address from an asset ID.
|
|
66
91
|
/// Reverts if `asset` is not a local ERC-20 asset.
|
|
67
92
|
/// @param asset ERC-20 asset identifier.
|