@latticexyz/cli 0.10.0 → 0.12.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/dist/commands/bulkupload.js +45 -0
- package/dist/commands/deploy.js +2 -2
- package/package.json +12 -9
- package/src/commands/bulkupload.ts +44 -0
- package/src/commands/call-system.ts +62 -0
- package/src/commands/create.ts +54 -0
- package/src/commands/deploy.ts +483 -0
- package/src/commands/diamond-abi.ts +58 -0
- package/src/commands/hello.ts +23 -0
- package/src/commands/sync-art.ts +47 -0
- package/src/commands/system-types.ts +98 -0
- package/src/commands/trace.ts +69 -0
- package/src/contracts/BulkUpload.sol +183 -0
- package/src/contracts/Cheats.sol +320 -0
- package/src/index.ts +12 -0
- package/src/utils.ts +69 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import glob from "glob";
|
|
3
|
+
import type { CommandBuilder } from "yargs";
|
|
4
|
+
import { deferred, extractIdFromFile } from "../utils";
|
|
5
|
+
|
|
6
|
+
type Options = Record<string, never>;
|
|
7
|
+
|
|
8
|
+
export const command = "system-types";
|
|
9
|
+
export const desc =
|
|
10
|
+
"Generates system type file. Note: assumes ABIs of all systems in ./abi and typechain generated types in ./types/ethers-contracts";
|
|
11
|
+
|
|
12
|
+
export const builder: CommandBuilder<Options, Options> = (yargs) =>
|
|
13
|
+
yargs.options({
|
|
14
|
+
include: { type: "array" },
|
|
15
|
+
exclude: { type: "array" },
|
|
16
|
+
out: { type: "string" },
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const handler = async (): Promise<void> => {
|
|
20
|
+
const wd = process.cwd();
|
|
21
|
+
let abis: string[] = [];
|
|
22
|
+
let systems: string[] = [];
|
|
23
|
+
let ids: string[] = [];
|
|
24
|
+
let typePaths: string[] = [];
|
|
25
|
+
|
|
26
|
+
const systemsPath = `${wd}/src/systems/*.sol`;
|
|
27
|
+
|
|
28
|
+
const [resolve, , promise] = deferred<void>();
|
|
29
|
+
glob(systemsPath, {}, (_, matches) => {
|
|
30
|
+
systems = matches.map((path) => {
|
|
31
|
+
const fragments = path.split("/");
|
|
32
|
+
return fragments[fragments.length - 1].split(".sol")[0];
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
ids = matches.map((path, index) => {
|
|
36
|
+
const id = extractIdFromFile(path);
|
|
37
|
+
if (!id) {
|
|
38
|
+
console.log("Path:", path);
|
|
39
|
+
console.log("ID:", id);
|
|
40
|
+
throw new Error(
|
|
41
|
+
"No ID found for" +
|
|
42
|
+
matches[index] +
|
|
43
|
+
". Make sure your system source file includes a ID definition (uint256 constant ID = uint256(keccak256(<ID>));)"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
return id;
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
abis = systems.map((system) => `../abi/${system}.json`);
|
|
50
|
+
|
|
51
|
+
typePaths = systems.map((system) => `./ethers-contracts/${system}.ts`);
|
|
52
|
+
|
|
53
|
+
resolve();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Make the callback synchronous
|
|
57
|
+
await promise;
|
|
58
|
+
|
|
59
|
+
console.log("Matches", systems);
|
|
60
|
+
console.log("Solidity", ids);
|
|
61
|
+
console.log("Type paths", typePaths);
|
|
62
|
+
console.log("ABIs", abis);
|
|
63
|
+
|
|
64
|
+
const SystemMappings = `// Autogenerated using mud system-types
|
|
65
|
+
export const systemToId = {
|
|
66
|
+
${systems.map((system, index) => ` ${system}: "${ids[index]}",`).join("\n")}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const idToSystem = {
|
|
70
|
+
${ids.map((id, index) => ` "${id}": "${systems[index]}",`).join("\n")}
|
|
71
|
+
};
|
|
72
|
+
`;
|
|
73
|
+
|
|
74
|
+
const SystemTypes = `// Autogenerated using mud system-types
|
|
75
|
+
${typePaths.map((path, index) => `import { ${systems[index]} } from "${path.replace(".ts", "")}";`).join("\n")}
|
|
76
|
+
|
|
77
|
+
export type SystemTypes = {
|
|
78
|
+
${systems.map((system, index) => ` "${ids[index]}": ${system};`).join("\n")}
|
|
79
|
+
};
|
|
80
|
+
`;
|
|
81
|
+
|
|
82
|
+
const SystemAbis = `// Autogenerated using mud system-types
|
|
83
|
+
${abis.map((path, index) => `import ${systems[index]} from "${path}";`).join("\n")}
|
|
84
|
+
|
|
85
|
+
export const SystemAbis = {
|
|
86
|
+
${systems.map((system, index) => ` "${ids[index]}": ${system}.abi,`).join("\n")}
|
|
87
|
+
};
|
|
88
|
+
`;
|
|
89
|
+
|
|
90
|
+
console.log("Generating files:");
|
|
91
|
+
console.log("SystemTypes.ts", SystemTypes);
|
|
92
|
+
console.log("SystemAbis.mts", SystemAbis);
|
|
93
|
+
console.log("SystemMappings.ts", SystemMappings);
|
|
94
|
+
|
|
95
|
+
fs.writeFileSync("./types/SystemTypes.ts", SystemTypes);
|
|
96
|
+
fs.writeFileSync("./types/SystemAbis.mts", SystemAbis);
|
|
97
|
+
fs.writeFileSync("./types/SystemMappings.ts", SystemMappings);
|
|
98
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Arguments, CommandBuilder } from "yargs";
|
|
2
|
+
import { execLog, extractIdFromFile, keccak256 } from "../utils";
|
|
3
|
+
import { readFileSync } from "fs";
|
|
4
|
+
import { Contract } from "ethers";
|
|
5
|
+
import { JsonRpcProvider } from "@ethersproject/providers";
|
|
6
|
+
import { abi as WorldAbi } from "@latticexyz/solecs/abi/World.json";
|
|
7
|
+
|
|
8
|
+
type Options = {
|
|
9
|
+
config?: string;
|
|
10
|
+
world: string;
|
|
11
|
+
tx: string;
|
|
12
|
+
rpc?: string;
|
|
13
|
+
debug?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const command = "trace";
|
|
17
|
+
export const desc = "Display the trace of a transaction";
|
|
18
|
+
|
|
19
|
+
export const builder: CommandBuilder<Options, Options> = (yargs) =>
|
|
20
|
+
yargs.options({
|
|
21
|
+
config: { type: "string", description: "path to mud deploy config (deploy.json)" },
|
|
22
|
+
world: { type: "string", required: true, description: "world contract address" },
|
|
23
|
+
tx: { type: "string", required: true, description: "tx hash to replay" },
|
|
24
|
+
rpc: { type: "string", description: "json rpc endpoint, defaults to http://localhost:8545" },
|
|
25
|
+
debug: { type: "boolean", description: "open debugger" },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export const handler = async (argv: Arguments<Options>): Promise<void> => {
|
|
29
|
+
const { config, world, rpc, tx, debug } = argv;
|
|
30
|
+
const wd = process.cwd();
|
|
31
|
+
const deployData = config && JSON.parse(readFileSync(config, { encoding: "utf8" }));
|
|
32
|
+
const labels = [];
|
|
33
|
+
|
|
34
|
+
const provider = new JsonRpcProvider(rpc || "http://localhost:8545");
|
|
35
|
+
const World = new Contract(world, WorldAbi, provider);
|
|
36
|
+
|
|
37
|
+
if (deployData) {
|
|
38
|
+
// Create component labels
|
|
39
|
+
const componentPromises = deployData.components.map(async (component: string) => {
|
|
40
|
+
const path = `${wd}/src/components/${component}.sol`;
|
|
41
|
+
const id = extractIdFromFile(path);
|
|
42
|
+
if (!id) return;
|
|
43
|
+
const address = await World.getComponent(keccak256(id));
|
|
44
|
+
return [component, address];
|
|
45
|
+
});
|
|
46
|
+
// Create system labels
|
|
47
|
+
const systemPromises = deployData.systems.map(async (system: { name: string }) => {
|
|
48
|
+
const path = `${wd}/src/systems/${system.name}.sol`;
|
|
49
|
+
const id = extractIdFromFile(path);
|
|
50
|
+
if (!id) return;
|
|
51
|
+
const address = await World.getSystemAddress(keccak256(id));
|
|
52
|
+
return [system.name, address];
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const components = await Promise.all(componentPromises);
|
|
56
|
+
const systems = await Promise.all(systemPromises);
|
|
57
|
+
|
|
58
|
+
labels.push(...components, ...systems);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
await execLog("cast", [
|
|
62
|
+
"run",
|
|
63
|
+
...labels.map((label) => ["--label", `${label[1]}:${label[0]}`]).flat(),
|
|
64
|
+
...(debug ? ["--debug"] : []),
|
|
65
|
+
`${tx}`,
|
|
66
|
+
]);
|
|
67
|
+
|
|
68
|
+
process.exit(0);
|
|
69
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Unlicense
|
|
2
|
+
pragma solidity >=0.8.0;
|
|
3
|
+
|
|
4
|
+
import "ds-test/test.sol";
|
|
5
|
+
import {console} from "forge-std/console.sol";
|
|
6
|
+
import {Cheats} from "./Cheats.sol";
|
|
7
|
+
import {BulkSetStateSystem, ID as BulkSetStateSystemID, ECSEvent} from "std-contracts/systems/BulkSetStateSystem.sol";
|
|
8
|
+
import {World} from "solecs/World.sol";
|
|
9
|
+
import {System} from "solecs/System.sol";
|
|
10
|
+
import {getAddressById} from "solecs/utils.sol";
|
|
11
|
+
import {Set} from "solecs/Set.sol";
|
|
12
|
+
|
|
13
|
+
struct ParsedState {
|
|
14
|
+
string[] componentIds;
|
|
15
|
+
string[] entities;
|
|
16
|
+
ParsedECSEvent[] state;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
struct ParsedECSEvent {
|
|
20
|
+
uint8 component;
|
|
21
|
+
uint32 entity;
|
|
22
|
+
string value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
struct State {
|
|
26
|
+
uint256[] componentIds;
|
|
27
|
+
uint256[] entities;
|
|
28
|
+
ECSEvent[] state;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Usage:
|
|
33
|
+
* forge script --sig "run(string, address)" --rpc-url http://localhost:8545 src/contracts/BulkUpload.sol:BulkUpload path/to/ecs-map-test.json <WORLD_ADDRESS>
|
|
34
|
+
*/
|
|
35
|
+
contract BulkUpload is DSTest {
|
|
36
|
+
Cheats internal immutable vm = Cheats(HEVM_ADDRESS);
|
|
37
|
+
|
|
38
|
+
function run(
|
|
39
|
+
string memory path,
|
|
40
|
+
address worldAddress,
|
|
41
|
+
uint256 eventsPerTx
|
|
42
|
+
) public {
|
|
43
|
+
vm.startBroadcast();
|
|
44
|
+
|
|
45
|
+
// Read JSON
|
|
46
|
+
console.log(path);
|
|
47
|
+
string memory json = vm.readFile(path);
|
|
48
|
+
|
|
49
|
+
console.log(worldAddress);
|
|
50
|
+
|
|
51
|
+
// Parse JSON
|
|
52
|
+
ParsedState memory parsedState = abi.decode(vm.parseJson(json), (ParsedState));
|
|
53
|
+
|
|
54
|
+
// Convert component ids
|
|
55
|
+
uint256[] memory componentIds = new uint256[](parsedState.componentIds.length);
|
|
56
|
+
for (uint256 i; i < componentIds.length; i++) {
|
|
57
|
+
componentIds[i] = hexToUint256(parsedState.componentIds[i]);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Convert entitiy ids
|
|
61
|
+
uint256[] memory entities = new uint256[](parsedState.entities.length);
|
|
62
|
+
for (uint256 i; i < entities.length; i++) {
|
|
63
|
+
entities[i] = hexToUint256(parsedState.entities[i]);
|
|
64
|
+
}
|
|
65
|
+
World world = World(worldAddress);
|
|
66
|
+
System bulkSetStateSystem = System(getAddressById(world.systems(), BulkSetStateSystemID));
|
|
67
|
+
|
|
68
|
+
// Convert state
|
|
69
|
+
ECSEvent[] memory allEvents = new ECSEvent[](parsedState.state.length);
|
|
70
|
+
for (uint256 i; i < parsedState.state.length; i++) {
|
|
71
|
+
ParsedECSEvent memory p = parsedState.state[i];
|
|
72
|
+
|
|
73
|
+
// Convert value hex string to bytes
|
|
74
|
+
bytes memory value = hexToBytes(substring(p.value, 2, bytes(p.value).length));
|
|
75
|
+
allEvents[i] = ECSEvent(p.component, p.entity, value);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
uint256 numTxs = allEvents.length / eventsPerTx;
|
|
79
|
+
|
|
80
|
+
for (uint256 i = 0; i < numTxs; i++) {
|
|
81
|
+
ECSEvent[] memory events = new ECSEvent[](eventsPerTx);
|
|
82
|
+
for (uint256 j = 0; j < eventsPerTx; j++) {
|
|
83
|
+
events[j] = allEvents[i * eventsPerTx + j];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
(uint256[] memory newEntities, ECSEvent[] memory newEvents) = transformEventsToOnlyUseNeededEntities(
|
|
87
|
+
entities,
|
|
88
|
+
events
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
bulkSetStateSystem.execute(abi.encode(componentIds, newEntities, newEvents));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// overflow tx
|
|
95
|
+
uint256 overflowEventCount = allEvents.length - numTxs * eventsPerTx;
|
|
96
|
+
|
|
97
|
+
ECSEvent[] memory overflowEvents = new ECSEvent[](overflowEventCount);
|
|
98
|
+
for (uint256 j = 0; j < overflowEventCount; j++) {
|
|
99
|
+
overflowEvents[j] = allEvents[numTxs * eventsPerTx + j];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
(
|
|
103
|
+
uint256[] memory newOverflowEntities,
|
|
104
|
+
ECSEvent[] memory newOverflowEvents
|
|
105
|
+
) = transformEventsToOnlyUseNeededEntities(entities, overflowEvents);
|
|
106
|
+
|
|
107
|
+
bulkSetStateSystem.execute(abi.encode(componentIds, newOverflowEntities, newOverflowEvents));
|
|
108
|
+
|
|
109
|
+
vm.stopBroadcast();
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function transformEventsToOnlyUseNeededEntities(uint256[] memory entities, ECSEvent[] memory events)
|
|
114
|
+
returns (uint256[] memory, ECSEvent[] memory)
|
|
115
|
+
{
|
|
116
|
+
Set uniqueEntityIndices = new Set();
|
|
117
|
+
|
|
118
|
+
// Find unique entity indices
|
|
119
|
+
for (uint256 i = 0; i < events.length; i++) {
|
|
120
|
+
ECSEvent memory e = events[i];
|
|
121
|
+
|
|
122
|
+
uniqueEntityIndices.add(e.entity);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Grab the Entity IDs from the big entities array and put them into our new array
|
|
126
|
+
uint256[] memory relevantEntities = new uint256[](uniqueEntityIndices.size());
|
|
127
|
+
for (uint256 i = 0; i < uniqueEntityIndices.size(); i++) {
|
|
128
|
+
relevantEntities[i] = entities[uniqueEntityIndices.getItems()[i]];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Re-assign event entity indices to point to our new array
|
|
132
|
+
for (uint256 i = 0; i < events.length; i++) {
|
|
133
|
+
(, uint256 index) = uniqueEntityIndices.getIndex(events[i].entity);
|
|
134
|
+
events[i].entity = uint32(index);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return (relevantEntities, events);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function hexToUint8(bytes1 b) pure returns (uint8 res) {
|
|
141
|
+
if (b >= "0" && b <= "9") {
|
|
142
|
+
return uint8(b) - uint8(bytes1("0"));
|
|
143
|
+
} else if (b >= "A" && b <= "F") {
|
|
144
|
+
return 10 + uint8(b) - uint8(bytes1("A"));
|
|
145
|
+
} else if (b >= "a" && b <= "f") {
|
|
146
|
+
return 10 + uint8(b) - uint8(bytes1("a"));
|
|
147
|
+
}
|
|
148
|
+
return uint8(b); // or return error ...
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function hexToUint256(string memory str) pure returns (uint256 value) {
|
|
152
|
+
bytes memory b = bytes(str);
|
|
153
|
+
uint256 number = 0;
|
|
154
|
+
for (uint256 i = 0; i < b.length; i++) {
|
|
155
|
+
number = number << 4; // or number = number * 16
|
|
156
|
+
number |= hexToUint8(b[i]); // or number += numberFromAscII(b[i]);
|
|
157
|
+
}
|
|
158
|
+
return number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Convert an hexadecimal string to raw bytes
|
|
162
|
+
function hexToBytes(string memory s) pure returns (bytes memory) {
|
|
163
|
+
bytes memory ss = bytes(s);
|
|
164
|
+
require(ss.length % 2 == 0); // length must be even
|
|
165
|
+
bytes memory r = new bytes(ss.length / 2);
|
|
166
|
+
for (uint256 i = 0; i < ss.length / 2; ++i) {
|
|
167
|
+
r[i] = bytes1(hexToUint8(ss[2 * i]) * 16 + hexToUint8(ss[2 * i + 1]));
|
|
168
|
+
}
|
|
169
|
+
return r;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function substring(
|
|
173
|
+
string memory str,
|
|
174
|
+
uint256 start,
|
|
175
|
+
uint256 end
|
|
176
|
+
) pure returns (string memory) {
|
|
177
|
+
bytes memory strBytes = bytes(str);
|
|
178
|
+
bytes memory result = new bytes(end - start);
|
|
179
|
+
for (uint256 i = start; i < end; i++) {
|
|
180
|
+
result[i - start] = strBytes[i];
|
|
181
|
+
}
|
|
182
|
+
return string(result);
|
|
183
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Unlicense
|
|
2
|
+
pragma solidity >=0.8.0;
|
|
3
|
+
|
|
4
|
+
interface Cheats {
|
|
5
|
+
// This allows us to getRecordedLogs()
|
|
6
|
+
struct Log {
|
|
7
|
+
bytes32[] topics;
|
|
8
|
+
bytes data;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Set block.timestamp (newTimestamp)
|
|
12
|
+
function warp(uint256) external;
|
|
13
|
+
|
|
14
|
+
// Set block.height (newHeight)
|
|
15
|
+
function roll(uint256) external;
|
|
16
|
+
|
|
17
|
+
// Set block.basefee (newBasefee)
|
|
18
|
+
function fee(uint256) external;
|
|
19
|
+
|
|
20
|
+
// Set block.coinbase (who)
|
|
21
|
+
function coinbase(address) external;
|
|
22
|
+
|
|
23
|
+
// Loads a storage slot from an address (who, slot)
|
|
24
|
+
function load(address, bytes32) external returns (bytes32);
|
|
25
|
+
|
|
26
|
+
// Stores a value to an address' storage slot, (who, slot, value)
|
|
27
|
+
function store(
|
|
28
|
+
address,
|
|
29
|
+
bytes32,
|
|
30
|
+
bytes32
|
|
31
|
+
) external;
|
|
32
|
+
|
|
33
|
+
// Signs data, (privateKey, digest) => (v, r, s)
|
|
34
|
+
function sign(uint256, bytes32)
|
|
35
|
+
external
|
|
36
|
+
returns (
|
|
37
|
+
uint8,
|
|
38
|
+
bytes32,
|
|
39
|
+
bytes32
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
// Gets address for a given private key, (privateKey) => (address)
|
|
43
|
+
function addr(uint256) external returns (address);
|
|
44
|
+
|
|
45
|
+
// Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path m/44'/60'/0'/0/{index}
|
|
46
|
+
function deriveKey(string calldata, uint32) external returns (uint256);
|
|
47
|
+
|
|
48
|
+
// Derive a private key from a provided mnenomic string (or mnenomic file path) at the derivation path {path}{index}
|
|
49
|
+
function deriveKey(
|
|
50
|
+
string calldata,
|
|
51
|
+
string calldata,
|
|
52
|
+
uint32
|
|
53
|
+
) external returns (uint256);
|
|
54
|
+
|
|
55
|
+
// Performs a foreign function call via terminal, (stringInputs) => (result)
|
|
56
|
+
function ffi(string[] calldata) external returns (bytes memory);
|
|
57
|
+
|
|
58
|
+
// Set environment variables, (name, value)
|
|
59
|
+
function setEnv(string calldata, string calldata) external;
|
|
60
|
+
|
|
61
|
+
// Read environment variables, (name) => (value)
|
|
62
|
+
function envBool(string calldata) external returns (bool);
|
|
63
|
+
|
|
64
|
+
function envUint(string calldata) external returns (uint256);
|
|
65
|
+
|
|
66
|
+
function envInt(string calldata) external returns (int256);
|
|
67
|
+
|
|
68
|
+
function envAddress(string calldata) external returns (address);
|
|
69
|
+
|
|
70
|
+
function envBytes32(string calldata) external returns (bytes32);
|
|
71
|
+
|
|
72
|
+
function envString(string calldata) external returns (string memory);
|
|
73
|
+
|
|
74
|
+
function envBytes(string calldata) external returns (bytes memory);
|
|
75
|
+
|
|
76
|
+
// Read environment variables as arrays, (name, delim) => (value[])
|
|
77
|
+
function envBool(string calldata, string calldata) external returns (bool[] memory);
|
|
78
|
+
|
|
79
|
+
function envUint(string calldata, string calldata) external returns (uint256[] memory);
|
|
80
|
+
|
|
81
|
+
function envInt(string calldata, string calldata) external returns (int256[] memory);
|
|
82
|
+
|
|
83
|
+
function envAddress(string calldata, string calldata) external returns (address[] memory);
|
|
84
|
+
|
|
85
|
+
function envBytes32(string calldata, string calldata) external returns (bytes32[] memory);
|
|
86
|
+
|
|
87
|
+
function envString(string calldata, string calldata) external returns (string[] memory);
|
|
88
|
+
|
|
89
|
+
function envBytes(string calldata, string calldata) external returns (bytes[] memory);
|
|
90
|
+
|
|
91
|
+
// Sets the *next* call's msg.sender to be the input address
|
|
92
|
+
function prank(address) external;
|
|
93
|
+
|
|
94
|
+
// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called
|
|
95
|
+
function startPrank(address) external;
|
|
96
|
+
|
|
97
|
+
// Sets the *next* call's msg.sender to be the input address, and the tx.origin to be the second input
|
|
98
|
+
function prank(address, address) external;
|
|
99
|
+
|
|
100
|
+
// Sets all subsequent calls' msg.sender to be the input address until `stopPrank` is called, and the tx.origin to be the second input
|
|
101
|
+
function startPrank(address, address) external;
|
|
102
|
+
|
|
103
|
+
// Resets subsequent calls' msg.sender to be `address(this)`
|
|
104
|
+
function stopPrank() external;
|
|
105
|
+
|
|
106
|
+
// Sets an address' balance, (who, newBalance)
|
|
107
|
+
function deal(address, uint256) external;
|
|
108
|
+
|
|
109
|
+
// Sets an address' code, (who, newCode)
|
|
110
|
+
function etch(address, bytes calldata) external;
|
|
111
|
+
|
|
112
|
+
// Expects an error on next call
|
|
113
|
+
function expectRevert() external;
|
|
114
|
+
|
|
115
|
+
function expectRevert(bytes calldata) external;
|
|
116
|
+
|
|
117
|
+
function expectRevert(bytes4) external;
|
|
118
|
+
|
|
119
|
+
// Record all storage reads and writes
|
|
120
|
+
function record() external;
|
|
121
|
+
|
|
122
|
+
// Gets all accessed reads and write slot from a recording session, for a given address
|
|
123
|
+
function accesses(address) external returns (bytes32[] memory reads, bytes32[] memory writes);
|
|
124
|
+
|
|
125
|
+
// Record all the transaction logs
|
|
126
|
+
function recordLogs() external;
|
|
127
|
+
|
|
128
|
+
// Gets all the recorded logs
|
|
129
|
+
function getRecordedLogs() external returns (Log[] memory);
|
|
130
|
+
|
|
131
|
+
// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData).
|
|
132
|
+
// Call this function, then emit an event, then call a function. Internally after the call, we check if
|
|
133
|
+
// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).
|
|
134
|
+
// Second form also checks supplied address against emitting contract.
|
|
135
|
+
function expectEmit(
|
|
136
|
+
bool,
|
|
137
|
+
bool,
|
|
138
|
+
bool,
|
|
139
|
+
bool
|
|
140
|
+
) external;
|
|
141
|
+
|
|
142
|
+
function expectEmit(
|
|
143
|
+
bool,
|
|
144
|
+
bool,
|
|
145
|
+
bool,
|
|
146
|
+
bool,
|
|
147
|
+
address
|
|
148
|
+
) external;
|
|
149
|
+
|
|
150
|
+
// Mocks a call to an address, returning specified data.
|
|
151
|
+
// Calldata can either be strict or a partial match, e.g. if you only
|
|
152
|
+
// pass a Solidity selector to the expected calldata, then the entire Solidity
|
|
153
|
+
// function will be mocked.
|
|
154
|
+
function mockCall(
|
|
155
|
+
address,
|
|
156
|
+
bytes calldata,
|
|
157
|
+
bytes calldata
|
|
158
|
+
) external;
|
|
159
|
+
|
|
160
|
+
// Mocks a call to an address with a specific msg.value, returning specified data.
|
|
161
|
+
// Calldata match takes precedence over msg.value in case of ambiguity.
|
|
162
|
+
function mockCall(
|
|
163
|
+
address,
|
|
164
|
+
uint256,
|
|
165
|
+
bytes calldata,
|
|
166
|
+
bytes calldata
|
|
167
|
+
) external;
|
|
168
|
+
|
|
169
|
+
// Clears all mocked calls
|
|
170
|
+
function clearMockedCalls() external;
|
|
171
|
+
|
|
172
|
+
// Expect a call to an address with the specified calldata.
|
|
173
|
+
// Calldata can either be strict or a partial match
|
|
174
|
+
function expectCall(address, bytes calldata) external;
|
|
175
|
+
|
|
176
|
+
// Expect a call to an address with the specified msg.value and calldata
|
|
177
|
+
function expectCall(
|
|
178
|
+
address,
|
|
179
|
+
uint256,
|
|
180
|
+
bytes calldata
|
|
181
|
+
) external;
|
|
182
|
+
|
|
183
|
+
// Gets the code from an artifact file. Takes in the relative path to the json file
|
|
184
|
+
function getCode(string calldata) external returns (bytes memory);
|
|
185
|
+
|
|
186
|
+
// Labels an address in call traces
|
|
187
|
+
function label(address, string calldata) external;
|
|
188
|
+
|
|
189
|
+
// If the condition is false, discard this run's fuzz inputs and generate new ones
|
|
190
|
+
function assume(bool) external;
|
|
191
|
+
|
|
192
|
+
// Set nonce for an account
|
|
193
|
+
function setNonce(address, uint64) external;
|
|
194
|
+
|
|
195
|
+
// Get nonce for an account
|
|
196
|
+
function getNonce(address) external returns (uint64);
|
|
197
|
+
|
|
198
|
+
// Set block.chainid (newChainId)
|
|
199
|
+
function chainId(uint256) external;
|
|
200
|
+
|
|
201
|
+
// Using the address that calls the test contract, has the next call (at this call depth only) create a transaction that can later be signed and sent onchain
|
|
202
|
+
function broadcast() external;
|
|
203
|
+
|
|
204
|
+
// Has the next call (at this call depth only) create a transaction with the address provided as the sender that can later be signed and sent onchain
|
|
205
|
+
function broadcast(address) external;
|
|
206
|
+
|
|
207
|
+
// Using the address that calls the test contract, has the all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
|
|
208
|
+
function startBroadcast() external;
|
|
209
|
+
|
|
210
|
+
// Has the all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain
|
|
211
|
+
function startBroadcast(address) external;
|
|
212
|
+
|
|
213
|
+
// Stops collecting onchain transactions
|
|
214
|
+
function stopBroadcast() external;
|
|
215
|
+
|
|
216
|
+
// Reads the entire content of file to string. Path is relative to the project root. (path) => (data)
|
|
217
|
+
function readFile(string calldata) external returns (string memory);
|
|
218
|
+
|
|
219
|
+
// Reads next line of file to string, (path) => (line)
|
|
220
|
+
function readLine(string calldata) external returns (string memory);
|
|
221
|
+
|
|
222
|
+
// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does.
|
|
223
|
+
// Path is relative to the project root. (path, data) => ()
|
|
224
|
+
function writeFile(string calldata, string calldata) external;
|
|
225
|
+
|
|
226
|
+
// Writes line to file, creating a file if it does not exist.
|
|
227
|
+
// Path is relative to the project root. (path, data) => ()
|
|
228
|
+
function writeLine(string calldata, string calldata) external;
|
|
229
|
+
|
|
230
|
+
// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine.
|
|
231
|
+
// Path is relative to the project root. (path) => ()
|
|
232
|
+
function closeFile(string calldata) external;
|
|
233
|
+
|
|
234
|
+
// Removes file. This cheatcode will revert in the following situations, but is not limited to just these cases:
|
|
235
|
+
// - Path points to a directory.
|
|
236
|
+
// - The file doesn't exist.
|
|
237
|
+
// - The user lacks permissions to remove the file.
|
|
238
|
+
// Path is relative to the project root. (path) => ()
|
|
239
|
+
function removeFile(string calldata) external;
|
|
240
|
+
|
|
241
|
+
function toString(address) external returns (string memory);
|
|
242
|
+
|
|
243
|
+
function toString(bytes calldata) external returns (string memory);
|
|
244
|
+
|
|
245
|
+
function toString(bytes32) external returns (string memory);
|
|
246
|
+
|
|
247
|
+
function toString(bool) external returns (string memory);
|
|
248
|
+
|
|
249
|
+
function toString(uint256) external returns (string memory);
|
|
250
|
+
|
|
251
|
+
function toString(int256) external returns (string memory);
|
|
252
|
+
|
|
253
|
+
// Snapshot the current state of the evm.
|
|
254
|
+
// Returns the id of the snapshot that was created.
|
|
255
|
+
// To revert a snapshot use `revertTo`
|
|
256
|
+
function snapshot() external returns (uint256);
|
|
257
|
+
|
|
258
|
+
// Revert the state of the evm to a previous snapshot
|
|
259
|
+
// Takes the snapshot id to revert to.
|
|
260
|
+
// This deletes the snapshot and all snapshots taken after the given snapshot id.
|
|
261
|
+
function revertTo(uint256) external returns (bool);
|
|
262
|
+
|
|
263
|
+
// Creates a new fork with the given endpoint and block and returns the identifier of the fork
|
|
264
|
+
function createFork(string calldata, uint256) external returns (uint256);
|
|
265
|
+
|
|
266
|
+
// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork
|
|
267
|
+
function createFork(string calldata) external returns (uint256);
|
|
268
|
+
|
|
269
|
+
// Creates _and_ also selects a new fork with the given endpoint and block and returns the identifier of the fork
|
|
270
|
+
function createSelectFork(string calldata, uint256) external returns (uint256);
|
|
271
|
+
|
|
272
|
+
// Creates _and_ also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork
|
|
273
|
+
function createSelectFork(string calldata) external returns (uint256);
|
|
274
|
+
|
|
275
|
+
// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.
|
|
276
|
+
function selectFork(uint256) external;
|
|
277
|
+
|
|
278
|
+
// Returns the currently active fork
|
|
279
|
+
// Reverts if no fork is currently active
|
|
280
|
+
function activeFork() external returns (uint256);
|
|
281
|
+
|
|
282
|
+
// Marks that the account(s) should use persistent storage across fork swaps.
|
|
283
|
+
// Meaning, changes made to the state of this account will be kept when switching forks
|
|
284
|
+
function makePersistent(address) external;
|
|
285
|
+
|
|
286
|
+
function makePersistent(address, address) external;
|
|
287
|
+
|
|
288
|
+
function makePersistent(
|
|
289
|
+
address,
|
|
290
|
+
address,
|
|
291
|
+
address
|
|
292
|
+
) external;
|
|
293
|
+
|
|
294
|
+
function makePersistent(address[] calldata) external;
|
|
295
|
+
|
|
296
|
+
// Revokes persistent status from the address, previously added via `makePersistent`
|
|
297
|
+
function revokePersistent(address) external;
|
|
298
|
+
|
|
299
|
+
function revokePersistent(address[] calldata) external;
|
|
300
|
+
|
|
301
|
+
// Returns true if the account is marked as persistent
|
|
302
|
+
function isPersistent(address) external returns (bool);
|
|
303
|
+
|
|
304
|
+
// Updates the currently active fork to given block number
|
|
305
|
+
// This is similar to `roll` but for the currently active fork
|
|
306
|
+
function rollFork(uint256) external;
|
|
307
|
+
|
|
308
|
+
// Updates the given fork to given block number
|
|
309
|
+
function rollFork(uint256 forkId, uint256 blockNumber) external;
|
|
310
|
+
|
|
311
|
+
/// Returns the RPC url for the given alias
|
|
312
|
+
function rpcUrl(string calldata) external returns (string memory);
|
|
313
|
+
|
|
314
|
+
/// Returns all rpc urls and their aliases `[alias, url][]`
|
|
315
|
+
function rpcUrls() external returns (string[2][] memory);
|
|
316
|
+
|
|
317
|
+
function parseJson(string calldata, string calldata) external returns (bytes memory);
|
|
318
|
+
|
|
319
|
+
function parseJson(string calldata) external returns (bytes memory);
|
|
320
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
5
|
+
|
|
6
|
+
yargs(hideBin(process.argv))
|
|
7
|
+
// Use the commands directory to scaffold.
|
|
8
|
+
.commandDir("commands")
|
|
9
|
+
// Enable strict mode.
|
|
10
|
+
.strict()
|
|
11
|
+
// Useful aliases.
|
|
12
|
+
.alias({ h: "help" }).argv;
|