@rootzero/contracts 0.2.0

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.
Files changed (101) hide show
  1. package/LICENSE +648 -0
  2. package/README.md +135 -0
  3. package/contracts/Blocks.sol +9 -0
  4. package/contracts/Commands.sol +41 -0
  5. package/contracts/Core.sol +10 -0
  6. package/contracts/Events.sol +18 -0
  7. package/contracts/Utils.sol +12 -0
  8. package/contracts/blocks/Blocks.sol +818 -0
  9. package/contracts/blocks/Keys.sol +24 -0
  10. package/contracts/blocks/Mem.sol +129 -0
  11. package/contracts/blocks/Schema.sol +105 -0
  12. package/contracts/blocks/Writers.sol +209 -0
  13. package/contracts/combinators/AmountToBalance.sol +25 -0
  14. package/contracts/combinators/AmountToCustody.sol +36 -0
  15. package/contracts/combinators/CustodyToBalance.sol +25 -0
  16. package/contracts/combinators/EachRoute.sol +18 -0
  17. package/contracts/combinators/MapBalance.sol +25 -0
  18. package/contracts/combinators/MapCustody.sol +25 -0
  19. package/contracts/combinators/RouteToBalance.sol +27 -0
  20. package/contracts/commands/Base.sol +40 -0
  21. package/contracts/commands/Borrow.sol +89 -0
  22. package/contracts/commands/Burn.sol +33 -0
  23. package/contracts/commands/Create.sol +32 -0
  24. package/contracts/commands/Credit.sol +36 -0
  25. package/contracts/commands/Debit.sol +46 -0
  26. package/contracts/commands/Deposit.sol +45 -0
  27. package/contracts/commands/Liquidate.sol +101 -0
  28. package/contracts/commands/Liquidity.sol +179 -0
  29. package/contracts/commands/Mint.sol +42 -0
  30. package/contracts/commands/Pipe.sol +55 -0
  31. package/contracts/commands/Provision.sol +73 -0
  32. package/contracts/commands/Reclaim.sol +48 -0
  33. package/contracts/commands/Redeem.sol +101 -0
  34. package/contracts/commands/Remove.sol +32 -0
  35. package/contracts/commands/Repay.sol +101 -0
  36. package/contracts/commands/Settle.sol +32 -0
  37. package/contracts/commands/Stake.sol +121 -0
  38. package/contracts/commands/Supply.sol +33 -0
  39. package/contracts/commands/Swap.sol +88 -0
  40. package/contracts/commands/Transfer.sol +44 -0
  41. package/contracts/commands/Unstake.sol +49 -0
  42. package/contracts/commands/Withdraw.sol +37 -0
  43. package/contracts/commands/admin/Allocate.sol +32 -0
  44. package/contracts/commands/admin/AllowAssets.sol +34 -0
  45. package/contracts/commands/admin/Authorize.sol +30 -0
  46. package/contracts/commands/admin/DenyAssets.sol +34 -0
  47. package/contracts/commands/admin/Destroy.sol +27 -0
  48. package/contracts/commands/admin/Init.sol +26 -0
  49. package/contracts/commands/admin/Relocate.sol +30 -0
  50. package/contracts/commands/admin/Unauthorize.sol +30 -0
  51. package/contracts/core/Access.sol +50 -0
  52. package/contracts/core/Balances.sol +23 -0
  53. package/contracts/core/Host.sol +25 -0
  54. package/contracts/core/Operation.sol +32 -0
  55. package/contracts/core/Validator.sol +31 -0
  56. package/contracts/events/Access.sol +14 -0
  57. package/contracts/events/Asset.sol +14 -0
  58. package/contracts/events/Balance.sol +14 -0
  59. package/contracts/events/Collateral.sol +15 -0
  60. package/contracts/events/Command.sol +14 -0
  61. package/contracts/events/Debt.sol +15 -0
  62. package/contracts/events/Deposit.sol +14 -0
  63. package/contracts/events/Emitter.sol +7 -0
  64. package/contracts/events/Governed.sol +14 -0
  65. package/contracts/events/HostAnnounced.sol +14 -0
  66. package/contracts/events/Listing.sol +14 -0
  67. package/contracts/events/Peer.sol +14 -0
  68. package/contracts/events/Quote.sol +14 -0
  69. package/contracts/events/RootZero.sol +14 -0
  70. package/contracts/events/Withdraw.sol +14 -0
  71. package/contracts/interfaces/IHostDiscovery.sol +6 -0
  72. package/contracts/peer/AllowAssets.sol +30 -0
  73. package/contracts/peer/Base.sol +17 -0
  74. package/contracts/peer/DenyAssets.sol +30 -0
  75. package/contracts/peer/Pull.sol +30 -0
  76. package/contracts/peer/Push.sol +30 -0
  77. package/contracts/test/TestBlockHelper.sol +261 -0
  78. package/contracts/test/TestBorrowHost.sol +47 -0
  79. package/contracts/test/TestBurnHost.sol +28 -0
  80. package/contracts/test/TestCreateHost.sol +26 -0
  81. package/contracts/test/TestDiscovery.sol +6 -0
  82. package/contracts/test/TestECDSA.sol +16 -0
  83. package/contracts/test/TestHost.sol +199 -0
  84. package/contracts/test/TestLiquidityHost.sol +145 -0
  85. package/contracts/test/TestMintHost.sol +40 -0
  86. package/contracts/test/TestPeerHost.sol +34 -0
  87. package/contracts/test/TestReclaimHost.sol +48 -0
  88. package/contracts/test/TestRejectEther.sol +8 -0
  89. package/contracts/test/TestRemoveHost.sol +26 -0
  90. package/contracts/test/TestSwapHost.sol +44 -0
  91. package/contracts/test/TestUtils.sol +169 -0
  92. package/contracts/test/TestValidator.sol +10 -0
  93. package/contracts/utils/Accounts.sol +40 -0
  94. package/contracts/utils/Assets.sol +76 -0
  95. package/contracts/utils/Channels.sol +11 -0
  96. package/contracts/utils/ECDSA.sol +36 -0
  97. package/contracts/utils/Ids.sol +75 -0
  98. package/contracts/utils/Layout.sol +22 -0
  99. package/contracts/utils/Utils.sol +126 -0
  100. package/contracts/utils/Value.sol +20 -0
  101. package/package.json +33 -0
