Skip to content

Commit 4e69e1c

Browse files
authored
feat!: use custom types for Results and Error, and use error functions (#189)
1 parent 50b1d14 commit 4e69e1c

File tree

13 files changed

+519
-187
lines changed

13 files changed

+519
-187
lines changed

src/_modules/Commands.sol

+69-55
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ pragma solidity >=0.8.13 <0.9.0;
33

44
import {VmSafe} from "forge-std/Vm.sol";
55
import {vulcan} from "./Vulcan.sol";
6-
import {Result, ResultType, Ok, Error} from "./Result.sol";
6+
import {Result, ResultType, Ok} from "./Result.sol";
7+
import {LibError, Error} from "./Error.sol";
78
import {removeSelector} from "../_utils/removeSelector.sol";
89

910
/// @dev Struct used to hold command parameters. Useful for creating commands that can be run
@@ -12,9 +13,7 @@ struct Command {
1213
string[] inputs;
1314
}
1415

15-
struct CommandResult {
16-
Result _inner;
17-
}
16+
type CommandResult is bytes32;
1817

1918
struct CommandOutput {
2019
int32 exitCode;
@@ -25,6 +24,7 @@ struct CommandOutput {
2524

2625
library commands {
2726
using commands for *;
27+
using CommandError for *;
2828

2929
/// @dev Creates a new 'Command' struct with empty arguments.
3030
/// @return cmd A new empty 'Command' struct.
@@ -161,14 +161,14 @@ library commands {
161161
/// @dev Runs a command using the specified `Command` struct as parameters and returns the result.
162162
/// @param self The `Command` struct that holds the parameters of the command.
163163
/// @return The result of the command as a bytes array.
164-
function run(Command memory self) internal returns (CommandResult memory) {
164+
function run(Command memory self) internal returns (CommandResult) {
165165
return self.inputs.run();
166166
}
167167

168168
/// @dev Runs a command with the specified `inputs` as parameters and returns the result.
169169
/// @param inputs An array of strings representing the parameters of the command.
170170
/// @return result The result of the command as a bytes array.
171-
function run(string[] memory inputs) internal returns (CommandResult memory result) {
171+
function run(string[] memory inputs) internal returns (CommandResult result) {
172172
try vulcan.hevm.tryFfi(inputs) returns (VmSafe.FfiResult memory ffiResult) {
173173
CommandOutput memory output;
174174

@@ -179,89 +179,90 @@ library commands {
179179

180180
return Ok(output);
181181
} catch Error(string memory message) {
182-
return CommandError.notExecuted(message);
183-
} catch (bytes memory message) {
184-
return CommandError.notExecuted(abi.decode(removeSelector(message), (string)));
182+
return CommandError.NotExecuted(message).toCommandResult();
183+
} catch (bytes memory data) {
184+
string memory message = abi.decode(removeSelector(data), (string));
185+
return CommandError.NotExecuted(message).toCommandResult();
185186
}
186187
}
187188

188-
function run(string[1] memory inputs) internal returns (CommandResult memory) {
189+
function run(string[1] memory inputs) internal returns (CommandResult) {
189190
return _toDynamic(inputs).run();
190191
}
191192

192-
function run(string[2] memory inputs) internal returns (CommandResult memory) {
193+
function run(string[2] memory inputs) internal returns (CommandResult) {
193194
return _toDynamic(inputs).run();
194195
}
195196

196-
function run(string[3] memory inputs) internal returns (CommandResult memory) {
197+
function run(string[3] memory inputs) internal returns (CommandResult) {
197198
return _toDynamic(inputs).run();
198199
}
199200

200-
function run(string[4] memory inputs) internal returns (CommandResult memory) {
201+
function run(string[4] memory inputs) internal returns (CommandResult) {
201202
return _toDynamic(inputs).run();
202203
}
203204

204-
function run(string[5] memory inputs) internal returns (CommandResult memory) {
205+
function run(string[5] memory inputs) internal returns (CommandResult) {
205206
return _toDynamic(inputs).run();
206207
}
207208

208-
function run(string[6] memory inputs) internal returns (CommandResult memory) {
209+
function run(string[6] memory inputs) internal returns (CommandResult) {
209210
return _toDynamic(inputs).run();
210211
}
211212

212-
function run(string[7] memory inputs) internal returns (CommandResult memory) {
213+
function run(string[7] memory inputs) internal returns (CommandResult) {
213214
return _toDynamic(inputs).run();
214215
}
215216

216-
function run(string[8] memory inputs) internal returns (CommandResult memory) {
217+
function run(string[8] memory inputs) internal returns (CommandResult) {
217218
return _toDynamic(inputs).run();
218219
}
219220

220-
function run(string[9] memory inputs) internal returns (CommandResult memory) {
221+
function run(string[9] memory inputs) internal returns (CommandResult) {
221222
return _toDynamic(inputs).run();
222223
}
223224

224-
function run(string[10] memory inputs) internal returns (CommandResult memory) {
225+
function run(string[10] memory inputs) internal returns (CommandResult) {
225226
return _toDynamic(inputs).run();
226227
}
227228

228-
function run(string[11] memory inputs) internal returns (CommandResult memory) {
229+
function run(string[11] memory inputs) internal returns (CommandResult) {
229230
return _toDynamic(inputs).run();
230231
}
231232

232-
function run(string[12] memory inputs) internal returns (CommandResult memory) {
233+
function run(string[12] memory inputs) internal returns (CommandResult) {
233234
return _toDynamic(inputs).run();
234235
}
235236

236-
function run(string[13] memory inputs) internal returns (CommandResult memory) {
237+
function run(string[13] memory inputs) internal returns (CommandResult) {
237238
return _toDynamic(inputs).run();
238239
}
239240

240-
function run(string[14] memory inputs) internal returns (CommandResult memory) {
241+
function run(string[14] memory inputs) internal returns (CommandResult) {
241242
return _toDynamic(inputs).run();
242243
}
243244

244-
function run(string[15] memory inputs) internal returns (CommandResult memory) {
245+
function run(string[15] memory inputs) internal returns (CommandResult) {
245246
return _toDynamic(inputs).run();
246247
}
247248

248-
function run(string[16] memory inputs) internal returns (CommandResult memory) {
249+
function run(string[16] memory inputs) internal returns (CommandResult) {
249250
return _toDynamic(inputs).run();
250251
}
251252

252-
function run(string[17] memory inputs) internal returns (CommandResult memory) {
253+
function run(string[17] memory inputs) internal returns (CommandResult) {
253254
return _toDynamic(inputs).run();
254255
}
255256

256-
function run(string[18] memory inputs) internal returns (CommandResult memory) {
257+
function run(string[18] memory inputs) internal returns (CommandResult) {
257258
return _toDynamic(inputs).run();
258259
}
259260

260-
function run(string[19] memory inputs) internal returns (CommandResult memory) {
261+
function run(string[19] memory inputs) internal returns (CommandResult) {
261262
return _toDynamic(inputs).run();
262263
}
263264

264-
function run(string[20] memory inputs) internal returns (CommandResult memory) {
265+
function run(string[20] memory inputs) internal returns (CommandResult) {
265266
return _toDynamic(inputs).run();
266267
}
267268

@@ -405,51 +406,64 @@ library commands {
405406
}
406407

407408
library CommandError {
408-
bytes32 constant NOT_EXECUTED = keccak256("COMMAND_NOT_EXECUTED");
409+
using LibError for *;
409410

410-
function notExecuted(string memory reason) public pure returns (CommandResult memory) {
411+
function NotExecuted(string memory reason) internal pure returns (Error) {
411412
string memory message = string.concat("The command was not executed: \"", reason, "\"");
412-
return CommandResult(Error(NOT_EXECUTED, message).toResult());
413+
return NotExecuted.encodeError(message, reason);
414+
}
415+
416+
function toCommandResult(Error self) internal pure returns (CommandResult) {
417+
return CommandResult.wrap(Result.unwrap(self.toResult()));
413418
}
414419
}
415420

416421
library LibCommandResult {
417-
/// @dev Checks if a `CommandResult` returned an `ok` exit code.
418-
function isOk(CommandResult memory self) internal pure returns (bool) {
419-
return self._inner.isOk();
422+
function isOk(CommandResult self) internal pure returns (bool) {
423+
return self.asResult().isOk();
424+
}
425+
426+
function isError(CommandResult self) internal pure returns (bool) {
427+
return self.asResult().isError();
420428
}
421429

422-
/// @dev Checks if a `CommandResult` struct is an error.
423-
function isError(CommandResult memory self) internal pure returns (bool) {
424-
return self._inner.isError();
430+
function unwrap(CommandResult self) internal pure returns (CommandOutput memory val) {
431+
bytes32 _val = self.asResult().unwrap();
432+
assembly {
433+
val := _val
434+
}
425435
}
426436

427-
/// @dev Returns the output of a `CommandResult` or reverts if the result was an error.
428-
function unwrap(CommandResult memory self) internal pure returns (CommandOutput memory) {
429-
return abi.decode(self._inner.unwrap(), (CommandOutput));
437+
function expect(CommandResult self, string memory err) internal pure returns (CommandOutput memory) {
438+
if (self.isError()) {
439+
revert(err);
440+
}
441+
442+
return self.toValue();
430443
}
431444

432-
/// @dev Returns the output of a `CommandResult` or reverts if the result was an error.
433-
/// @param customError The error message that will be used when reverting.
434-
function expect(CommandResult memory self, string memory customError)
435-
internal
436-
pure
437-
returns (CommandOutput memory)
438-
{
439-
return abi.decode(self._inner.expect(customError), (CommandOutput));
445+
function toError(CommandResult self) internal pure returns (Error) {
446+
return self.asResult().toError();
440447
}
441448

442-
function toValue(CommandResult memory self) internal pure returns (CommandOutput memory) {
443-
return abi.decode(self._inner.toValue(), (CommandOutput));
449+
function toValue(CommandResult self) internal pure returns (CommandOutput memory val) {
450+
bytes32 _val = self.asResult().toValue();
451+
assembly {
452+
val := _val
453+
}
444454
}
445455

446-
function toError(CommandResult memory self) internal pure returns (Error memory) {
447-
return self._inner.toError();
456+
function asResult(CommandResult self) internal pure returns (Result) {
457+
return Result.wrap(CommandResult.unwrap(self));
448458
}
449459
}
450460

451-
function Ok(CommandOutput memory output) pure returns (CommandResult memory) {
452-
return CommandResult(Ok(abi.encode(output)));
461+
function Ok(CommandOutput memory value) pure returns (CommandResult) {
462+
bytes32 _value;
463+
assembly {
464+
_value := value
465+
}
466+
return CommandResult.wrap(Result.unwrap(Ok(_value)));
453467
}
454468

455469
using commands for Command global;

src/_modules/Error.sol

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.13;
3+
4+
import {LibResult, Result, ResultType} from "./Result.sol";
5+
6+
type Error is bytes32;
7+
8+
library LibError {
9+
using LibError for *;
10+
11+
function toResult(Error err) internal pure returns (Result) {
12+
return LibResult.encode(ResultType.Error, Error.unwrap(err));
13+
}
14+
15+
// Used internally by error functions
16+
17+
function decode(Error err) internal pure returns (bytes32 id, string memory message, bytes memory data) {
18+
bytes memory errorData;
19+
assembly {
20+
errorData := err
21+
}
22+
return abi.decode(errorData, (bytes32, string, bytes));
23+
}
24+
25+
/* Function definitions for multiple permutations of function types */
26+
27+
// ()
28+
function encodeError(function() returns(Error) fn, string memory message) internal pure returns (Error err) {
29+
bytes memory data = abi.encode(fn.toErrorId(), message, "");
30+
assembly {
31+
err := data
32+
}
33+
}
34+
35+
function toErrorId(function() returns(Error) fn) internal pure returns (bytes32 id) {
36+
assembly {
37+
id := fn
38+
}
39+
}
40+
41+
function matches(Error err, function() returns(Error) fn) internal pure returns (bool) {
42+
(bytes32 id,,) = decode(err);
43+
return id == toErrorId(fn);
44+
}
45+
46+
function decodeAs(Error, function() returns(Error)) internal pure {
47+
revert("No data to decode!");
48+
}
49+
50+
// (uint256)
51+
52+
function encodeError(function(uint256) returns(Error) fn, string memory message, uint256 p0)
53+
internal
54+
pure
55+
returns (Error err)
56+
{
57+
bytes memory data = abi.encode(fn.toErrorId(), message, abi.encode(p0));
58+
assembly {
59+
err := data
60+
}
61+
}
62+
63+
function toErrorId(function(uint256) returns(Error) fn) internal pure returns (bytes32 id) {
64+
assembly {
65+
id := fn
66+
}
67+
}
68+
69+
function matches(Error err, function(uint256) returns(Error) fn) internal pure returns (bool) {
70+
(bytes32 id,,) = decode(err);
71+
return id == toErrorId(fn);
72+
}
73+
74+
function decodeAs(Error err, function(uint256) returns(Error)) internal pure returns (uint256) {
75+
(,, bytes memory data) = decode(err);
76+
return abi.decode(data, (uint256));
77+
}
78+
79+
// (string)
80+
81+
function encodeError(function(string memory) returns(Error) fn, string memory message, string memory p0)
82+
internal
83+
pure
84+
returns (Error err)
85+
{
86+
bytes memory data = abi.encode(fn.toErrorId(), message, abi.encode(p0));
87+
assembly {
88+
err := data
89+
}
90+
}
91+
92+
function toErrorId(function(string memory) returns(Error) fn) internal pure returns (bytes32 id) {
93+
assembly {
94+
id := fn
95+
}
96+
}
97+
98+
function matches(Error err, function(string memory) returns(Error) fn) internal pure returns (bool) {
99+
(bytes32 id,,) = decode(err);
100+
return id == toErrorId(fn);
101+
}
102+
103+
function decodeAs(Error err, function(string memory) returns(Error)) internal pure returns (string memory) {
104+
(,, bytes memory data) = decode(err);
105+
return abi.decode(data, (string));
106+
}
107+
}
108+
109+
using LibError for Error global;

src/_modules/Fe.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ library fe {
2323

2424
/// @dev Builds a binary file from a `.fe` file.
2525
/// @param self The `Fe` struct to build.
26-
function build(Fe memory self) internal returns (CommandResult memory) {
26+
function build(Fe memory self) internal returns (CommandResult) {
2727
return self.toCommand().run();
2828
}
2929

src/_modules/Huff.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ library huff {
3232
});
3333
}
3434

35-
function compile(Huffc memory self) internal returns (CommandResult memory) {
35+
function compile(Huffc memory self) internal returns (CommandResult) {
3636
return self.toCommand().run();
3737
}
3838

0 commit comments

Comments
 (0)