Skip to content

Commit 60fb760

Browse files
authored
BytesParsing for calldata (#58)
* taking first stab at BytesParsing for calldata impl (untested) * fix typo * implement calldata parsing and testing for BytesParsing * add forge runs parameter to BytesParsing test * fix calldata prefixedSlice parsing impl
1 parent 847c823 commit 60fb760

File tree

5 files changed

+2770
-549
lines changed

5 files changed

+2770
-549
lines changed

gen/libraryTestWrapper.ts

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,19 @@
11
//Simple parser for .sol files that finds libraries defined in the file and creates a wrapper
2-
// that converts all their internal functions to external functions so they can be tested
3-
// in forge unit tests.
2+
// that converts all their internal functions to external functions so they can be externally
3+
// called in forge unit tests.
4+
//
5+
//Forge supports vm.expectRevert even for internal functions, so this wrapper is primarily
6+
// helpful for libraries like BytesParsing (the original motivation for this script) where
7+
// you have a large family of similar functions to test and you don't want to write a separate
8+
// test for each one. So, it really mostly is a workaround for Solidity's lack of support for
9+
// generics.
10+
11+
//Regarding the implementation of this script:
412
//Instead of properly parsing the full AST, we make our task of finding and transforming the
513
// relevant bits easier by making some basic assumptions about code formatting that any sane
6-
// code should almost certainly adhere to regardless.
7-
14+
// code should almost certainly adhere to regardless, like closing braces of library definitions
15+
// being on their own line with no leading whitespace, etc.
16+
//
817
//Solidity language grammar:
918
// https://docs.soliditylang.org/en/latest/grammar.html
1019

@@ -43,8 +52,22 @@ if (process.argv.length != 3) {
4352
process.exit(1);
4453
}
4554

46-
const filename = process.argv[2];
47-
let fileCode = readFileSync("../src/" + filename + filename.endsWith(".sol") ? "" : ".sol", "utf8");
55+
//convenience for use with Makefile:
56+
//If no .sol file ending is specified, this script will use Wormhole Solidity SDK defaults for
57+
// the file paths, the SPDX license header, the pragma version, and the import statement.
58+
const fullPath = (() => {
59+
const filename = process.argv[2];
60+
if (filename.endsWith(".sol"))
61+
return filename;
62+
63+
console.log(
64+
`// SPDX-License-Identifier: Apache 2\npragma solidity ^0.8.24;\n\n` +
65+
`import "wormhole-sdk/${filename}.sol";\n`
66+
);
67+
68+
return "../src/" + filename + ".sol";
69+
})();
70+
let fileCode = readFileSync(fullPath, "utf8");
4871

4972
//we first remove all comments so we can be sure that everything we're parsing is actual code
5073
fileCode = removeComments(fileCode);
@@ -76,13 +99,13 @@ for (const libs of libMatches) {
7699
const [_, funcName, funcParasRaw, modsRaw, close] = funcs;
77100
if (close == ';')
78101
continue; //function pointer, not a function definition
79-
102+
80103
if (!modsRaw.includes("internal"))
81104
continue; //not an internal function
82105

83106
const retParasRegex = /returns\s*\(([\s\S]*?)\)/;
84107
const retParasRaw = modsRaw.match(retParasRegex);
85-
108+
86109
const collapseSpaceRegex = /\s\s+/g;
87110
const paramsToArray = (paramList: string) =>
88111
paramList.replace(collapseSpaceRegex, ' ').trim().split(',').map(param => {
@@ -100,12 +123,7 @@ for (const libs of libMatches) {
100123
}
101124
}
102125

103-
console.log(`// SPDX-License-Identifier: Apache 2
104-
pragma solidity ^0.8.24;
105-
106-
//This file was auto-generated by libraryTestWrapper.ts
107-
108-
import "wormhole-sdk/${filename}.sol";`);
126+
console.log(`// This file was auto-generated by wormhole-solidity-sdk gen/libraryTestWrapper.ts`);
109127

110128
const pConcat = (paras: string[]) =>
111129
(paras.length > 2 ? "\n " : "") +
@@ -121,7 +139,7 @@ const pNames = (paras: string[]) =>
121139

122140
for (const [libName, funcs] of Object.entries(libraries)) {
123141
console.log(`\ncontract ${libName}TestWrapper {`);
124-
const funcCode = [];
142+
const funcCode = [];
125143
for (const func of funcs)
126144
funcCode.push([
127145
` function ${func.name}(${pConcat(func.paras)}) external ${func.stateMut}` +

src/constants/Common.sol

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// SPDX-License-Identifier: Apache 2
2+
pragma solidity ^0.8.4;
3+
4+
uint256 constant FREE_MEMORY_PTR = 0x40;
5+
uint256 constant WORD_SIZE = 32;
6+
//we can't define _WORD_SIZE_MINUS_ONE via _WORD_SIZE - 1 because of solc restrictions
7+
// what constants can be used in inline assembly
8+
uint256 constant WORD_SIZE_MINUS_ONE = 31; //=0x1f=0b00011111
9+
10+
//see section "prefer `< MAX + 1` over `<= MAX` for const comparison" in docs/Optimization.md
11+
uint256 constant WORD_SIZE_PLUS_ONE = 33;

0 commit comments

Comments
 (0)