@fastish/contracts 0.1.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 (105) hide show
  1. package/LICENSE +648 -0
  2. package/README.md +134 -0
  3. package/contracts/Blocks.sol +73 -0
  4. package/contracts/Commands.sol +47 -0
  5. package/contracts/Core.sol +10 -0
  6. package/contracts/Events.sol +18 -0
  7. package/contracts/Schema.sol +57 -0
  8. package/contracts/Utils.sol +105 -0
  9. package/contracts/blocks/Data.sol +646 -0
  10. package/contracts/blocks/Errors.sol +10 -0
  11. package/contracts/blocks/Mem.sol +122 -0
  12. package/contracts/blocks/Readers.sol +938 -0
  13. package/contracts/blocks/Schema.sol +148 -0
  14. package/contracts/blocks/Writers.sol +187 -0
  15. package/contracts/combinators/AmountToBalance.sol +26 -0
  16. package/contracts/combinators/AmountToCustody.sol +37 -0
  17. package/contracts/combinators/CustodyToBalance.sol +27 -0
  18. package/contracts/combinators/EachRoute.sol +19 -0
  19. package/contracts/combinators/MapBalance.sol +26 -0
  20. package/contracts/combinators/MapCustody.sol +26 -0
  21. package/contracts/combinators/RouteToBalance.sol +27 -0
  22. package/contracts/commands/Base.sol +39 -0
  23. package/contracts/commands/Borrow.sol +86 -0
  24. package/contracts/commands/Burn.sol +32 -0
  25. package/contracts/commands/Create.sol +31 -0
  26. package/contracts/commands/CreditTo.sol +36 -0
  27. package/contracts/commands/DebitFrom.sol +44 -0
  28. package/contracts/commands/Deposit.sol +46 -0
  29. package/contracts/commands/Fund.sol +37 -0
  30. package/contracts/commands/Liquidate.sol +93 -0
  31. package/contracts/commands/Liquidity.sol +171 -0
  32. package/contracts/commands/Mint.sol +41 -0
  33. package/contracts/commands/Pipe.sol +54 -0
  34. package/contracts/commands/Provision.sol +48 -0
  35. package/contracts/commands/Reclaim.sol +46 -0
  36. package/contracts/commands/Redeem.sol +93 -0
  37. package/contracts/commands/Remove.sol +31 -0
  38. package/contracts/commands/Repay.sol +93 -0
  39. package/contracts/commands/Settle.sol +32 -0
  40. package/contracts/commands/Stake.sol +114 -0
  41. package/contracts/commands/Supply.sol +32 -0
  42. package/contracts/commands/Swap.sol +86 -0
  43. package/contracts/commands/Transfer.sol +41 -0
  44. package/contracts/commands/Unstake.sol +49 -0
  45. package/contracts/commands/Withdraw.sol +37 -0
  46. package/contracts/commands/admin/Allocate.sol +33 -0
  47. package/contracts/commands/admin/AllowAssets.sol +34 -0
  48. package/contracts/commands/admin/Authorize.sol +32 -0
  49. package/contracts/commands/admin/DenyAssets.sol +34 -0
  50. package/contracts/commands/admin/Destroy.sol +26 -0
  51. package/contracts/commands/admin/Init.sol +26 -0
  52. package/contracts/commands/admin/Relocate.sol +32 -0
  53. package/contracts/commands/admin/Unauthorize.sol +32 -0
  54. package/contracts/core/Access.sol +49 -0
  55. package/contracts/core/Balances.sol +9 -0
  56. package/contracts/core/Host.sol +25 -0
  57. package/contracts/core/Operation.sol +32 -0
  58. package/contracts/core/Validator.sol +31 -0
  59. package/contracts/events/Access.sol +14 -0
  60. package/contracts/events/Asset.sol +14 -0
  61. package/contracts/events/Balance.sol +14 -0
  62. package/contracts/events/Collateral.sol +15 -0
  63. package/contracts/events/Command.sol +14 -0
  64. package/contracts/events/Debt.sol +15 -0
  65. package/contracts/events/Deposit.sol +14 -0
  66. package/contracts/events/Emitter.sol +7 -0
  67. package/contracts/events/Fastish.sol +14 -0
  68. package/contracts/events/Governed.sol +14 -0
  69. package/contracts/events/HostAnnounced.sol +14 -0
  70. package/contracts/events/Listing.sol +14 -0
  71. package/contracts/events/Peer.sol +14 -0
  72. package/contracts/events/Quote.sol +14 -0
  73. package/contracts/events/Withdraw.sol +14 -0
  74. package/contracts/interfaces/IHostDiscovery.sol +6 -0
  75. package/contracts/peer/AllowAssets.sol +31 -0
  76. package/contracts/peer/Base.sol +19 -0
  77. package/contracts/peer/DenyAssets.sol +31 -0
  78. package/contracts/peer/Pull.sol +30 -0
  79. package/contracts/peer/Push.sol +30 -0
  80. package/contracts/test/TestBlockHelper.sol +256 -0
  81. package/contracts/test/TestBorrowHost.sol +46 -0
  82. package/contracts/test/TestBurnHost.sol +28 -0
  83. package/contracts/test/TestCreateHost.sol +26 -0
  84. package/contracts/test/TestDiscovery.sol +6 -0
  85. package/contracts/test/TestECDSA.sol +16 -0
  86. package/contracts/test/TestHost.sol +215 -0
  87. package/contracts/test/TestLiquidityHost.sol +149 -0
  88. package/contracts/test/TestMintHost.sol +40 -0
  89. package/contracts/test/TestPeerHost.sol +34 -0
  90. package/contracts/test/TestReclaimHost.sol +47 -0
  91. package/contracts/test/TestRejectEther.sol +8 -0
  92. package/contracts/test/TestRemoveHost.sol +26 -0
  93. package/contracts/test/TestSwapHost.sol +45 -0
  94. package/contracts/test/TestUtils.sol +180 -0
  95. package/contracts/test/TestValidator.sol +10 -0
  96. package/contracts/utils/Accounts.sol +42 -0
  97. package/contracts/utils/Assets.sol +71 -0
  98. package/contracts/utils/Channels.sol +9 -0
  99. package/contracts/utils/ECDSA.sol +36 -0
  100. package/contracts/utils/Ids.sol +75 -0
  101. package/contracts/utils/Layout.sol +20 -0
  102. package/contracts/utils/Strings.sol +16 -0
  103. package/contracts/utils/Utils.sol +117 -0
  104. package/contracts/utils/Value.sol +18 -0
  105. package/package.json +29 -0
