@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,32 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandBase, CommandContext} from "./Base.sol";
5
+ import {BALANCES, SETUP} from "../utils/Channels.sol";
6
+ import {Blocks, BlockRef} from "../Blocks.sol";
7
+ using Blocks for BlockRef;
8
+
9
+ string constant NAME = "burn";
10
+
11
+ abstract contract Burn is CommandBase {
12
+ uint internal immutable burnId = commandId(NAME);
13
+
14
+ constructor(string memory route) {
15
+ emit Command(host, NAME, route, burnId, BALANCES, SETUP);
16
+ }
17
+
18
+ function burn(bytes32 account, bytes32 asset, bytes32 meta, uint amount) internal virtual returns (uint);
19
+
20
+ function burn(CommandContext calldata c) external payable onlyCommand(burnId, c.target) returns (bytes memory) {
21
+ uint i = 0;
22
+ while (i < c.state.length) {
23
+ BlockRef memory ref = Blocks.from(c.state, i);
24
+ if (!ref.isBalance()) break;
25
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackBalance(c.state);
26
+ burn(c.account, asset, meta, amount);
27
+ i = ref.end;
28
+ }
29
+
30
+ return done(0, i);
31
+ }
32
+ }
@@ -0,0 +1,31 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandBase, CommandContext} from "./Base.sol";
5
+ import {SETUP} from "../utils/Channels.sol";
6
+ import {Data, DataRef, ROUTE_KEY} from "../Blocks.sol";
7
+ using Data for DataRef;
8
+
9
+ string constant NAME = "create";
10
+
11
+ abstract contract Create is CommandBase {
12
+ uint internal immutable createId = commandId(NAME);
13
+
14
+ constructor(string memory route) {
15
+ emit Command(host, NAME, route, createId, SETUP, SETUP);
16
+ }
17
+
18
+ function create(bytes32 account, DataRef memory rawRoute) internal virtual;
19
+
20
+ function create(CommandContext calldata c) external payable onlyCommand(createId, c.target) returns (bytes memory) {
21
+ uint q = 0;
22
+ while (q < c.request.length) {
23
+ (DataRef memory ref, uint next) = Data.from(c.request, q);
24
+ if (ref.key != ROUTE_KEY) break;
25
+ create(c.account, ref);
26
+ q = next;
27
+ }
28
+
29
+ return done(0, q);
30
+ }
31
+ }
@@ -0,0 +1,36 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandBase, CommandContext} from "./Base.sol";
5
+ import {BALANCES, SETUP} from "../utils/Channels.sol";
6
+ import {BlockRef, RECIPIENT} from "../blocks/Schema.sol";
7
+ import {Blocks} from "../blocks/Readers.sol";
8
+ string constant NAME = "creditBalanceToAccount";
9
+
10
+ using Blocks for BlockRef;
11
+
12
+ abstract contract CreditBalanceToAccount is CommandBase {
13
+ uint internal immutable creditBalanceToAccountId = commandId(NAME);
14
+
15
+ constructor() {
16
+ emit Command(host, NAME, RECIPIENT, creditBalanceToAccountId, BALANCES, SETUP);
17
+ }
18
+
19
+ function creditAccount(bytes32 account, bytes32 asset, bytes32 meta, uint amount) internal virtual;
20
+
21
+ function creditBalanceToAccount(
22
+ CommandContext calldata c
23
+ ) external payable onlyCommand(creditBalanceToAccountId, c.target) returns (bytes memory) {
24
+ bytes32 to = Blocks.resolveRecipient(c.request, 0, c.request.length, c.account);
25
+ uint i = 0;
26
+ while (i < c.state.length) {
27
+ BlockRef memory ref = Blocks.from(c.state, i);
28
+ if (!ref.isBalance()) break;
29
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackBalance(c.state);
30
+ creditAccount(to, asset, meta, amount);
31
+ i = ref.end;
32
+ }
33
+
34
+ return done(0, i);
35
+ }
36
+ }
@@ -0,0 +1,44 @@
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, SETUP} from "../utils/Channels.sol";
6
+ import {AMOUNT, AMOUNT_KEY, BlockRef, Writer} from "../blocks/Schema.sol";
7
+ import {Blocks} from "../blocks/Readers.sol";
8
+ import {Writers} from "../blocks/Writers.sol";
9
+
10
+ string constant NAME = "debitAccountToBalance";
11
+
12
+ using Blocks for BlockRef;
13
+ using Writers for Writer;
14
+
15
+ abstract contract DebitAccountToBalance is CommandBase {
16
+ uint internal immutable debitAccountToBalanceId = commandId(NAME);
17
+
18
+ constructor() {
19
+ emit Command(host, NAME, AMOUNT, debitAccountToBalanceId, SETUP, BALANCES);
20
+ }
21
+
22
+ function debitAccount(bytes32 account, bytes32 asset, bytes32 meta, uint amount) internal virtual;
23
+
24
+ function debitAccountToBalance(bytes32 from, bytes calldata request) internal virtual returns (bytes memory) {
25
+ uint q = 0;
26
+ (Writer memory writer, uint end) = Writers.allocBalancesFrom(request, q, AMOUNT_KEY);
27
+
28
+ while (q < end) {
29
+ BlockRef memory ref = Blocks.from(request, q);
30
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackAmount(request);
31
+ debitAccount(from, asset, meta, amount);
32
+ writer.appendBalance(asset, meta, amount);
33
+ q = ref.end;
34
+ }
35
+
36
+ return writer.done();
37
+ }
38
+
39
+ function debitAccountToBalance(
40
+ CommandContext calldata c
41
+ ) external payable onlyCommand(debitAccountToBalanceId, c.target) returns (bytes memory) {
42
+ return debitAccountToBalance(c.account, c.request);
43
+ }
44
+ }
@@ -0,0 +1,46 @@
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, SETUP} from "../utils/Channels.sol";
6
+ import {AMOUNT, AMOUNT_KEY, BlockRef, Writer} from "../blocks/Schema.sol";
7
+ import {Blocks} from "../blocks/Readers.sol";
8
+ import {Writers} from "../blocks/Writers.sol";
9
+
10
+ string constant NAME = "deposit";
11
+
12
+ using Blocks for BlockRef;
13
+ using Writers for Writer;
14
+
15
+ // @dev Use `deposit` for externally sourced assets; use `debitAccountToBalance` for internal balance deductions.
16
+ abstract contract Deposit is CommandBase {
17
+ uint internal immutable depositId = commandId(NAME);
18
+
19
+ constructor() {
20
+ emit Command(host, NAME, AMOUNT, depositId, SETUP, BALANCES);
21
+ }
22
+
23
+ function deposit(
24
+ bytes32 account,
25
+ bytes32 asset,
26
+ bytes32 meta,
27
+ uint amount
28
+ ) internal virtual;
29
+
30
+ function deposit(
31
+ CommandContext calldata c
32
+ ) external payable onlyCommand(depositId, c.target) returns (bytes memory) {
33
+ uint q = 0;
34
+ (Writer memory writer, uint next) = Writers.allocBalancesFrom(c.request, q, AMOUNT_KEY);
35
+
36
+ while (q < next) {
37
+ BlockRef memory ref = Blocks.from(c.request, q);
38
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackAmount(c.request);
39
+ deposit(c.account, asset, meta, amount);
40
+ writer.appendBalance(asset, meta, amount);
41
+ q = ref.end;
42
+ }
43
+
44
+ return writer.done();
45
+ }
46
+ }
@@ -0,0 +1,37 @@
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 {BALANCE_KEY, Blocks, BlockRef, NODE, Writers, Writer} from "../Blocks.sol";
7
+ using Blocks for BlockRef;
8
+ using Writers for Writer;
9
+
10
+ string constant NAME = "fund";
11
+
12
+ // @dev Converts BALANCE state into CUSTODY state for a destination host.
13
+ abstract contract Fund is CommandBase {
14
+ uint internal immutable fundId = commandId(NAME);
15
+
16
+ constructor() {
17
+ emit Command(host, NAME, NODE, fundId, BALANCES, CUSTODIES);
18
+ }
19
+
20
+ function fund(uint host, bytes32 account, bytes32 asset, bytes32 meta, uint amount) internal virtual;
21
+
22
+ function fund(CommandContext calldata c) external payable onlyCommand(fundId, c.target) returns (bytes memory) {
23
+ uint h = Blocks.resolveNode(c.request, 0, c.request.length, 0);
24
+ uint i = 0;
25
+ (Writer memory writer, uint end) = Writers.allocCustodiesFrom(c.state, i, BALANCE_KEY);
26
+
27
+ while (i < end) {
28
+ BlockRef memory ref = Blocks.from(c.state, i);
29
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackBalance(c.state);
30
+ fund(h, c.account, asset, meta, amount);
31
+ writer.appendCustody(h, asset, meta, amount);
32
+ i = ref.end;
33
+ }
34
+
35
+ return writer.done();
36
+ }
37
+ }
@@ -0,0 +1,93 @@
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, BALANCE_KEY, CUSTODY_KEY, Data, DataRef, Blocks, BlockRef, Writers, Writer} from "../Blocks.sol";
7
+
8
+ string constant LFBTB = "liquidateFromBalanceToBalances";
9
+ string constant LFCTB = "liquidateFromCustodyToBalances";
10
+
11
+ using Blocks for BlockRef;
12
+ using Data for DataRef;
13
+ using Writers for Writer;
14
+
15
+ abstract contract LiquidateFromBalanceToBalances is CommandBase {
16
+ uint internal immutable liquidateFromBalanceToBalancesId = commandId(LFBTB);
17
+ uint private immutable outScale;
18
+ bool private immutable useRoute;
19
+
20
+ constructor(string memory maybeRoute, uint scaledRatio) {
21
+ outScale = scaledRatio;
22
+ useRoute = bytes(maybeRoute).length > 0;
23
+ emit Command(host, LFBTB, maybeRoute, liquidateFromBalanceToBalancesId, BALANCES, BALANCES);
24
+ }
25
+
26
+ // @dev `balance` is the offered liquidation repayment amount and may leave a returned remainder.
27
+ // `rawRoute` is zero-initialized and should be ignored when `maybeRoute` is empty.
28
+ function liquidateFromBalanceToBalances(
29
+ bytes32 account,
30
+ AssetAmount memory balance,
31
+ DataRef memory rawRoute,
32
+ Writer memory out
33
+ ) internal virtual;
34
+
35
+ function liquidateFromBalanceToBalances(
36
+ CommandContext calldata c
37
+ ) external payable onlyCommand(liquidateFromBalanceToBalancesId, c.target) returns (bytes memory) {
38
+ uint i = 0;
39
+ uint q = 0;
40
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.state, i, BALANCE_KEY, outScale);
41
+
42
+ while (i < end) {
43
+ DataRef memory route;
44
+ if (useRoute) (route, q) = Data.routeFrom(c.request, q);
45
+ BlockRef memory ref = Blocks.from(c.state, i);
46
+ AssetAmount memory balance = ref.toBalanceValue(c.state);
47
+ liquidateFromBalanceToBalances(c.account, balance, route, writer);
48
+ i = ref.end;
49
+ }
50
+
51
+ return writer.finish();
52
+ }
53
+ }
54
+
55
+ abstract contract LiquidateFromCustodyToBalances is CommandBase {
56
+ uint internal immutable liquidateFromCustodyToBalancesId = commandId(LFCTB);
57
+ uint private immutable outScale;
58
+ bool private immutable useRoute;
59
+
60
+ constructor(string memory maybeRoute, uint scaledRatio) {
61
+ outScale = scaledRatio;
62
+ useRoute = bytes(maybeRoute).length > 0;
63
+ emit Command(host, LFCTB, maybeRoute, liquidateFromCustodyToBalancesId, CUSTODIES, BALANCES);
64
+ }
65
+
66
+ // @dev `custody` is the offered liquidation repayment amount and may leave a returned remainder.
67
+ // `rawRoute` is zero-initialized and should be ignored when `maybeRoute` is empty.
68
+ function liquidateFromCustodyToBalances(
69
+ bytes32 account,
70
+ HostAmount memory custody,
71
+ DataRef memory rawRoute,
72
+ Writer memory out
73
+ ) internal virtual;
74
+
75
+ function liquidateFromCustodyToBalances(
76
+ CommandContext calldata c
77
+ ) external payable onlyCommand(liquidateFromCustodyToBalancesId, c.target) returns (bytes memory) {
78
+ uint i = 0;
79
+ uint q = 0;
80
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.state, i, CUSTODY_KEY, outScale);
81
+
82
+ while (i < end) {
83
+ DataRef memory route;
84
+ if (useRoute) (route, q) = Data.routeFrom(c.request, q);
85
+ BlockRef memory ref = Blocks.from(c.state, i);
86
+ HostAmount memory custody = ref.toCustodyValue(c.state);
87
+ liquidateFromCustodyToBalances(c.account, custody, route, writer);
88
+ i = ref.end;
89
+ }
90
+
91
+ return writer.finish();
92
+ }
93
+ }
@@ -0,0 +1,171 @@
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, BALANCE_KEY, CUSTODY_KEY, MINIMUM, DataPairRef} from "../blocks/Schema.sol";
7
+ import {BlockRef, Blocks, Data, DataRef, Writers, Writer} from "../Blocks.sol";
8
+ import {routeSchema1, routeSchema2} from "../utils/Utils.sol";
9
+
10
+ using Blocks for BlockRef;
11
+ using Data for DataRef;
12
+ using Writers for Writer;
13
+
14
+ string constant ALFCTB = "addLiquidityFromCustodiesToBalances";
15
+ string constant ALFBTB = "addLiquidityFromBalancesToBalances";
16
+ string constant RLFCTB = "removeLiquidityFromCustodyToBalances";
17
+ string constant RLFBTB = "removeLiquidityFromBalanceToBalances";
18
+
19
+ abstract contract AddLiquidityFromCustodiesToBalances is CommandBase {
20
+ uint internal immutable addLiquidityFromCustodiesToBalancesId = commandId(ALFCTB);
21
+ uint private immutable outScale;
22
+
23
+ constructor(string memory maybeRoute, uint scaledRatio) {
24
+ outScale = scaledRatio;
25
+ string memory schema = routeSchema1(maybeRoute, MINIMUM);
26
+ emit Command(host, ALFCTB, schema, addLiquidityFromCustodiesToBalancesId, CUSTODIES, BALANCES);
27
+ }
28
+
29
+ // @dev implementation extracts the requested minimum liquidity output from rawRoute.innerMinimum()
30
+ // and may append up to three balances per custody pair: two refunds plus the liquidity receipt.
31
+ function addLiquidityFromCustodiesToBalances(
32
+ bytes32 account,
33
+ DataPairRef memory rawCustodies,
34
+ DataRef memory rawRoute,
35
+ Writer memory out
36
+ ) internal virtual;
37
+
38
+ function addLiquidityFromCustodiesToBalances(
39
+ CommandContext calldata c
40
+ ) external payable onlyCommand(addLiquidityFromCustodiesToBalancesId, c.target) returns (bytes memory) {
41
+ uint i = 0;
42
+ uint q = 0;
43
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.state, i, CUSTODY_KEY, outScale);
44
+
45
+ while (i < end) {
46
+ DataRef memory route;
47
+ (route, q) = Data.routeFrom(c.request, q);
48
+ DataPairRef memory custodies;
49
+ (custodies, i) = Data.twoFrom(c.state, i);
50
+ addLiquidityFromCustodiesToBalances(c.account, custodies, route, writer);
51
+ }
52
+
53
+ return writer.finish();
54
+ }
55
+ }
56
+
57
+ abstract contract RemoveLiquidityFromCustodyToBalances is CommandBase {
58
+ uint internal immutable removeLiquidityFromCustodyToBalancesId = commandId(RLFCTB);
59
+ uint private immutable outScale;
60
+
61
+ constructor(string memory maybeRoute, uint scaledRatio) {
62
+ outScale = scaledRatio;
63
+ string memory schema = routeSchema2(maybeRoute, MINIMUM, MINIMUM);
64
+ emit Command(host, RLFCTB, schema, removeLiquidityFromCustodyToBalancesId, CUSTODIES, BALANCES);
65
+ }
66
+
67
+ // @dev implementation extracts requested minimum outputs from rawRoute and
68
+ // may append up to two balances per custody input when removing liquidity.
69
+ function removeLiquidityFromCustodyToBalances(
70
+ bytes32 account,
71
+ HostAmount memory custody,
72
+ DataRef memory rawRoute,
73
+ Writer memory out
74
+ ) internal virtual;
75
+
76
+ function removeLiquidityFromCustodyToBalances(
77
+ CommandContext calldata c
78
+ ) external payable onlyCommand(removeLiquidityFromCustodyToBalancesId, c.target) returns (bytes memory) {
79
+ uint i = 0;
80
+ uint q = 0;
81
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.state, i, CUSTODY_KEY, outScale);
82
+
83
+ while (i < end) {
84
+ DataRef memory route;
85
+ (route, q) = Data.routeFrom(c.request, q);
86
+ BlockRef memory ref = Blocks.from(c.state, i);
87
+ HostAmount memory custody = ref.toCustodyValue(c.state);
88
+ removeLiquidityFromCustodyToBalances(c.account, custody, route, writer);
89
+ i = ref.end;
90
+ }
91
+
92
+ return writer.finish();
93
+ }
94
+ }
95
+
96
+ abstract contract AddLiquidityFromBalancesToBalances is CommandBase {
97
+ uint internal immutable addLiquidityFromBalancesToBalancesId = commandId(ALFBTB);
98
+ uint private immutable outScale;
99
+
100
+ constructor(string memory maybeRoute, uint scaledRatio) {
101
+ outScale = scaledRatio;
102
+ string memory schema = routeSchema1(maybeRoute, MINIMUM);
103
+ emit Command(host, ALFBTB, schema, addLiquidityFromBalancesToBalancesId, BALANCES, BALANCES);
104
+ }
105
+
106
+ // @dev implementation extracts the requested minimum liquidity output from rawRoute.innerMinimum()
107
+ // and may append up to three balances per balance pair: two refunds plus the liquidity receipt.
108
+ function addLiquidityFromBalancesToBalances(
109
+ bytes32 account,
110
+ DataPairRef memory rawBalances,
111
+ DataRef memory rawRoute,
112
+ Writer memory out
113
+ ) internal virtual;
114
+
115
+ function addLiquidityFromBalancesToBalances(
116
+ CommandContext calldata c
117
+ ) external payable onlyCommand(addLiquidityFromBalancesToBalancesId, c.target) returns (bytes memory) {
118
+ uint i = 0;
119
+ uint q = 0;
120
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.state, i, BALANCE_KEY, outScale);
121
+
122
+ while (i < end) {
123
+ DataRef memory route;
124
+ (route, q) = Data.routeFrom(c.request, q);
125
+ DataPairRef memory balances;
126
+ (balances, i) = Data.twoFrom(c.state, i);
127
+ addLiquidityFromBalancesToBalances(c.account, balances, route, writer);
128
+ }
129
+
130
+ return writer.finish();
131
+ }
132
+ }
133
+
134
+ abstract contract RemoveLiquidityFromBalanceToBalances is CommandBase {
135
+ uint internal immutable removeLiquidityFromBalanceToBalancesId = commandId(RLFBTB);
136
+ uint private immutable outScale;
137
+
138
+ constructor(string memory maybeRoute, uint scaledRatio) {
139
+ outScale = scaledRatio;
140
+ string memory schema = routeSchema2(maybeRoute, MINIMUM, MINIMUM);
141
+ emit Command(host, RLFBTB, schema, removeLiquidityFromBalanceToBalancesId, BALANCES, BALANCES);
142
+ }
143
+
144
+ // @dev implementation extracts requested minimum outputs from rawRoute and
145
+ // may append up to two balances per balance input when removing liquidity.
146
+ function removeLiquidityFromBalanceToBalances(
147
+ bytes32 account,
148
+ AssetAmount memory balance,
149
+ DataRef memory rawRoute,
150
+ Writer memory out
151
+ ) internal virtual;
152
+
153
+ function removeLiquidityFromBalanceToBalances(
154
+ CommandContext calldata c
155
+ ) external payable onlyCommand(removeLiquidityFromBalanceToBalancesId, c.target) returns (bytes memory) {
156
+ uint i = 0;
157
+ uint q = 0;
158
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.state, i, BALANCE_KEY, outScale);
159
+
160
+ while (i < end) {
161
+ DataRef memory route;
162
+ (route, q) = Data.routeFrom(c.request, q);
163
+ BlockRef memory ref = Blocks.from(c.state, i);
164
+ AssetAmount memory balance = ref.toBalanceValue(c.state);
165
+ removeLiquidityFromBalanceToBalances(c.account, balance, route, writer);
166
+ i = ref.end;
167
+ }
168
+
169
+ return writer.finish();
170
+ }
171
+ }
@@ -0,0 +1,41 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandBase, CommandContext} from "./Base.sol";
5
+ import {BALANCES, SETUP} from "../utils/Channels.sol";
6
+ import {ROUTE_KEY} from "../Schema.sol";
7
+ import {Data, DataRef, Writers, Writer} from "../Blocks.sol";
8
+ using Writers for Writer;
9
+
10
+ string constant NAME = "mintToBalances";
11
+
12
+ abstract contract MintToBalances is CommandBase {
13
+ uint internal immutable mintToBalancesId = commandId(NAME);
14
+ uint private immutable outScale;
15
+
16
+ constructor(string memory route, uint scaledRatio) {
17
+ outScale = scaledRatio;
18
+ emit Command(host, NAME, route, mintToBalancesId, SETUP, BALANCES);
19
+ }
20
+
21
+ function mintToBalances(
22
+ bytes32 account,
23
+ DataRef memory rawRoute,
24
+ Writer memory out
25
+ ) internal virtual;
26
+
27
+ function mintToBalances(
28
+ CommandContext calldata c
29
+ ) external payable onlyCommand(mintToBalancesId, c.target) returns (bytes memory) {
30
+ uint q = 0;
31
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.request, q, ROUTE_KEY, outScale);
32
+
33
+ while (q < end) {
34
+ DataRef memory route;
35
+ (route, q) = Data.routeFrom(c.request, q);
36
+ mintToBalances(c.account, route, writer);
37
+ }
38
+
39
+ return writer.finish();
40
+ }
41
+ }
@@ -0,0 +1,54 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandBase, CommandContext} from "./Base.sol";
5
+ import {BlockRef, STEP, STEP_KEY} from "../blocks/Schema.sol";
6
+ import {Blocks} from "../blocks/Readers.sol";
7
+ import {isAdminAccount, InvalidAccount} from "../utils/Accounts.sol";
8
+ import {msgValue, useValue, ValueBudget} from "../utils/Value.sol";
9
+
10
+ using Blocks for BlockRef;
11
+
12
+ string constant NAME = "pipe";
13
+
14
+ abstract contract Pipe is CommandBase {
15
+ uint internal immutable pipeId = commandId(NAME);
16
+
17
+ constructor() {
18
+ emit Command(host, NAME, STEP, pipeId, 0, 0);
19
+ }
20
+
21
+ function dispatchStep(
22
+ uint target,
23
+ bytes32 account,
24
+ bytes memory state,
25
+ bytes calldata request,
26
+ uint value
27
+ ) internal virtual returns (bytes memory);
28
+
29
+ function pipe(
30
+ bytes32 account,
31
+ bytes memory state,
32
+ bytes calldata steps,
33
+ ValueBudget memory budget
34
+ ) internal returns (bytes memory) {
35
+ uint i = 0;
36
+ while (i < steps.length) {
37
+ BlockRef memory ref = Blocks.from(steps, i);
38
+ if (ref.key != STEP_KEY) break;
39
+ (uint target, uint value, bytes calldata request) = ref.unpackStep(steps);
40
+ uint spend = useValue(value, budget);
41
+ state = dispatchStep(target, account, state, request, spend);
42
+ i = ref.end;
43
+ }
44
+
45
+ return done(state, 0, i);
46
+ }
47
+
48
+ // Any unused value will not be credited back to the account using this path.
49
+ function pipe(CommandContext calldata c) external payable onlyCommand(pipeId, c.target) returns (bytes memory) {
50
+ if (isAdminAccount(c.account)) revert InvalidAccount();
51
+ ValueBudget memory budget = msgValue();
52
+ return pipe(c.account, c.state, c.request, budget);
53
+ }
54
+ }
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {CommandContext, CommandBase} from "./Base.sol";
5
+ import {CUSTODIES, SETUP} from "../utils/Channels.sol";
6
+ import {HostAmount, AMOUNT, AMOUNT_KEY, NODE} from "../blocks/Schema.sol";
7
+ import {Blocks, BlockRef, Writers, Writer} from "../Blocks.sol";
8
+ using Blocks for BlockRef;
9
+ using Writers for Writer;
10
+
11
+ string constant NAME = "provision";
12
+ string constant REQUEST = string.concat(AMOUNT, ">", NODE);
13
+
14
+ abstract contract Provision is CommandBase {
15
+ uint internal immutable provisionId = commandId(NAME);
16
+ uint private immutable outScale;
17
+
18
+ constructor(uint scaledRatio) {
19
+ outScale = scaledRatio;
20
+ emit Command(host, NAME, REQUEST, provisionId, SETUP, CUSTODIES);
21
+ }
22
+
23
+ function provision(
24
+ bytes32 account,
25
+ uint host,
26
+ bytes32 asset,
27
+ bytes32 meta,
28
+ uint amount,
29
+ Writer memory out
30
+ ) internal virtual;
31
+
32
+ function provision(
33
+ CommandContext calldata c
34
+ ) external payable onlyCommand(provisionId, c.target) returns (bytes memory) {
35
+ uint q = 0;
36
+ (Writer memory writer, uint end) = Writers.allocScaledCustodiesFrom(c.request, q, AMOUNT_KEY, outScale);
37
+
38
+ while (q < end) {
39
+ BlockRef memory ref = Blocks.from(c.request, q);
40
+ (bytes32 asset, bytes32 meta, uint amount) = ref.unpackAmount(c.request);
41
+ uint h = ref.innerNode(c.request);
42
+ provision(c.account, h, asset, meta, amount, writer);
43
+ q = ref.end;
44
+ }
45
+
46
+ return writer.finish();
47
+ }
48
+ }
@@ -0,0 +1,46 @@
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, SETUP} from "../utils/Channels.sol";
6
+ import {AssetAmount, AMOUNT, ROUTE_KEY, Data, DataRef, Writers, Writer} from "../Blocks.sol";
7
+ import {routeSchema1} from "../utils/Utils.sol";
8
+
9
+ string constant NAME = "reclaimToBalances";
10
+
11
+ using Data for DataRef;
12
+ using Writers for Writer;
13
+
14
+ abstract contract ReclaimToBalances is CommandBase {
15
+ uint internal immutable reclaimToBalancesId = commandId(NAME);
16
+ uint private immutable outScale;
17
+
18
+ constructor(string memory maybeRoute, uint scaledRatio) {
19
+ outScale = scaledRatio;
20
+ string memory schema = routeSchema1(maybeRoute, AMOUNT);
21
+ emit Command(host, NAME, schema, reclaimToBalancesId, SETUP, BALANCES);
22
+ }
23
+
24
+ function reclaimToBalances(
25
+ bytes32 account,
26
+ AssetAmount memory amount,
27
+ DataRef memory rawRoute,
28
+ Writer memory out
29
+ ) internal virtual;
30
+
31
+ function reclaimToBalances(
32
+ CommandContext calldata c
33
+ ) external payable onlyCommand(reclaimToBalancesId, c.target) returns (bytes memory) {
34
+ uint q = 0;
35
+ (Writer memory writer, uint end) = Writers.allocScaledBalancesFrom(c.request, q, ROUTE_KEY, outScale);
36
+
37
+ while (q < end) {
38
+ DataRef memory route;
39
+ (route, q) = Data.routeFrom(c.request, q);
40
+ AssetAmount memory value = route.innerAmountValue();
41
+ reclaimToBalances(c.account, value, route, writer);
42
+ }
43
+
44
+ return writer.finish();
45
+ }
46
+ }