@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.
- package/LICENSE +648 -0
- package/README.md +134 -0
- package/contracts/Blocks.sol +73 -0
- package/contracts/Commands.sol +47 -0
- package/contracts/Core.sol +10 -0
- package/contracts/Events.sol +18 -0
- package/contracts/Schema.sol +57 -0
- package/contracts/Utils.sol +105 -0
- package/contracts/blocks/Data.sol +646 -0
- package/contracts/blocks/Errors.sol +10 -0
- package/contracts/blocks/Mem.sol +122 -0
- package/contracts/blocks/Readers.sol +938 -0
- package/contracts/blocks/Schema.sol +148 -0
- package/contracts/blocks/Writers.sol +187 -0
- package/contracts/combinators/AmountToBalance.sol +26 -0
- package/contracts/combinators/AmountToCustody.sol +37 -0
- package/contracts/combinators/CustodyToBalance.sol +27 -0
- package/contracts/combinators/EachRoute.sol +19 -0
- package/contracts/combinators/MapBalance.sol +26 -0
- package/contracts/combinators/MapCustody.sol +26 -0
- package/contracts/combinators/RouteToBalance.sol +27 -0
- package/contracts/commands/Base.sol +39 -0
- package/contracts/commands/Borrow.sol +86 -0
- package/contracts/commands/Burn.sol +32 -0
- package/contracts/commands/Create.sol +31 -0
- package/contracts/commands/CreditTo.sol +36 -0
- package/contracts/commands/DebitFrom.sol +44 -0
- package/contracts/commands/Deposit.sol +46 -0
- package/contracts/commands/Fund.sol +37 -0
- package/contracts/commands/Liquidate.sol +93 -0
- package/contracts/commands/Liquidity.sol +171 -0
- package/contracts/commands/Mint.sol +41 -0
- package/contracts/commands/Pipe.sol +54 -0
- package/contracts/commands/Provision.sol +48 -0
- package/contracts/commands/Reclaim.sol +46 -0
- package/contracts/commands/Redeem.sol +93 -0
- package/contracts/commands/Remove.sol +31 -0
- package/contracts/commands/Repay.sol +93 -0
- package/contracts/commands/Settle.sol +32 -0
- package/contracts/commands/Stake.sol +114 -0
- package/contracts/commands/Supply.sol +32 -0
- package/contracts/commands/Swap.sol +86 -0
- package/contracts/commands/Transfer.sol +41 -0
- package/contracts/commands/Unstake.sol +49 -0
- package/contracts/commands/Withdraw.sol +37 -0
- package/contracts/commands/admin/Allocate.sol +33 -0
- package/contracts/commands/admin/AllowAssets.sol +34 -0
- package/contracts/commands/admin/Authorize.sol +32 -0
- package/contracts/commands/admin/DenyAssets.sol +34 -0
- package/contracts/commands/admin/Destroy.sol +26 -0
- package/contracts/commands/admin/Init.sol +26 -0
- package/contracts/commands/admin/Relocate.sol +32 -0
- package/contracts/commands/admin/Unauthorize.sol +32 -0
- package/contracts/core/Access.sol +49 -0
- package/contracts/core/Balances.sol +9 -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/Fastish.sol +14 -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/Withdraw.sol +14 -0
- package/contracts/interfaces/IHostDiscovery.sol +6 -0
- package/contracts/peer/AllowAssets.sol +31 -0
- package/contracts/peer/Base.sol +19 -0
- package/contracts/peer/DenyAssets.sol +31 -0
- package/contracts/peer/Pull.sol +30 -0
- package/contracts/peer/Push.sol +30 -0
- package/contracts/test/TestBlockHelper.sol +256 -0
- package/contracts/test/TestBorrowHost.sol +46 -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 +215 -0
- package/contracts/test/TestLiquidityHost.sol +149 -0
- package/contracts/test/TestMintHost.sol +40 -0
- package/contracts/test/TestPeerHost.sol +34 -0
- package/contracts/test/TestReclaimHost.sol +47 -0
- package/contracts/test/TestRejectEther.sol +8 -0
- package/contracts/test/TestRemoveHost.sol +26 -0
- package/contracts/test/TestSwapHost.sol +45 -0
- package/contracts/test/TestUtils.sol +180 -0
- package/contracts/test/TestValidator.sol +10 -0
- package/contracts/utils/Accounts.sol +42 -0
- package/contracts/utils/Assets.sol +71 -0
- package/contracts/utils/Channels.sol +9 -0
- package/contracts/utils/ECDSA.sol +36 -0
- package/contracts/utils/Ids.sol +75 -0
- package/contracts/utils/Layout.sol +20 -0
- package/contracts/utils/Strings.sol +16 -0
- package/contracts/utils/Utils.sol +117 -0
- package/contracts/utils/Value.sol +18 -0
- package/package.json +29 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
library ECDSA {
|
|
5
|
+
uint256 internal constant MALLEABILITY_THRESHOLD =
|
|
6
|
+
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;
|
|
7
|
+
|
|
8
|
+
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 digest) {
|
|
9
|
+
assembly ("memory-safe") {
|
|
10
|
+
mstore(0x00, "\x19Ethereum Signed Message:\n32")
|
|
11
|
+
mstore(0x1c, hash)
|
|
12
|
+
digest := keccak256(0x00, 0x3c)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal pure returns (address signer) {
|
|
17
|
+
if (signature.length != 65) return address(0);
|
|
18
|
+
|
|
19
|
+
bytes32 r;
|
|
20
|
+
bytes32 s;
|
|
21
|
+
uint8 v;
|
|
22
|
+
|
|
23
|
+
assembly ("memory-safe") {
|
|
24
|
+
let offset := signature.offset
|
|
25
|
+
r := calldataload(offset)
|
|
26
|
+
s := calldataload(add(offset, 0x20))
|
|
27
|
+
v := byte(0, calldataload(add(offset, 0x40)))
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (v < 27) v += 27;
|
|
31
|
+
if (v != 27 && v != 28) return address(0);
|
|
32
|
+
if (uint256(s) > MALLEABILITY_THRESHOLD) return address(0);
|
|
33
|
+
|
|
34
|
+
return ecrecover(hash, v, r, s);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {COMMAND, EVM32, HOST, NODE, PEER} from "./Layout.sol";
|
|
5
|
+
import {bytes32ToString} from "./Strings.sol";
|
|
6
|
+
import {isLocalFamily, matchesBase, toLocalBase} from "./Utils.sol";
|
|
7
|
+
|
|
8
|
+
error InvalidId();
|
|
9
|
+
|
|
10
|
+
uint24 constant NODE_FAMILY = (uint24(EVM32) << 8) | uint24(NODE);
|
|
11
|
+
uint32 constant HOST_PREFIX = (uint32(EVM32) << 16) | (uint32(NODE) << 8) | uint32(HOST);
|
|
12
|
+
uint32 constant COMMAND_PREFIX = (uint32(EVM32) << 16) | (uint32(NODE) << 8) | uint32(COMMAND);
|
|
13
|
+
uint32 constant PEER_PREFIX = (uint32(EVM32) << 16) | (uint32(NODE) << 8) | uint32(PEER);
|
|
14
|
+
string constant COMMAND_ARGS = "((uint256,bytes32,bytes,bytes))";
|
|
15
|
+
string constant PEER_ARGS = "(bytes)";
|
|
16
|
+
|
|
17
|
+
function isHost(uint id) pure returns (bool) {
|
|
18
|
+
return uint32(id >> 224) == HOST_PREFIX;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function isCommand(uint id) pure returns (bool) {
|
|
22
|
+
return uint32(id >> 224) == COMMAND_PREFIX;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function isPeer(uint id) pure returns (bool) {
|
|
26
|
+
return uint32(id >> 224) == PEER_PREFIX;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function toHostId(address addr) view returns (uint) {
|
|
30
|
+
return toLocalBase(HOST_PREFIX) | uint(uint160(addr));
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function toCommandSelector(string memory name) pure returns (bytes4) {
|
|
34
|
+
return bytes4(keccak256(bytes.concat(bytes(name), bytes(COMMAND_ARGS))));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toCommandSelector(bytes32 name) pure returns (bytes4) {
|
|
38
|
+
return toCommandSelector(bytes32ToString(name));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function toPeerSelector(string memory name) pure returns (bytes4) {
|
|
42
|
+
return bytes4(keccak256(bytes.concat(bytes(name), bytes(PEER_ARGS))));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function toCommandId(bytes4 selector, address addr) view returns (uint) {
|
|
46
|
+
uint id = toLocalBase(COMMAND_PREFIX) | uint(uint160(addr));
|
|
47
|
+
id |= uint(uint32(selector)) << 160;
|
|
48
|
+
return id;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function toPeerId(bytes4 selector, address addr) view returns (uint) {
|
|
52
|
+
uint id = toLocalBase(PEER_PREFIX) | uint(uint160(addr));
|
|
53
|
+
id |= uint(uint32(selector)) << 160;
|
|
54
|
+
return id;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function ensureHost(uint id, address addr) view returns (uint) {
|
|
58
|
+
if (id != toHostId(addr)) revert InvalidId();
|
|
59
|
+
return id;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function ensureCommand(uint id) pure returns (uint cid) {
|
|
63
|
+
if (!isCommand(id)) revert InvalidId();
|
|
64
|
+
return id;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function localNodeAddr(uint node) view returns (address) {
|
|
68
|
+
if (!isLocalFamily(node, NODE_FAMILY)) revert InvalidId();
|
|
69
|
+
return address(uint160(node));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function localHostAddr(uint host) view returns (address) {
|
|
73
|
+
if (!matchesBase(bytes32(host), toLocalBase(HOST_PREFIX))) revert InvalidId();
|
|
74
|
+
return address(uint160(host));
|
|
75
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
uint16 constant EVM32 = 0x2001;
|
|
5
|
+
uint16 constant EVM64 = 0x4001;
|
|
6
|
+
|
|
7
|
+
uint8 constant ACCOUNT = 0x01;
|
|
8
|
+
uint8 constant NODE = 0x02;
|
|
9
|
+
uint8 constant ASSET = 0x03;
|
|
10
|
+
|
|
11
|
+
uint8 constant ADMIN = 0x01;
|
|
12
|
+
uint8 constant USER = 0x02;
|
|
13
|
+
|
|
14
|
+
uint8 constant HOST = 0x01;
|
|
15
|
+
uint8 constant COMMAND = 0x02;
|
|
16
|
+
uint8 constant PEER = 0x03;
|
|
17
|
+
|
|
18
|
+
uint8 constant VALUE = 0x01;
|
|
19
|
+
uint8 constant ERC20 = 0x02;
|
|
20
|
+
uint8 constant ERC721 = 0x03;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
function bytes32ToString(bytes32 value) pure returns (string memory result) {
|
|
5
|
+
uint len;
|
|
6
|
+
while (len < 32 && value[len] != 0) {
|
|
7
|
+
unchecked {
|
|
8
|
+
++len;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
result = new string(len);
|
|
13
|
+
assembly ("memory-safe") {
|
|
14
|
+
mstore(add(result, 0x20), value)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {ROUTE_EMPTY} from "../blocks/Schema.sol";
|
|
5
|
+
|
|
6
|
+
uint16 constant MAX_BPS = 10_000;
|
|
7
|
+
|
|
8
|
+
error ValueOverflow();
|
|
9
|
+
|
|
10
|
+
function max8(uint value) pure returns (uint) {
|
|
11
|
+
if (value > type(uint8).max) {
|
|
12
|
+
revert ValueOverflow();
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function max16(uint value) pure returns (uint) {
|
|
18
|
+
if (value > type(uint16).max) {
|
|
19
|
+
revert ValueOverflow();
|
|
20
|
+
}
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function max24(uint value) pure returns (uint) {
|
|
25
|
+
if (value > type(uint24).max) {
|
|
26
|
+
revert ValueOverflow();
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function max32(uint value) pure returns (uint) {
|
|
32
|
+
if (value > type(uint32).max) {
|
|
33
|
+
revert ValueOverflow();
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function max40(uint value) pure returns (uint) {
|
|
39
|
+
if (value > type(uint40).max) {
|
|
40
|
+
revert ValueOverflow();
|
|
41
|
+
}
|
|
42
|
+
return value;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function max64(uint value) pure returns (uint) {
|
|
46
|
+
if (value > type(uint64).max) {
|
|
47
|
+
revert ValueOverflow();
|
|
48
|
+
}
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function max96(uint value) pure returns (uint) {
|
|
53
|
+
if (value > type(uint96).max) {
|
|
54
|
+
revert ValueOverflow();
|
|
55
|
+
}
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function max128(uint value) pure returns (uint) {
|
|
60
|
+
if (value > type(uint128).max) {
|
|
61
|
+
revert ValueOverflow();
|
|
62
|
+
}
|
|
63
|
+
return value;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function max160(uint value) pure returns (uint) {
|
|
67
|
+
if (value > type(uint160).max) {
|
|
68
|
+
revert ValueOverflow();
|
|
69
|
+
}
|
|
70
|
+
return value;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function toLocalBase(uint32 prefix) view returns (uint) {
|
|
74
|
+
return (uint(prefix) << 224) | (uint(max32(block.chainid)) << 192);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function toLocalFamily(uint24 family) view returns (uint) {
|
|
78
|
+
return (uint(family) << 232) | (uint(max32(block.chainid)) << 192);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function toUnspecifiedBase(uint32 prefix) pure returns (uint) {
|
|
82
|
+
return uint(prefix) << 224;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function isFamily(uint value, uint24 family) pure returns (bool) {
|
|
86
|
+
return uint24(value >> 232) == family;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function isLocal(uint value) view returns (bool) {
|
|
90
|
+
return uint32(value >> 192) == block.chainid;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function isLocalFamily(uint value, uint24 family) view returns (bool) {
|
|
94
|
+
return isFamily(value, family) && isLocal(value);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function matchesBase(bytes32 value, uint base) pure returns (bool) {
|
|
98
|
+
return uint64(uint(value) >> 192) == uint64(base >> 192);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function applyBps(uint amount, uint16 bps) pure returns (uint) {
|
|
102
|
+
if (amount == 0 || bps == 0) return 0;
|
|
103
|
+
return (amount * bps) / MAX_BPS;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function beforeBps(uint amount, uint16 bps) pure returns (uint) {
|
|
107
|
+
if (amount == 0 || bps == 0) return 0;
|
|
108
|
+
return (amount * MAX_BPS) / (MAX_BPS + bps);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function routeSchema1(string memory maybeRoute, string memory a) pure returns (string memory) {
|
|
112
|
+
return string.concat(bytes(maybeRoute).length == 0 ? ROUTE_EMPTY : maybeRoute, ">", a);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function routeSchema2(string memory maybeRoute, string memory a, string memory b) pure returns (string memory) {
|
|
116
|
+
return string.concat(bytes(maybeRoute).length == 0 ? ROUTE_EMPTY : maybeRoute, ">", a, ">", b);
|
|
117
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
struct ValueBudget {
|
|
5
|
+
uint remaining;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
error InsufficientValue();
|
|
9
|
+
|
|
10
|
+
function msgValue() view returns (ValueBudget memory) {
|
|
11
|
+
return ValueBudget({remaining: msg.value});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function useValue(uint amount, ValueBudget memory budget) pure returns (uint) {
|
|
15
|
+
if (amount > budget.remaining) revert InsufficientValue();
|
|
16
|
+
budget.remaining -= amount;
|
|
17
|
+
return amount;
|
|
18
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fastish/contracts",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Solidity contracts and protocol building blocks for Fastish hosts and commands.",
|
|
5
|
+
"private": false,
|
|
6
|
+
"license": "GPL-3.0-only",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"files": [
|
|
9
|
+
"contracts/**/*.sol",
|
|
10
|
+
"README.md",
|
|
11
|
+
"LICENSE"
|
|
12
|
+
],
|
|
13
|
+
"publishConfig": {
|
|
14
|
+
"access": "public"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"compile": "hardhat compile",
|
|
18
|
+
"test": "hardhat test",
|
|
19
|
+
"prepublishOnly": "npm test"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@nomicfoundation/hardhat-mocha": "^3.0.13",
|
|
23
|
+
"chai": "^6.2.2",
|
|
24
|
+
"ethers": "^6.16.0",
|
|
25
|
+
"hardhat": "^3.1.7",
|
|
26
|
+
"mocha": "^11.7.5",
|
|
27
|
+
"typescript": "~5.8.0"
|
|
28
|
+
}
|
|
29
|
+
}
|