Skip to content

Commit

Permalink
Add validation for --ffi enabled + suave binary in forge (#18)
Browse files Browse the repository at this point in the history
* Add validation for --ffi enabled + suave binary in forge
  • Loading branch information
ferranbt authored Jan 9, 2024
1 parent d82abfe commit 0b37577
Showing 1 changed file with 58 additions and 6 deletions.
64 changes: 58 additions & 6 deletions src/Test.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,66 @@
pragma solidity ^0.8.8;

import "./forge/Registry.sol";
import "forge-std/Test.sol";

contract SuaveEnabled {
contract SuaveEnabled is Test {
function setUp() public {
// TODO: Add checks to validate that:
// - User is running the test with ffi. Since vm.ffi is deployed as a contract, the error if ffi is not active
// is reported as a Suave.PeekerReverted error and it is not clear what the problem is.
// - Suave binary is on $PATH and Suave is running. This could be done with ffi calls to the suave binary.
// Put this logic inside `enable` itself.
string[] memory inputs = new string[](3);
inputs[0] = "suave-geth";
inputs[1] = "forge";
inputs[2] = "status";

try vm.ffi(inputs) returns (bytes memory response) {
// the status call of the `suave-geth forge` command fails with the 'not-ok' prefix
// which is '6e6f742d6f6b' in hex
if (isPrefix(hex"6e6f742d6f6b", response)) {
revert("Local Suave node not detected running");
}
} catch (bytes memory reason) {
revert(detectErrorMessage(reason));
}

Registry.enable();
}

function detectErrorMessage(bytes memory reason) internal pure returns (string memory) {
// Errors from cheatcodes are reported as 'CheatcodeError(string)' events
// 'eeaa9e6f' is the signature of the event
if (!isPrefix(hex"eeaa9e6f", reason)) {
return string(reason);
}

// retrieve the body of the event by removing the signature
bytes memory eventBody = new bytes(reason.length - 4);
for (uint256 i = 4; i < reason.length; i++) {
eventBody[i - 4] = reason[i];
}

// decode event as 'tuple(bytes message)' since it is equivalent to tuple(string)
(bytes memory message) = abi.decode(eventBody, (bytes));

// the prefix is 'FFI is disabled' in hex
if (isPrefix(hex"4646492069732064697361626c6564", message)) {
return "Suave <> Forge integration requires the --ffi flag to be enabled";
}

// the prefix is 'failed to execute command' in hex
if (isPrefix(hex"6661696c656420746f206578656375746520636f6d6d616e64", message)) {
return "Forge cannot locate the 'suave' binary. Is it installed in $PATH?";
}

return string(message);
}

function isPrefix(bytes memory prefix, bytes memory data) internal pure returns (bool) {
if (prefix.length > data.length) {
return false;
}
for (uint256 i = 0; i < prefix.length; i++) {
if (prefix[i] != data[i]) {
return false;
}
}
return true;
}
}

0 comments on commit 0b37577

Please sign in to comment.