Forge
There is limited support for Forge in SUAVE. We recommend that you use it only for writing contracts intended to test precompiles.
Writing and compiling contracts for SUAVE is similar to Ethereum, and can be done with familiar local tools like Forge, or even IDEs like Remix. Deploying those contracts to SUAVE is done using the same transaction type as Ethereum, and so can also be achieved from those tools without modifying anything other than the RPC endpoint.
However, SUAVE makes an extended set of precompiles available in any contract. While these are included as a library to keep compilation easy, you can't use Forge (or Remix) to interact with any method in those contracts which uses any of the new precompiles once the contracts are deployed.
Methods which use new precompiles can only be executed through a Kettle as a Confidential Compute Request (CCR). Foundry supports neither precompiles nor CCRs. This limits the current use cases for Forge.
SuaveForge.sol
is a Solidity library that implements the same precompiles as Suave.sol
. The difference is this:
Suave.sol
is used in the MEVM on the Kettle specified by any CCRSuaveForge.sol
uses the ffi cheatcode in an environment external to Forge (i.e. the instance of SUAVE you are running locally). Theffi
cheatcode uses thesuave forge
command from thesuave
binary to make remote calls.
Installβ
Let's start a new, empty repo and set suave-geth
as a submodule so that we can easily import the SuaveForge.sol
library:
mkdir suave-forge
cd suave-forge
forge init
git submodule init
git submodule add https://github.com/flashbots/suave-geth.git
Write and run a Forge scriptβ
Here is an example Forge script that uses the SuaveForge.sol
library to create a new bid. Copy and paste it into a file called Example.sol
in the src
directory:
pragma solidity ^0.8.8;
import "../suave-geth/suave/sol/libraries/SuaveForge.sol";
import "forge-std/Script.sol";
contract Example is Script {
address[] public addressList = [Suave.ANYALLOWED];
function run() public {
Suave.DataRecord memory record = SuaveForge.newDataRecord(
0,
addressList,
addressList,
"default:v0:ethBundles"
);
Suave.DataRecord[] memory allShareMatchRecords = SuaveForge.fetchDataRecords(
0,
"default:v0:ethBundles"
);
console.log(allShareMatchRecords.length);
SuaveForge.confidentialStore(record.id, "a", abi.encodePacked("bbbbbb"));
bytes memory result = SuaveForge.confidentialRetrieve(record.id, "a");
console.logBytes(result);
}
}
The same precompile functions available in Suave.sol
are also implemented in SuaveForge.sol
, though the struct types are still imported from Suave.sol
. It is not required to import Suave.sol
in your scripts since SuaveForge.sol
already does it.
In order to deploy this example contract, you need to have SUAVE running locally, which can be done from your git submodule directory:
cd suave-geth
make suave
suave --suave.dev
Then, run the Forge script with the ffi
flag enabled:
forge script Example.sol --ffi
Having issues?
Typically, building SUAVE yourself places the binary in the $GOPATH/bin
directory. If it didn't happen, ensure that path is added to your PATH
environment variable:
export PATH=$PATH:$GOPATH/bin
The Forge script should print the gas used to run the specified function in your console. If you check the logs of your SUAVE devnet, you should see a message like this:
INFO [timestamp] confidential engine: refusing to send writes based on unsigned transaction
Due to the limitations described above (no native support for precompiles or CCRs in Forge) and having to rely on your local environment, rather than Foundry's built-in network or forks, we recommend that you only use Forge for testing new precompiles you are writing.
Deploy your contractβ
That said, you can use Forge to deploy contracts to SUAVE (though we recommend that you then use the Golang SDK to send transactions).
If you wanted to deploy Example.sol
, there are three steps you need to take:
- Replace
SuaveForge.sol
withSuave.sol
and update all references in your contract. - Get Rigil ETH from the faucet.
- Run the following command:
forge create --rpc-url https://rpc.rigil.suave.flashbots.net --legacy \
--private-key <your_funded_private_key> src/Example.sol:Example