@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.
- package/LICENSE +648 -0
- package/README.md +135 -0
- package/contracts/Blocks.sol +9 -0
- package/contracts/Commands.sol +41 -0
- package/contracts/Core.sol +10 -0
- package/contracts/Events.sol +18 -0
- package/contracts/Utils.sol +12 -0
- package/contracts/blocks/Blocks.sol +818 -0
- package/contracts/blocks/Keys.sol +24 -0
- package/contracts/blocks/Mem.sol +129 -0
- package/contracts/blocks/Schema.sol +105 -0
- package/contracts/blocks/Writers.sol +209 -0
- package/contracts/combinators/AmountToBalance.sol +25 -0
- package/contracts/combinators/AmountToCustody.sol +36 -0
- package/contracts/combinators/CustodyToBalance.sol +25 -0
- package/contracts/combinators/EachRoute.sol +18 -0
- package/contracts/combinators/MapBalance.sol +25 -0
- package/contracts/combinators/MapCustody.sol +25 -0
- package/contracts/combinators/RouteToBalance.sol +27 -0
- package/contracts/commands/Base.sol +40 -0
- package/contracts/commands/Borrow.sol +89 -0
- package/contracts/commands/Burn.sol +33 -0
- package/contracts/commands/Create.sol +32 -0
- package/contracts/commands/Credit.sol +36 -0
- package/contracts/commands/Debit.sol +46 -0
- package/contracts/commands/Deposit.sol +45 -0
- package/contracts/commands/Liquidate.sol +101 -0
- package/contracts/commands/Liquidity.sol +179 -0
- package/contracts/commands/Mint.sol +42 -0
- package/contracts/commands/Pipe.sol +55 -0
- package/contracts/commands/Provision.sol +73 -0
- package/contracts/commands/Reclaim.sol +48 -0
- package/contracts/commands/Redeem.sol +101 -0
- package/contracts/commands/Remove.sol +32 -0
- package/contracts/commands/Repay.sol +101 -0
- package/contracts/commands/Settle.sol +32 -0
- package/contracts/commands/Stake.sol +121 -0
- package/contracts/commands/Supply.sol +33 -0
- package/contracts/commands/Swap.sol +88 -0
- package/contracts/commands/Transfer.sol +44 -0
- package/contracts/commands/Unstake.sol +49 -0
- package/contracts/commands/Withdraw.sol +37 -0
- package/contracts/commands/admin/Allocate.sol +32 -0
- package/contracts/commands/admin/AllowAssets.sol +34 -0
- package/contracts/commands/admin/Authorize.sol +30 -0
- package/contracts/commands/admin/DenyAssets.sol +34 -0
- package/contracts/commands/admin/Destroy.sol +27 -0
- package/contracts/commands/admin/Init.sol +26 -0
- package/contracts/commands/admin/Relocate.sol +30 -0
- package/contracts/commands/admin/Unauthorize.sol +30 -0
- package/contracts/core/Access.sol +50 -0
- package/contracts/core/Balances.sol +23 -0
- package/contracts/core/Host.sol +25 -0
- package/contracts/core/Operation.sol +32 -0
- package/contracts/core/Validator.sol +31 -0
- package/contracts/events/Access.sol +14 -0
- package/contracts/events/Asset.sol +14 -0
- package/contracts/events/Balance.sol +14 -0
- package/contracts/events/Collateral.sol +15 -0
- package/contracts/events/Command.sol +14 -0
- package/contracts/events/Debt.sol +15 -0
- package/contracts/events/Deposit.sol +14 -0
- package/contracts/events/Emitter.sol +7 -0
- package/contracts/events/Governed.sol +14 -0
- package/contracts/events/HostAnnounced.sol +14 -0
- package/contracts/events/Listing.sol +14 -0
- package/contracts/events/Peer.sol +14 -0
- package/contracts/events/Quote.sol +14 -0
- package/contracts/events/RootZero.sol +14 -0
- package/contracts/events/Withdraw.sol +14 -0
- package/contracts/interfaces/IHostDiscovery.sol +6 -0
- package/contracts/peer/AllowAssets.sol +30 -0
- package/contracts/peer/Base.sol +17 -0
- package/contracts/peer/DenyAssets.sol +30 -0
- package/contracts/peer/Pull.sol +30 -0
- package/contracts/peer/Push.sol +30 -0
- package/contracts/test/TestBlockHelper.sol +261 -0
- package/contracts/test/TestBorrowHost.sol +47 -0
- package/contracts/test/TestBurnHost.sol +28 -0
- package/contracts/test/TestCreateHost.sol +26 -0
- package/contracts/test/TestDiscovery.sol +6 -0
- package/contracts/test/TestECDSA.sol +16 -0
- package/contracts/test/TestHost.sol +199 -0
- package/contracts/test/TestLiquidityHost.sol +145 -0
- package/contracts/test/TestMintHost.sol +40 -0
- package/contracts/test/TestPeerHost.sol +34 -0
- package/contracts/test/TestReclaimHost.sol +48 -0
- package/contracts/test/TestRejectEther.sol +8 -0
- package/contracts/test/TestRemoveHost.sol +26 -0
- package/contracts/test/TestSwapHost.sol +44 -0
- package/contracts/test/TestUtils.sol +169 -0
- package/contracts/test/TestValidator.sol +10 -0
- package/contracts/utils/Accounts.sol +40 -0
- package/contracts/utils/Assets.sol +76 -0
- package/contracts/utils/Channels.sol +11 -0
- package/contracts/utils/ECDSA.sol +36 -0
- package/contracts/utils/Ids.sol +75 -0
- package/contracts/utils/Layout.sol +22 -0
- package/contracts/utils/Utils.sol +126 -0
- package/contracts/utils/Value.sol +20 -0
- 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
|
+
}
|