@@ -0,0 +1,148 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ // Block stream:
5
+ // - encoding is [bytes4 key][bytes4 selfLen][bytes4 totalLen][self payload][child blocks...]
6
+ // - `selfLen` covers only the block payload
7
+ // - `totalLen` covers payload plus child blocks
8
+ // - payload layout is block-specific
9
+ //
10
+ // Extensible payloads:
11
+ // - self payload may be [head][dynamic tail]
12
+ // - head layout is implied by the block key
13
+ // - one dynamic field may consume the rest of self payload without its own length prefix
14
+ // - child blocks, if any, are encoded as a normal nested block stream
15
+ //
16
+ // Schema DSL:
17
+ // - `;` separates top-level sibling blocks
18
+ // - `>` attaches child blocks to the preceding parent
19
+ // - repeated `>` adds more children to the same parent, not to the previous child
20
+ // - `->` separates request and response shapes, appears at most once, and is omitted when no output is modeled
21
+ // - top-level blocks of the same type should be grouped together
22
+ // - primary / driving blocks should appear before auxiliary blocks
23
+ // - `route(<fields...>)` is a reserved extensible schema form whose key is always `ROUTE_KEY`
24
+ // - canonical blocks are `amount(...)` for request amounts, `balance(...)` for state balances,
25
+ // `minimum(...)` for result floors, `maximum(...)` for spend ceilings, and `quantity(...)`
26
+ // for plain scalar amounts
27
+ // - `auth(uint cid, uint deadline, bytes proof)` is a proof-separator child and must be emitted last
28
+ //
29
+ // Signed blocks:
30
+ // - a signed top-level block ends with one trailing AUTH child
31
+ // - only the final AUTH is treated specially; earlier AUTH blocks remain ordinary signed child bytes
32
+ // - the signed slice runs from the parent block start through the AUTH head, excluding only AUTH proof bytes
33
+ // - `cid` binds the signature to one command; `deadline` acts as expiry and nonce
34
+ // - current helpers assume proof layout `[bytes20 signer][bytes65 sig]`
35
+
36
+ string constant AMOUNT = "amount(bytes32 asset, bytes32 meta, uint amount)";
37
+ bytes4 constant AMOUNT_KEY = bytes4(keccak256("amount(bytes32 asset, bytes32 meta, uint amount)"));
38
+ string constant BALANCE = "balance(bytes32 asset, bytes32 meta, uint amount)";
39
+ bytes4 constant BALANCE_KEY = bytes4(keccak256("balance(bytes32 asset, bytes32 meta, uint amount)"));
40
+ string constant CUSTODY = "custody(uint host, bytes32 asset, bytes32 meta, uint amount)";
41
+ bytes4 constant CUSTODY_KEY = bytes4(keccak256("custody(uint host, bytes32 asset, bytes32 meta, uint amount)"));
42
+ string constant MINIMUM = "minimum(bytes32 asset, bytes32 meta, uint amount)";
43
+ bytes4 constant MINIMUM_KEY = bytes4(keccak256("minimum(bytes32 asset, bytes32 meta, uint amount)"));
44
+ string constant MAXIMUM = "maximum(bytes32 asset, bytes32 meta, uint amount)";
45
+ bytes4 constant MAXIMUM_KEY = bytes4(keccak256("maximum(bytes32 asset, bytes32 meta, uint amount)"));
46
+ string constant ROUTE = "route(bytes data)";
47
+ string constant ROUTE_EMPTY = "route()";
48
+ bytes4 constant ROUTE_KEY = bytes4(keccak256("route(bytes data)"));
49
+ string constant QUANTITY = "quantity(uint amount)";
50
+ bytes4 constant QUANTITY_KEY = bytes4(keccak256("quantity(uint amount)"));
51
+ string constant RATE = "rate(uint value)";
52
+ bytes4 constant RATE_KEY = bytes4(keccak256("rate(uint value)"));
53
+ string constant PARTY = "party(bytes32 account)";
54
+ bytes4 constant PARTY_KEY = bytes4(keccak256("party(bytes32 account)"));
55
+ string constant RECIPIENT = "recipient(bytes32 account)";
56
+ bytes4 constant RECIPIENT_KEY = bytes4(keccak256("recipient(bytes32 account)"));
57
+ string constant TX = "tx(bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount)";
58
+ bytes4 constant TX_KEY = bytes4(keccak256("tx(bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount)"));
59
+ string constant STEP = "step(uint target, uint value, bytes request)";
60
+ bytes4 constant STEP_KEY = bytes4(keccak256("step(uint target, uint value, bytes request)"));
61
+ string constant AUTH = "auth(uint cid, uint deadline, bytes proof)";
62
+ bytes4 constant AUTH_KEY = bytes4(keccak256("auth(uint cid, uint deadline, bytes proof)"));
63
+ string constant ASSET = "asset(bytes32 asset, bytes32 meta)";
64
+ bytes4 constant ASSET_KEY = bytes4(keccak256("asset(bytes32 asset, bytes32 meta)"));
65
+ string constant NODE = "node(uint id)";
66
+ bytes4 constant NODE_KEY = bytes4(keccak256("node(uint id)"));
67
+ string constant LISTING = "listing(uint host, bytes32 asset, bytes32 meta)";
68
+ bytes4 constant LISTING_KEY = bytes4(keccak256("listing(uint host, bytes32 asset, bytes32 meta)"));
69
+ string constant FUNDING = "funding(uint host, uint amount)";
70
+ bytes4 constant FUNDING_KEY = bytes4(keccak256("funding(uint host, uint amount)"));
71
+ string constant ALLOCATION = "allocation(uint host, bytes32 asset, bytes32 meta, uint amount)";
72
+ bytes4 constant ALLOCATION_KEY = bytes4(keccak256("allocation(uint host, bytes32 asset, bytes32 meta, uint amount)"));
73
+ string constant BOUNTY = "bounty(uint amount, bytes32 relayer)";
74
+ bytes4 constant BOUNTY_KEY = bytes4(keccak256("bounty(uint amount, bytes32 relayer)"));
75
+
76
+ uint constant AUTH_PROOF_LEN = 85;
77
+ uint constant AUTH_TOTAL_LEN = 161;
78
+
79
+ struct AssetAmount {
80
+ bytes32 asset;
81
+ bytes32 meta;
82
+ uint amount;
83
+ }
84
+
85
+ struct HostAmount {
86
+ uint host;
87
+ bytes32 asset;
88
+ bytes32 meta;
89
+ uint amount;
90
+ }
91
+
92
+ struct UserAmount {
93
+ bytes32 account;
94
+ bytes32 asset;
95
+ bytes32 meta;
96
+ uint amount;
97
+ }
98
+
99
+ struct Listing {
100
+ uint host;
101
+ bytes32 asset;
102
+ bytes32 meta;
103
+ }
104
+
105
+ struct Tx {
106
+ bytes32 from;
107
+ bytes32 to;
108
+ bytes32 asset;
109
+ bytes32 meta;
110
+ uint amount;
111
+ }
112
+
113
+ struct BlockRef {
114
+ bytes4 key;
115
+ uint i;
116
+ uint bound;
117
+ uint end;
118
+ }
119
+
120
+ struct BlockPairRef {
121
+ BlockRef a;
122
+ BlockRef b;
123
+ }
124
+
125
+ struct DataRef {
126
+ bytes4 key;
127
+ uint i;
128
+ uint bound;
129
+ uint end;
130
+ }
131
+
132
+ struct DataPairRef {
133
+ DataRef a;
134
+ DataRef b;
135
+ }
136
+
137
+ struct MemRef {
138
+ bytes4 key;
139
+ uint i;
140
+ uint bound;
141
+ uint end;
142
+ }
143
+
144
+ struct Writer {
145
+ uint i;
146
+ uint end;
147
+ bytes dst;
148
+ }
@@ -0,0 +1,187 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Blocks} from "./Readers.sol";
5
+ import {MalformedBlocks} from "./Errors.sol";
6
+ import {AssetAmount, BALANCE_KEY, CUSTODY_KEY, HostAmount, TX_KEY, Tx, Writer} from "./Schema.sol";
7
+
8
+ error WriterOverflow();
9
+ error IncompleteWriter();
10
+ error EmptyRequest();
11
+
12
+ uint constant ALLOC_SCALE = 10_000;
13
+ uint constant BALANCE_BLOCK_LEN = 108;
14
+ uint constant CUSTODY_BLOCK_LEN = 140;
15
+ uint constant TX_BLOCK_LEN = 172;
16
+
17
+ library Writers {
18
+ // Encodes a 12-byte block header (4-byte key + 4-byte selfLen + 4-byte totalLen) into a uint so assembly can
19
+ // write the full header in one mstore while the payload starts at offset + 12.
20
+ function toBlockHeader(bytes4 key, uint selfLen, uint totalLen) internal pure returns (uint) {
21
+ if (selfLen > type(uint32).max || totalLen > type(uint32).max || selfLen > totalLen) revert MalformedBlocks();
22
+ return (uint(uint32(key)) << 224) | (uint(uint32(selfLen)) << 192) | (uint(uint32(totalLen)) << 160);
23
+ }
24
+
25
+ function alloc(uint len) internal pure returns (Writer memory writer) {
26
+ writer = Writer({i: 0, end: len, dst: new bytes(len)});
27
+ }
28
+
29
+ function append(Writer memory writer, bytes memory data) internal pure {
30
+ uint next = writer.i + data.length;
31
+ if (next > writer.dst.length) revert WriterOverflow();
32
+ assembly ("memory-safe") {
33
+ mcopy(add(add(mload(add(writer, 0x40)), 0x20), mload(writer)), add(data, 0x20), mload(data))
34
+ }
35
+ writer.i = next;
36
+ }
37
+
38
+ function allocBalancesFrom(
39
+ bytes calldata blocks,
40
+ uint i,
41
+ bytes4 source
42
+ ) internal pure returns (Writer memory writer, uint next) {
43
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE, BALANCE_BLOCK_LEN);
44
+ }
45
+
46
+ function allocPairedBalancesFrom(
47
+ bytes calldata blocks,
48
+ uint i,
49
+ bytes4 source
50
+ ) internal pure returns (Writer memory writer, uint next) {
51
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE * 2, BALANCE_BLOCK_LEN);
52
+ }
53
+
54
+ function allocScaledBalancesFrom(
55
+ bytes calldata blocks,
56
+ uint i,
57
+ bytes4 source,
58
+ uint scaledRatio
59
+ ) internal pure returns (Writer memory writer, uint next) {
60
+ return allocFromScaledCount(blocks, i, source, scaledRatio, BALANCE_BLOCK_LEN);
61
+ }
62
+
63
+ function allocTxsFrom(
64
+ bytes calldata blocks,
65
+ uint i,
66
+ bytes4 source
67
+ ) internal pure returns (Writer memory writer, uint next) {
68
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE, TX_BLOCK_LEN);
69
+ }
70
+
71
+ function allocCustodiesFrom(
72
+ bytes calldata blocks,
73
+ uint i,
74
+ bytes4 source
75
+ ) internal pure returns (Writer memory writer, uint next) {
76
+ return allocFromScaledCount(blocks, i, source, ALLOC_SCALE, CUSTODY_BLOCK_LEN);
77
+ }
78
+
79
+ function allocScaledCustodiesFrom(
80
+ bytes calldata blocks,
81
+ uint i,
82
+ bytes4 source,
83
+ uint scaledRatio
84
+ ) internal pure returns (Writer memory writer, uint next) {
85
+ return allocFromScaledCount(blocks, i, source, scaledRatio, CUSTODY_BLOCK_LEN);
86
+ }
87
+
88
+ function allocFromScaledCount(
89
+ bytes calldata blocks,
90
+ uint i,
91
+ bytes4 source,
92
+ uint scaledRatio,
93
+ uint blockLen
94
+ ) internal pure returns (Writer memory writer, uint next) {
95
+ uint count;
96
+ (count, next) = Blocks.count(blocks, i, source);
97
+ if (count == 0) revert EmptyRequest();
98
+ uint scaledCount = count * scaledRatio;
99
+ if (scaledCount % ALLOC_SCALE != 0) revert MalformedBlocks();
100
+ uint len = (scaledCount / ALLOC_SCALE) * blockLen;
101
+ writer = Writer({i: 0, end: len, dst: new bytes(len)});
102
+ }
103
+
104
+ function writeBalanceBlock(bytes memory dst, uint i, AssetAmount memory value) internal pure returns (uint next) {
105
+ next = i + BALANCE_BLOCK_LEN;
106
+ if (next > dst.length) revert WriterOverflow();
107
+ uint header = toBlockHeader(BALANCE_KEY, 96, 96);
108
+ assembly ("memory-safe") {
109
+ let p := add(add(dst, 0x20), i)
110
+ mstore(p, header)
111
+ mstore(add(p, 0x0c), mload(value))
112
+ mstore(add(p, 0x2c), mload(add(value, 0x20)))
113
+ mstore(add(p, 0x4c), mload(add(value, 0x40)))
114
+ }
115
+ }
116
+
117
+ function appendBalance(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
118
+ appendBalance(writer, AssetAmount(asset, meta, amount));
119
+ }
120
+
121
+ function appendBalance(Writer memory writer, AssetAmount memory value) internal pure {
122
+ writer.i = writeBalanceBlock(writer.dst, writer.i, value);
123
+ }
124
+
125
+ function appendNonZeroBalance(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
126
+ if (amount > 0) appendBalance(writer, asset, meta, amount);
127
+ }
128
+
129
+ function appendNonZeroBalance(Writer memory writer, AssetAmount memory value) internal pure {
130
+ if (value.amount > 0) appendBalance(writer, value);
131
+ }
132
+
133
+ function writeCustodyBlock(bytes memory dst, uint i, HostAmount memory value) internal pure returns (uint next) {
134
+ next = i + CUSTODY_BLOCK_LEN;
135
+ if (next > dst.length) revert WriterOverflow();
136
+ uint header = toBlockHeader(CUSTODY_KEY, 128, 128);
137
+ assembly ("memory-safe") {
138
+ let p := add(add(dst, 0x20), i)
139
+ mstore(p, header)
140
+ mstore(add(p, 0x0c), mload(value))
141
+ mstore(add(p, 0x2c), mload(add(value, 0x20)))
142
+ mstore(add(p, 0x4c), mload(add(value, 0x40)))
143
+ mstore(add(p, 0x6c), mload(add(value, 0x60)))
144
+ }
145
+ }
146
+
147
+ function appendCustody(Writer memory writer, uint host, bytes32 asset, bytes32 meta, uint amount) internal pure {
148
+ appendCustody(writer, HostAmount(host, asset, meta, amount));
149
+ }
150
+
151
+ function appendCustody(Writer memory writer, HostAmount memory value) internal pure {
152
+ writer.i = writeCustodyBlock(writer.dst, writer.i, value);
153
+ }
154
+
155
+ function writeTxBlock(bytes memory dst, uint i, Tx memory value) internal pure returns (uint next) {
156
+ next = i + TX_BLOCK_LEN;
157
+ if (next > dst.length) revert WriterOverflow();
158
+ uint header = toBlockHeader(TX_KEY, 160, 160);
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
+ mstore(add(p, 0x8c), mload(add(value, 0x80)))
167
+ }
168
+ }
169
+
170
+ function appendTx(Writer memory writer, Tx memory value) internal pure {
171
+ writer.i = writeTxBlock(writer.dst, writer.i, value);
172
+ }
173
+
174
+ function done(Writer memory writer) internal pure returns (bytes memory) {
175
+ if (writer.i != writer.dst.length) revert IncompleteWriter();
176
+ return writer.dst;
177
+ }
178
+
179
+ function finish(Writer memory writer) internal pure returns (bytes memory out) {
180
+ if (writer.i == 0) revert EmptyRequest();
181
+ if (writer.i > writer.dst.length) revert IncompleteWriter();
182
+ out = writer.dst;
183
+ assembly ("memory-safe") {
184
+ mstore(out, mload(writer))
185
+ }
186
+ }
187
+ }
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {AMOUNT_KEY, AssetAmount} from "../Schema.sol";
5
+ import {Blocks, BlockRef, Writers, Writer} from "../Blocks.sol";
6
+
7
+ using Blocks for BlockRef;
8
+ using Writers for Writer;
9
+
10
+ abstract contract AmountToBalance {
11
+ function amountToBalance(bytes32 account, AssetAmount memory amount) internal virtual returns (AssetAmount memory);
12
+
13
+ function amountsToBalances(bytes calldata blocks, uint i, bytes32 account) internal returns (bytes memory) {
14
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(blocks, i, AMOUNT_KEY);
15
+
16
+ while (i < end) {
17
+ BlockRef memory ref = Blocks.from(blocks, i);
18
+ AssetAmount memory amount = ref.toAmountValue(blocks);
19
+ AssetAmount memory out = amountToBalance(account, amount);
20
+ writer.appendNonZeroBalance(out);
21
+ i = ref.end;
22
+ }
23
+
24
+ return writer.finish();
25
+ }
26
+ }
@@ -0,0 +1,37 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {AMOUNT_KEY, HostAmount} from "../Schema.sol";
5
+ import {Blocks, BlockRef, Writers, Writer} from "../Blocks.sol";
6
+
7
+ using Blocks for BlockRef;
8
+ using Writers for Writer;
9
+
10
+ abstract contract AmountToCustody {
11
+ function amountToCustody(
12
+ uint host,
13
+ bytes32 account,
14
+ bytes32 asset,
15
+ bytes32 meta,
16
+ uint amount
17
+ ) internal virtual returns (HostAmount memory);
18
+
19
+ function amountsToCustodies(
20
+ bytes calldata blocks,
21
+ uint i,
22
+ uint host,
23
+ bytes32 account
24
+ ) internal returns (bytes memory) {
25
+ (Writer memory writer, uint end) = Writers.allocCustodiesFrom(blocks, i, AMOUNT_KEY);
26
+
27
+ while (i < end) {
28
+ BlockRef memory ref = Blocks.from(blocks, i);
29
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackAmount(blocks);
30
+ HostAmount memory out = amountToCustody(host, account, asset, meta, amount);
31
+ if (out.amount > 0) writer.appendCustody(out);
32
+ i = ref.end;
33
+ }
34
+
35
+ return writer.finish();
36
+ }
37
+ }
@@ -0,0 +1,27 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {AssetAmount, HostAmount, CUSTODY_KEY, ROUTE_KEY} from "../Schema.sol";
5
+ import {Blocks, BlockRef, Data, DataRef, Writers, Writer} from "../Blocks.sol";
6
+
7
+ using Blocks for BlockRef;
8
+ using Data for DataRef;
9
+ using Writers for Writer;
10
+
11
+ abstract contract CustodyToBalance {
12
+ function custodyToBalance(bytes32 account, HostAmount memory custody) internal virtual returns (AssetAmount memory);
13
+
14
+ function custodiesToBalances(bytes calldata blocks, uint i, bytes32 account) internal returns (bytes memory) {
15
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(blocks, i, CUSTODY_KEY);
16
+
17
+ while (i < end) {
18
+ BlockRef memory ref = Blocks.from(blocks, i);
19
+ HostAmount memory custody = ref.toCustodyValue(blocks);
20
+ AssetAmount memory out = custodyToBalance(account, custody);
21
+ writer.appendNonZeroBalance(out);
22
+ i = ref.end;
23
+ }
24
+
25
+ return writer.finish();
26
+ }
27
+ }
@@ -0,0 +1,19 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {ROUTE_KEY} from "../Schema.sol";
5
+ import {Data, DataRef} from "../Blocks.sol";
6
+
7
+ abstract contract EachRoute {
8
+ function eachRoute(DataRef memory rawRoute) internal virtual;
9
+
10
+ function forEachRoute(bytes calldata blocks, uint i) internal returns (uint) {
11
+ while (i < blocks.length) {
12
+ (DataRef memory ref, uint next) = Data.from(blocks, i);
13
+ if (ref.key != ROUTE_KEY) return i;
14
+ eachRoute(ref);
15
+ i = next;
16
+ }
17
+ return i;
18
+ }
19
+ }
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {AssetAmount, BALANCE_KEY} from "../Schema.sol";
5
+ import {Blocks, BlockRef, Writers, Writer} from "../Blocks.sol";
6
+
7
+ using Blocks for BlockRef;
8
+ using Writers for Writer;
9
+
10
+ abstract contract MapBalance {
11
+ function mapBalance(bytes32 account, AssetAmount memory balance) internal virtual returns (AssetAmount memory out);
12
+
13
+ function mapBalances(bytes calldata state, uint i, bytes32 account) internal returns (bytes memory) {
14
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(state, i, BALANCE_KEY);
15
+
16
+ while (i < end) {
17
+ BlockRef memory ref = Blocks.from(state, i);
18
+ AssetAmount memory balance = ref.toBalanceValue(state);
19
+ AssetAmount memory out = mapBalance(account, balance);
20
+ writer.appendNonZeroBalance(out);
21
+ i = ref.end;
22
+ }
23
+
24
+ return writer.finish();
25
+ }
26
+ }
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CUSTODY_KEY, HostAmount} from "../Schema.sol";
5
+ import {Blocks, BlockRef, Writers, Writer} from "../Blocks.sol";
6
+
7
+ using Blocks for BlockRef;
8
+ using Writers for Writer;
9
+
10
+ abstract contract MapCustody {
11
+ function mapCustody(bytes32 account, HostAmount memory custody) internal virtual returns (HostAmount memory out);
12
+
13
+ function mapCustodies(bytes calldata state, uint i, bytes32 account) internal returns (bytes memory) {
14
+ (Writer memory writer, uint end) = Writers.allocCustodiesFrom(state, i, CUSTODY_KEY);
15
+
16
+ while (i < end) {
17
+ BlockRef memory ref = Blocks.from(state, i);
18
+ HostAmount memory custody = ref.toCustodyValue(state);
19
+ HostAmount memory out = mapCustody(account, custody);
20
+ if (out.amount > 0) writer.appendCustody(out);
21
+ i = ref.end;
22
+ }
23
+
24
+ return writer.finish();
25
+ }
26
+ }
@@ -0,0 +1,27 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {ROUTE_KEY} from "../Schema.sol";
5
+ import {Data, DataRef, Writers, Writer} from "../Blocks.sol";
6
+
7
+ using Writers for Writer;
8
+
9
+ abstract contract RouteToBalance {
10
+ function routeToBalance(
11
+ bytes32 account,
12
+ DataRef memory rawRoute
13
+ ) internal virtual returns (bytes32 asset, bytes32 meta, uint amount);
14
+
15
+ function routesToBalances(bytes calldata blocks, uint i, bytes32 account) internal returns (bytes memory) {
16
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(blocks, i, ROUTE_KEY);
17
+
18
+ while (i < end) {
19
+ DataRef memory route;
20
+ (route, i) = Data.routeFrom(blocks, i);
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
+ }
@@ -0,0 +1,39 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {OperationBase} from "../core/Operation.sol";
5
+ import {CommandEvent} from "../events/Command.sol";
6
+ import {toCommandId, toCommandSelector} from "../utils/Ids.sol";
7
+
8
+ struct CommandContext {
9
+ uint target;
10
+ bytes32 account;
11
+ bytes state;
12
+ bytes request;
13
+ }
14
+
15
+ abstract contract CommandBase is OperationBase, CommandEvent {
16
+ error Expired();
17
+ error NotAdmin(bytes32 value);
18
+ error UnexpectedEndpoint();
19
+
20
+ modifier onlyAdmin(bytes32 account) {
21
+ if (account != adminAccount) revert NotAdmin(account);
22
+ _;
23
+ }
24
+
25
+ modifier onlyCommand(uint cid, uint target) {
26
+ if (target != 0 && target != cid) revert UnexpectedEndpoint();
27
+ enforceCaller(msg.sender);
28
+ _;
29
+ }
30
+
31
+ modifier onlyActive(uint deadline) {
32
+ if (deadline < block.timestamp) revert Expired();
33
+ _;
34
+ }
35
+
36
+ function commandId(string memory name) internal view returns (uint) {
37
+ return toCommandId(toCommandSelector(name), address(this));
38
+ }
39
+ }
@@ -0,0 +1,86 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandContext, CommandBase} from "./Base.sol";
5
+ import {BALANCES, CUSTODIES} from "../utils/Channels.sol";
6
+ import {AssetAmount, HostAmount, AMOUNT, BALANCE_KEY, CUSTODY_KEY, Blocks, BlockRef, Data, DataRef, Writers, Writer} from "../Blocks.sol";
7
+ import {routeSchema1} from "../utils/Utils.sol";
8
+
9
+ string constant BABTB = "borrowAgainstBalanceToBalance";
10
+ string constant BACTB = "borrowAgainstCustodyToBalance";
11
+
12
+ using Blocks for BlockRef;
13
+ using Data for DataRef;
14
+ using Writers for Writer;
15
+
16
+ abstract contract BorrowAgainstCustodyToBalance is CommandBase {
17
+ uint internal immutable borrowAgainstCustodyToBalanceId = commandId(BACTB);
18
+
19
+ constructor(string memory maybeRoute) {
20
+ string memory schema = routeSchema1(maybeRoute, AMOUNT);
21
+ emit Command(host, BACTB, schema, borrowAgainstCustodyToBalanceId, CUSTODIES, BALANCES);
22
+ }
23
+
24
+ // @dev implementation extracts the requested borrow amount from rawRoute.innerAmount()
25
+ function borrowAgainstCustodyToBalance(
26
+ bytes32 account,
27
+ HostAmount memory custody,
28
+ DataRef memory rawRoute
29
+ ) internal virtual returns (AssetAmount memory);
30
+
31
+ function borrowAgainstCustodyToBalance(
32
+ CommandContext calldata c
33
+ ) external payable onlyCommand(borrowAgainstCustodyToBalanceId, c.target) returns (bytes memory) {
34
+ uint i = 0;
35
+ uint q = 0;
36
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(c.state, i, CUSTODY_KEY);
37
+
38
+ while (i < end) {
39
+ DataRef memory route;
40
+ (route, q) = Data.routeFrom(c.request, q);
41
+ BlockRef memory ref = Blocks.from(c.state, i);
42
+ HostAmount memory custody = ref.toCustodyValue(c.state);
43
+ AssetAmount memory out = borrowAgainstCustodyToBalance(c.account, custody, route);
44
+ writer.appendNonZeroBalance(out);
45
+ i = ref.end;
46
+ }
47
+
48
+ return writer.finish();
49
+ }
50
+ }
51
+
52
+ abstract contract BorrowAgainstBalanceToBalance is CommandBase {
53
+ uint internal immutable borrowAgainstBalanceToBalanceId = commandId(BABTB);
54
+
55
+ constructor(string memory maybeRoute) {
56
+ string memory schema = routeSchema1(maybeRoute, AMOUNT);
57
+ emit Command(host, BABTB, schema, borrowAgainstBalanceToBalanceId, BALANCES, BALANCES);
58
+ }
59
+
60
+ // @dev implementation extracts the requested borrow amount from rawRoute.innerAmount()
61
+ function borrowAgainstBalanceToBalance(
62
+ bytes32 account,
63
+ AssetAmount memory balance,
64
+ DataRef memory rawRoute
65
+ ) internal virtual returns (AssetAmount memory);
66
+
67
+ function borrowAgainstBalanceToBalance(
68
+ CommandContext calldata c
69
+ ) external payable onlyCommand(borrowAgainstBalanceToBalanceId, c.target) returns (bytes memory) {
70
+ uint i = 0;
71
+ uint q = 0;
72
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(c.state, i, BALANCE_KEY);
73
+
74
+ while (i < end) {
75
+ DataRef memory route;
76
+ (route, q) = Data.routeFrom(c.request, q);
77
+ BlockRef memory ref = Blocks.from(c.state, i);
78
+ AssetAmount memory balance = ref.toBalanceValue(c.state);
79
+ AssetAmount memory out = borrowAgainstBalanceToBalance(c.account, balance, route);
80
+ writer.appendNonZeroBalance(out);
81
+ i = ref.end;
82
+ }
83
+
84
+ return writer.finish();
85
+ }
86
+ }