@@ -0,0 +1,24 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ library Keys {
5
+ bytes4 constant Amount = bytes4(keccak256("amount(bytes32 asset, bytes32 meta, uint amount)"));
6
+ bytes4 constant Balance = bytes4(keccak256("balance(bytes32 asset, bytes32 meta, uint amount)"));
7
+ bytes4 constant Custody = bytes4(keccak256("custody(uint host, bytes32 asset, bytes32 meta, uint amount)"));
8
+ bytes4 constant Minimum = bytes4(keccak256("minimum(bytes32 asset, bytes32 meta, uint amount)"));
9
+ bytes4 constant Maximum = bytes4(keccak256("maximum(bytes32 asset, bytes32 meta, uint amount)"));
10
+ bytes4 constant Route = bytes4(keccak256("route(bytes data)"));
11
+ bytes4 constant Quantity = bytes4(keccak256("quantity(uint amount)"));
12
+ bytes4 constant Rate = bytes4(keccak256("rate(uint value)"));
13
+ bytes4 constant Party = bytes4(keccak256("party(bytes32 account)"));
14
+ bytes4 constant Recipient = bytes4(keccak256("recipient(bytes32 account)"));
15
+ bytes4 constant Transaction = bytes4(keccak256("tx(bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount)"));
16
+ bytes4 constant Step = bytes4(keccak256("step(uint target, uint value, bytes request)"));
17
+ bytes4 constant Auth = bytes4(keccak256("auth(uint cid, uint deadline, bytes proof)"));
18
+ bytes4 constant Asset = bytes4(keccak256("asset(bytes32 asset, bytes32 meta)"));
19
+ bytes4 constant Node = bytes4(keccak256("node(uint id)"));
20
+ bytes4 constant Listing = bytes4(keccak256("listing(uint host, bytes32 asset, bytes32 meta)"));
21
+ bytes4 constant Funding = bytes4(keccak256("funding(uint host, uint amount)"));
22
+ bytes4 constant Allocation = bytes4(keccak256("allocation(uint host, bytes32 asset, bytes32 meta, uint amount)"));
23
+ bytes4 constant Bounty = bytes4(keccak256("bounty(uint amount, bytes32 relayer)"));
24
+ }
@@ -0,0 +1,129 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { HostAmount, Tx, Keys } from "./Schema.sol";
5
+ import { Blocks } from "./Blocks.sol";
6
+
7
+ struct MemRef {
8
+ bytes4 key;
9
+ uint i;
10
+ uint bound;
11
+ uint end;
12
+ }
13
+
14
+ library Mem {
15
+ function from(bytes memory source, uint i) internal pure returns (MemRef memory ref) {
16
+ uint eod = source.length;
17
+ if (i == eod) return MemRef(bytes4(0), 0, 0, i);
18
+ if (i > eod) revert Blocks.MalformedBlocks();
19
+
20
+ unchecked {
21
+ ref.i = i + 12;
22
+ }
23
+ if (ref.i > eod) revert Blocks.MalformedBlocks();
24
+
25
+ bytes32 w;
26
+ assembly ("memory-safe") {
27
+ w := mload(add(add(source, 0x20), i))
28
+ }
29
+
30
+ ref.key = bytes4(w);
31
+ ref.bound = ref.i + uint32(bytes4(w << 32));
32
+ ref.end = ref.i + uint32(bytes4(w << 64));
33
+
34
+ if (ref.bound > ref.end || ref.end > eod) revert Blocks.MalformedBlocks();
35
+ }
36
+
37
+ function slice(bytes memory source, uint start, uint end) internal pure returns (bytes memory out) {
38
+ if (end < start || end > source.length) revert Blocks.MalformedBlocks();
39
+ uint len = end - start;
40
+ out = new bytes(len);
41
+ if (len == 0) return out;
42
+
43
+ assembly ("memory-safe") {
44
+ mcopy(add(out, 0x20), add(add(source, 0x20), start), len)
45
+ }
46
+ }
47
+
48
+ function count(bytes memory source, uint i, bytes4 key) internal pure returns (uint count_, uint next) {
49
+ next = i;
50
+ while (next < source.length) {
51
+ MemRef memory ref = from(source, next);
52
+ if (ref.key != key) break;
53
+ unchecked {
54
+ ++count_;
55
+ }
56
+ next = ref.end;
57
+ }
58
+ }
59
+
60
+ function find(bytes memory source, uint i, uint limit, bytes4 key) internal pure returns (MemRef memory ref) {
61
+ if (limit > source.length) revert Blocks.MalformedBlocks();
62
+ while (i < limit) {
63
+ ref = from(source, i);
64
+ if (ref.end > limit) revert Blocks.MalformedBlocks();
65
+ if (ref.key == key) return ref;
66
+ i = ref.end;
67
+ }
68
+
69
+ return MemRef(bytes4(0), limit, limit, limit);
70
+ }
71
+
72
+ function ensure(MemRef memory ref, bytes4 key) internal pure {
73
+ if (key == 0 || key != ref.key) revert Blocks.InvalidBlock();
74
+ }
75
+
76
+ function ensure(MemRef memory ref, bytes4 key, uint len) internal pure {
77
+ if (key == 0 || key != ref.key || len != (ref.bound - ref.i)) revert Blocks.InvalidBlock();
78
+ }
79
+
80
+ function ensure(MemRef memory ref, bytes4 key, uint min, uint max) internal pure {
81
+ uint len = ref.bound - ref.i;
82
+ if (key == 0 || key != ref.key || len < min || (max != 0 && len > max)) revert Blocks.InvalidBlock();
83
+ }
84
+
85
+ function unpackBalance(
86
+ MemRef memory ref,
87
+ bytes memory source
88
+ ) internal pure returns (bytes32 asset, bytes32 meta, uint amount) {
89
+ ensure(ref, Keys.Balance, 96);
90
+ uint i = ref.i;
91
+
92
+ assembly ("memory-safe") {
93
+ let p := add(add(source, 0x20), i)
94
+ asset := mload(p)
95
+ meta := mload(add(p, 0x20))
96
+ amount := mload(add(p, 0x40))
97
+ }
98
+ }
99
+
100
+ function toCustodyValue(
101
+ MemRef memory ref,
102
+ bytes memory source
103
+ ) internal pure returns (HostAmount memory value) {
104
+ ensure(ref, Keys.Custody, 128);
105
+ uint i = ref.i;
106
+
107
+ assembly ("memory-safe") {
108
+ let p := add(add(source, 0x20), i)
109
+ mstore(value, mload(p))
110
+ mstore(add(value, 0x20), mload(add(p, 0x20)))
111
+ mstore(add(value, 0x40), mload(add(p, 0x40)))
112
+ mstore(add(value, 0x60), mload(add(p, 0x60)))
113
+ }
114
+ }
115
+
116
+ function toTxValue(MemRef memory ref, bytes memory source) internal pure returns (Tx memory value) {
117
+ ensure(ref, Keys.Transaction, 160);
118
+ uint i = ref.i;
119
+
120
+ assembly ("memory-safe") {
121
+ let p := add(add(source, 0x20), i)
122
+ mstore(value, mload(p))
123
+ mstore(add(value, 0x20), mload(add(p, 0x20)))
124
+ mstore(add(value, 0x40), mload(add(p, 0x40)))
125
+ mstore(add(value, 0x60), mload(add(p, 0x60)))
126
+ mstore(add(value, 0x80), mload(add(p, 0x80)))
127
+ }
128
+ }
129
+ }
@@ -0,0 +1,105 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { Keys } from "./Keys.sol";
5
+
6
+ library Schemas {
7
+ string constant Amount = "amount(bytes32 asset, bytes32 meta, uint amount)";
8
+ string constant Balance = "balance(bytes32 asset, bytes32 meta, uint amount)";
9
+ string constant Custody = "custody(uint host, bytes32 asset, bytes32 meta, uint amount)";
10
+ string constant Minimum = "minimum(bytes32 asset, bytes32 meta, uint amount)";
11
+ string constant Maximum = "maximum(bytes32 asset, bytes32 meta, uint amount)";
12
+ string constant Route = "route(bytes data)";
13
+ string constant RouteEmpty = "route()";
14
+ string constant Quantity = "quantity(uint amount)";
15
+ string constant Rate = "rate(uint value)";
16
+ string constant Party = "party(bytes32 account)";
17
+ string constant Recipient = "recipient(bytes32 account)";
18
+ string constant Transaction = "tx(bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount)";
19
+ string constant Step = "step(uint target, uint value, bytes request)";
20
+ string constant Auth = "auth(uint cid, uint deadline, bytes proof)";
21
+ string constant Asset = "asset(bytes32 asset, bytes32 meta)";
22
+ string constant Node = "node(uint id)";
23
+ string constant Listing = "listing(uint host, bytes32 asset, bytes32 meta)";
24
+ string constant Funding = "funding(uint host, uint amount)";
25
+ string constant Allocation = "allocation(uint host, bytes32 asset, bytes32 meta, uint amount)";
26
+ string constant Bounty = "bounty(uint amount, bytes32 relayer)";
27
+
28
+ function route1(string memory maybeRoute, string memory a) internal pure returns (string memory) {
29
+ return string.concat(bytes(maybeRoute).length == 0 ? RouteEmpty : maybeRoute, ">", a);
30
+ }
31
+
32
+ function route2(string memory maybeRoute, string memory a, string memory b) internal pure returns (string memory) {
33
+ return string.concat(bytes(maybeRoute).length == 0 ? RouteEmpty : maybeRoute, ">", a, ">", b);
34
+ }
35
+ }
36
+
37
+ // Block stream:
38
+ // - encoding is [bytes4 key][bytes4 selfLen][bytes4 totalLen][self payload][child blocks...]
39
+ // - `selfLen` covers only the block payload
40
+ // - `totalLen` covers payload plus child blocks
41
+ // - payload layout is block-specific
42
+ //
43
+ // Extensible payloads:
44
+ // - self payload may be [head][dynamic tail]
45
+ // - head layout is implied by the block key
46
+ // - one dynamic field may consume the rest of self payload without its own length prefix
47
+ // - child blocks, if any, are encoded as a normal nested block stream
48
+ //
49
+ // Schema DSL:
50
+ // - `;` separates top-level sibling blocks
51
+ // - `>` attaches child blocks to the preceding parent
52
+ // - repeated `>` adds more children to the same parent, not to the previous child
53
+ // - `->` separates request and response shapes, appears at most once, and is omitted when no output is modeled
54
+ // - top-level blocks of the same type should be grouped together
55
+ // - primary / driving blocks should appear before auxiliary blocks
56
+ // - `route(<fields...>)` is a reserved extensible schema form whose key is always `Keys.Route`
57
+ // - canonical blocks are `amount(...)` for request amounts, `balance(...)` for state balances,
58
+ // `minimum(...)` for result floors, `maximum(...)` for spend ceilings, and `quantity(...)`
59
+ // for plain scalar amounts
60
+ // - `auth(uint cid, uint deadline, bytes proof)` is a proof-separator child and must be emitted last
61
+ //
62
+ // Signed blocks:
63
+ // - a signed top-level block ends with one trailing AUTH child
64
+ // - only the final AUTH is treated specially; earlier AUTH blocks remain ordinary signed child bytes
65
+ // - the signed slice runs from the parent block start through the AUTH head, excluding only AUTH proof bytes
66
+ // - `cid` binds the signature to one command; `deadline` acts as expiry and nonce
67
+ // - current helpers assume proof layout `[bytes20 signer][bytes65 sig]`
68
+
69
+ uint constant AUTH_PROOF_LEN = 85;
70
+ uint constant AUTH_TOTAL_LEN = 161;
71
+
72
+ struct AssetAmount {
73
+ bytes32 asset;
74
+ bytes32 meta;
75
+ uint amount;
76
+ }
77
+
78
+ struct HostAmount {
79
+ uint host;
80
+ bytes32 asset;
81
+ bytes32 meta;
82
+ uint amount;
83
+ }
84
+
85
+ struct UserAmount {
86
+ bytes32 account;
87
+ bytes32 asset;
88
+ bytes32 meta;
89
+ uint amount;
90
+ }
91
+
92
+ struct HostAsset {
93
+ uint host;
94
+ bytes32 asset;
95
+ bytes32 meta;
96
+ }
97
+
98
+ struct Tx {
99
+ bytes32 from;
100
+ bytes32 to;
101
+ bytes32 asset;
102
+ bytes32 meta;
103
+ uint amount;
104
+ }
105
+
@@ -0,0 +1,209 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { Blocks } from "./Blocks.sol";
5
+ import { AssetAmount, HostAmount, Tx, Keys } from "./Schema.sol";
6
+
7
+ struct Writer {
8
+ uint i;
9
+ uint end;
10
+ bytes dst;
11
+ }
12
+
13
+ uint constant ALLOC_SCALE = 10_000;
14
+ uint constant BALANCE_BLOCK_LEN = 108;
15
+ uint constant BOUNTY_BLOCK_LEN = 76;
16
+ uint constant CUSTODY_BLOCK_LEN = 140;
17
+ uint constant TX_BLOCK_LEN = 172;
18
+
19
+ library Writers {
20
+ error WriterOverflow();
21
+ error IncompleteWriter();
22
+ error EmptyRequest();
23
+
24
+ // Encodes a 12-byte block header (4-byte key + 4-byte selfLen + 4-byte totalLen) into a uint so assembly can
25
+ // write the full header in one mstore while the payload starts at offset + 12.
26
+ function toBlockHeader(bytes4 key, uint selfLen, uint totalLen) internal pure returns (uint) {
27
+ if (selfLen > type(uint32).max || totalLen > type(uint32).max || selfLen > totalLen) revert Blocks.MalformedBlocks();
28
+ return (uint(uint32(key)) << 224) | (uint(uint32(selfLen)) << 192) | (uint(uint32(totalLen)) << 160);
29
+ }
30
+
31
+ function alloc(uint len) internal pure returns (Writer memory writer) {
32
+ writer = Writer({i: 0, end: len, dst: new bytes(len)});
33
+ }
34
+
35
+ function append(Writer memory writer, bytes memory data) internal pure {
36
+ uint next = writer.i + data.length;
37
+ if (next > writer.dst.length) revert WriterOverflow();
38
+ assembly ("memory-safe") {
39
+ mcopy(add(add(mload(add(writer, 0x40)), 0x20), mload(writer)), add(data, 0x20), mload(data))
40
+ }
41
+ writer.i = next;
42
+ }
43
+
44
+ function allocBalancesFrom(
45
+ bytes calldata blocks,
46
+ uint i,
47
+ bytes4 source
48
+ ) internal pure returns (Writer memory writer, uint next) {
49
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE, BALANCE_BLOCK_LEN);
50
+ }
51
+
52
+ function allocPairedBalancesFrom(
53
+ bytes calldata blocks,
54
+ uint i,
55
+ bytes4 source
56
+ ) internal pure returns (Writer memory writer, uint next) {
57
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE * 2, BALANCE_BLOCK_LEN);
58
+ }
59
+
60
+ function allocScaledBalancesFrom(
61
+ bytes calldata blocks,
62
+ uint i,
63
+ bytes4 source,
64
+ uint scaledRatio
65
+ ) internal pure returns (Writer memory writer, uint next) {
66
+ return allocFromScaledCount(blocks, i, source, scaledRatio, BALANCE_BLOCK_LEN);
67
+ }
68
+
69
+ function allocTxsFrom(
70
+ bytes calldata blocks,
71
+ uint i,
72
+ bytes4 source
73
+ ) internal pure returns (Writer memory writer, uint next) {
74
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE, TX_BLOCK_LEN);
75
+ }
76
+
77
+ function allocCustodiesFrom(
78
+ bytes calldata blocks,
79
+ uint i,
80
+ bytes4 source
81
+ ) internal pure returns (Writer memory writer, uint next) {
82
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE, CUSTODY_BLOCK_LEN);
83
+ }
84
+
85
+ function allocScaledCustodiesFrom(
86
+ bytes calldata blocks,
87
+ uint i,
88
+ bytes4 source,
89
+ uint scaledRatio
90
+ ) internal pure returns (Writer memory writer, uint next) {
91
+ return allocFromScaledCount(blocks, i, source, scaledRatio, CUSTODY_BLOCK_LEN);
92
+ }
93
+
94
+ function allocFromScaledCount(
95
+ bytes calldata blocks,
96
+ uint i,
97
+ bytes4 source,
98
+ uint scaledRatio,
99
+ uint blockLen
100
+ ) internal pure returns (Writer memory writer, uint next) {
101
+ uint count;
102
+ (count, next) = Blocks.count(blocks, i, source);
103
+ if (count == 0) revert EmptyRequest();
104
+ uint scaledCount = count * scaledRatio;
105
+ if (scaledCount % ALLOC_SCALE != 0) revert Blocks.MalformedBlocks();
106
+ uint len = (scaledCount / ALLOC_SCALE) * blockLen;
107
+ writer = Writer({i: 0, end: len, dst: new bytes(len)});
108
+ }
109
+
110
+ function writeBalanceBlock(bytes memory dst, uint i, AssetAmount memory value) internal pure returns (uint next) {
111
+ next = i + BALANCE_BLOCK_LEN;
112
+ if (next > dst.length) revert WriterOverflow();
113
+ uint header = toBlockHeader(Keys.Balance, 96, 96);
114
+ assembly ("memory-safe") {
115
+ let p := add(add(dst, 0x20), i)
116
+ mstore(p, header)
117
+ mstore(add(p, 0x0c), mload(value))
118
+ mstore(add(p, 0x2c), mload(add(value, 0x20)))
119
+ mstore(add(p, 0x4c), mload(add(value, 0x40)))
120
+ }
121
+ }
122
+
123
+ function appendBalance(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
124
+ appendBalance(writer, AssetAmount(asset, meta, amount));
125
+ }
126
+
127
+ function appendBalance(Writer memory writer, AssetAmount memory value) internal pure {
128
+ writer.i = writeBalanceBlock(writer.dst, writer.i, value);
129
+ }
130
+
131
+ function appendNonZeroBalance(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
132
+ if (amount > 0) appendBalance(writer, asset, meta, amount);
133
+ }
134
+
135
+ function appendNonZeroBalance(Writer memory writer, AssetAmount memory value) internal pure {
136
+ if (value.amount > 0) appendBalance(writer, value);
137
+ }
138
+
139
+ function writeBountyBlock(bytes memory dst, uint i, uint amount, bytes32 relayer) internal pure returns (uint next) {
140
+ next = i + BOUNTY_BLOCK_LEN;
141
+ if (next > dst.length) revert WriterOverflow();
142
+ uint header = toBlockHeader(Keys.Bounty, 64, 64);
143
+ assembly ("memory-safe") {
144
+ let p := add(add(dst, 0x20), i)
145
+ mstore(p, header)
146
+ mstore(add(p, 0x0c), amount)
147
+ mstore(add(p, 0x2c), relayer)
148
+ }
149
+ }
150
+
151
+ function appendBounty(Writer memory writer, uint amount, bytes32 relayer) internal pure {
152
+ writer.i = writeBountyBlock(writer.dst, writer.i, amount, relayer);
153
+ }
154
+
155
+ function writeCustodyBlock(bytes memory dst, uint i, HostAmount memory value) internal pure returns (uint next) {
156
+ next = i + CUSTODY_BLOCK_LEN;
157
+ if (next > dst.length) revert WriterOverflow();
158
+ uint header = toBlockHeader(Keys.Custody, 128, 128);
159
+ assembly ("memory-safe") {
160
+ let p := add(add(dst, 0x20), i)
161
+ mstore(p, header)
162
+ mstore(add(p, 0x0c), mload(value))
163
+ mstore(add(p, 0x2c), mload(add(value, 0x20)))
164
+ mstore(add(p, 0x4c), mload(add(value, 0x40)))
165
+ mstore(add(p, 0x6c), mload(add(value, 0x60)))
166
+ }
167
+ }
168
+
169
+ function appendCustody(Writer memory writer, uint host, bytes32 asset, bytes32 meta, uint amount) internal pure {
170
+ appendCustody(writer, HostAmount(host, asset, meta, amount));
171
+ }
172
+
173
+ function appendCustody(Writer memory writer, HostAmount memory value) internal pure {
174
+ writer.i = writeCustodyBlock(writer.dst, writer.i, value);
175
+ }
176
+
177
+ function writeTxBlock(bytes memory dst, uint i, Tx memory value) internal pure returns (uint next) {
178
+ next = i + TX_BLOCK_LEN;
179
+ if (next > dst.length) revert WriterOverflow();
180
+ uint header = toBlockHeader(Keys.Transaction, 160, 160);
181
+ assembly ("memory-safe") {
182
+ let p := add(add(dst, 0x20), i)
183
+ mstore(p, header)
184
+ mstore(add(p, 0x0c), mload(value))
185
+ mstore(add(p, 0x2c), mload(add(value, 0x20)))
186
+ mstore(add(p, 0x4c), mload(add(value, 0x40)))
187
+ mstore(add(p, 0x6c), mload(add(value, 0x60)))
188
+ mstore(add(p, 0x8c), mload(add(value, 0x80)))
189
+ }
190
+ }
191
+
192
+ function appendTx(Writer memory writer, Tx memory value) internal pure {
193
+ writer.i = writeTxBlock(writer.dst, writer.i, value);
194
+ }
195
+
196
+ function done(Writer memory writer) internal pure returns (bytes memory) {
197
+ if (writer.i != writer.dst.length) revert IncompleteWriter();
198
+ return writer.dst;
199
+ }
200
+
201
+ function finish(Writer memory writer) internal pure returns (bytes memory out) {
202
+ if (writer.i == 0) revert EmptyRequest();
203
+ if (writer.i > writer.dst.length) revert IncompleteWriter();
204
+ out = writer.dst;
205
+ assembly ("memory-safe") {
206
+ mstore(out, mload(writer))
207
+ }
208
+ }
209
+ }
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { AssetAmount, Blocks, Block, Writers, Writer, Keys } from "../Blocks.sol";
5
+
6
+ using Blocks for Block;
7
+ using Writers for Writer;
8
+
9
+ abstract contract AmountToBalance {
10
+ function amountToBalance(bytes32 account, AssetAmount memory amount) internal virtual returns (AssetAmount memory);
11
+
12
+ function amountsToBalances(bytes calldata blocks, uint i, bytes32 account) internal returns (bytes memory) {
13
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(blocks, i, Keys.Amount);
14
+
15
+ while (i < end) {
16
+ Block memory ref = Blocks.from(blocks, i);
17
+ AssetAmount memory amount = ref.toAmountValue();
18
+ AssetAmount memory out = amountToBalance(account, amount);
19
+ writer.appendNonZeroBalance(out);
20
+ i = ref.cursor;
21
+ }
22
+
23
+ return writer.finish();
24
+ }
25
+ }
@@ -0,0 +1,36 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { HostAmount, Blocks, Block, Writers, Writer, Keys } from "../Blocks.sol";
5
+
6
+ using Blocks for Block;
7
+ using Writers for Writer;
8
+
9
+ abstract contract AmountToCustody {
10
+ function amountToCustody(
11
+ uint host,
12
+ bytes32 account,
13
+ bytes32 asset,
14
+ bytes32 meta,
15
+ uint amount
16
+ ) internal virtual returns (HostAmount memory);
17
+
18
+ function amountsToCustodies(
19
+ bytes calldata blocks,
20
+ uint i,
21
+ uint host,
22
+ bytes32 account
23
+ ) internal returns (bytes memory) {
24
+ (Writer memory writer, uint end) = Writers.allocCustodiesFrom(blocks, i, Keys.Amount);
25
+
26
+ while (i < end) {
27
+ Block memory ref = Blocks.from(blocks, i);
28
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackAmount();
29
+ HostAmount memory out = amountToCustody(host, account, asset, meta, amount);
30
+ if (out.amount > 0) writer.appendCustody(out);
31
+ i = ref.cursor;
32
+ }
33
+
34
+ return writer.finish();
35
+ }
36
+ }
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { AssetAmount, HostAmount, Blocks, Block, Writers, Writer, Keys } from "../Blocks.sol";
5
+
6
+ using Blocks for Block;
7
+ using Writers for Writer;
8
+
9
+ abstract contract CustodyToBalance {
10
+ function custodyToBalance(bytes32 account, HostAmount memory custody) internal virtual returns (AssetAmount memory);
11
+
12
+ function custodiesToBalances(bytes calldata blocks, uint i, bytes32 account) internal returns (bytes memory) {
13
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(blocks, i, Keys.Custody);
14
+
15
+ while (i < end) {
16
+ Block memory ref = Blocks.from(blocks, i);
17
+ HostAmount memory custody = ref.toCustodyValue();
18
+ AssetAmount memory out = custodyToBalance(account, custody);
19
+ writer.appendNonZeroBalance(out);
20
+ i = ref.cursor;
21
+ }
22
+
23
+ return writer.finish();
24
+ }
25
+ }
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { Blocks, Block, Keys } from "../Blocks.sol";
5
+
6
+ abstract contract EachRoute {
7
+ function eachRoute(Block memory rawRoute) internal virtual;
8
+
9
+ function forEachRoute(bytes calldata blocks, uint i) internal returns (uint) {
10
+ while (i < blocks.length) {
11
+ Block memory ref = Blocks.from(blocks, i);
12
+ if (ref.key != Keys.Route) return i;
13
+ eachRoute(ref);
14
+ i = ref.cursor;
15
+ }
16
+ return i;
17
+ }
18
+ }
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { AssetAmount, Blocks, Block, Writers, Writer, Keys } from "../Blocks.sol";
5
+
6
+ using Blocks for Block;
7
+ using Writers for Writer;
8
+
9
+ abstract contract MapBalance {
10
+ function mapBalance(bytes32 account, AssetAmount memory balance) internal virtual returns (AssetAmount memory out);
11
+
12
+ function mapBalances(bytes calldata state, uint i, bytes32 account) internal returns (bytes memory) {
13
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(state, i, Keys.Balance);
14
+
15
+ while (i < end) {
16
+ Block memory ref = Blocks.from(state, i);
17
+ AssetAmount memory balance = ref.toBalanceValue();
18
+ AssetAmount memory out = mapBalance(account, balance);
19
+ writer.appendNonZeroBalance(out);
20
+ i = ref.cursor;
21
+ }
22
+
23
+ return writer.finish();
24
+ }
25
+ }
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { HostAmount, Blocks, Block, Writers, Writer, Keys } from "../Blocks.sol";
5
+
6
+ using Blocks for Block;
7
+ using Writers for Writer;
8
+
9
+ abstract contract MapCustody {
10
+ function mapCustody(bytes32 account, HostAmount memory custody) internal virtual returns (HostAmount memory out);
11
+
12
+ function mapCustodies(bytes calldata state, uint i, bytes32 account) internal returns (bytes memory) {
13
+ (Writer memory writer, uint end) = Writers.allocCustodiesFrom(state, i, Keys.Custody);
14
+
15
+ while (i < end) {
16
+ Block memory ref = Blocks.from(state, i);
17
+ HostAmount memory custody = ref.toCustodyValue();
18
+ HostAmount memory out = mapCustody(account, custody);
19
+ if (out.amount > 0) writer.appendCustody(out);
20
+ i = ref.cursor;
21
+ }
22
+
23
+ return writer.finish();
24
+ }
25
+ }
@@ -0,0 +1,27 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { Blocks, Block, Writers, Writer, Keys } from "../Blocks.sol";
5
+
6
+ using Writers for Writer;
7
+
8
+ abstract contract RouteToBalance {
9
+ function routeToBalance(
10
+ bytes32 account,
11
+ Block memory rawRoute
12
+ ) internal virtual returns (bytes32 asset, bytes32 meta, uint amount);
13
+
14
+ function routesToBalances(bytes calldata blocks, uint i, bytes32 account) internal returns (bytes memory) {
15
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(blocks, i, Keys.Route);
16
+
17
+ while (i < end) {
18
+ Block memory route;
19
+ route = Blocks.routeFrom(blocks, i);
20
+ i = route.cursor;
21
+ (bytes32 asset, bytes32 meta, uint amount) = routeToBalance(account, route);
22
+ if (amount > 0) writer.appendBalance(asset, meta, amount);
23
+ }
24
+
25
+ return writer.finish();
26
+ }
27
+ }