Skip to content

Commit

Permalink
Add specialized code generation for Foundry.
Browse files Browse the repository at this point in the history
  • Loading branch information
wuestholz committed Oct 9, 2023
1 parent 2da4c25 commit 20e9c31
Showing 1 changed file with 37 additions and 10 deletions.
47 changes: 37 additions & 10 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ func generateBenchmarkStateful() error {
if depth < 1 {
indentStr := strings.Repeat(" ", indent)
return fmt.Sprintf(
`%vemit AssertionFailed("%v"); assert(false); // bug`,
`%vfound[%v] = true; return -1; // bug`,
indentStr,
rv,
)
Expand Down Expand Up @@ -240,13 +240,27 @@ func generateBenchmarkStateful() error {
}
bodyStr := bodyBuilder.String()

var invBuilder strings.Builder
for i := 1; i < retCnt; i++ {
_, _ = fmt.Fprintf(
&invBuilder,
` function invariant_%v() external { if (m.found(%v)) { fail("%v"); } }
`,
i,
i,
i,
)
}
invStr := invBuilder.String()

type ProgramPlaceholders struct {
ParamsStr string
ArgsStr string
DimX int
DimY int
BodyStr string
RetCnt int
InvStr string
}
placeholders := ProgramPlaceholders{
ParamsStr: paramsStr,
Expand All @@ -255,43 +269,56 @@ func generateBenchmarkStateful() error {
DimY: dimY,
BodyStr: bodyStr,
RetCnt: retCnt,
InvStr: invStr,
}
progTemplate := `pragma solidity ^0.8.19;
/// automatically generated by Daedaluzz
contract Maze {
event AssertionFailed(string message);
uint64 private x;
uint64 private y;
mapping (uint64 => bool) public found;
function moveNorth({{.ParamsStr}}) payable external returns (int64) {
uint64 ny = y + 1;
require(ny < {{.DimY}});
y = ny;
return step({{.ArgsStr}});
int64 r = step(x, ny, {{.ArgsStr}});
if (0 <= r) { y = ny; }
return r;
}
function moveSouth({{.ParamsStr}}) payable external returns (int64) {
require(0 < y);
uint64 ny = y - 1;
y = ny;
return step({{.ArgsStr}});
int64 r = step(x, ny, {{.ArgsStr}});
if (0 <= r) { y = ny; }
return r;
}
function moveEast({{.ParamsStr}}) payable external returns (int64) {
uint64 nx = x + 1;
require(nx < {{.DimX}});
x = nx;
return step({{.ArgsStr}});
int64 r = step(nx, y, {{.ArgsStr}});
if (0 <= r) { x = nx; }
return r;
}
function moveWest({{.ParamsStr}}) payable external returns (int64) {
require(0 < x);
uint64 nx = x - 1;
x = nx;
return step({{.ArgsStr}});
int64 r = step(nx, y, {{.ArgsStr}});
if (0 <= r) { x = nx; }
return r;
}
function step({{.ParamsStr}}) internal returns (int64) {
function step(uint64 x, uint64 y, {{.ParamsStr}}) internal returns (int64) {
unchecked {
{{.BodyStr}} return {{.RetCnt}};
}
}
}
import "forge-std/Test.sol";
contract TestMaze is Test {
Maze m;
function setUp() external {
m = new Maze();
}
{{.InvStr}}}
`
parsedTemplate, parseErr := template.New("program").Parse(progTemplate)
if parseErr != nil {
Expand Down

0 comments on commit 20e9c31

Please sign in to comment.