Skip to content

Commit 4d7cb97

Browse files
naftali-gjohspaeth
andauthored
Add an example for internal function calls (#191)
* add an example for internal function calls * Update CVLByExample/InternalFunctionsFromCVL/README.md Co-authored-by: Johannes Späth <johspaeth@users.noreply.github.com> --------- Co-authored-by: Johannes Späth <johspaeth@users.noreply.github.com>
1 parent de25ddf commit 4d7cb97

File tree

4 files changed

+122
-0
lines changed

4 files changed

+122
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// SPDX-License-Identifier: MIT
2+
contract A {
3+
struct S {
4+
int i;
5+
}
6+
7+
S s;
8+
9+
function anInternalFunction() internal returns (uint) { return 0; }
10+
function summarizedInternal() internal returns (uint) { return 0; }
11+
12+
function internalFunctionWithStorageInput(S storage _s) internal { s = _s; }
13+
function internalFunctionWithStorageOutput() internal returns (S storage) { return s; }
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"files": [
3+
"A.sol"
4+
],
5+
"process": "emv",
6+
"solc": "solc8.25",
7+
"verify": "A:InternalFunctionCall.spec"
8+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
methods {
2+
function summarizedInternal() internal returns (uint) => cvlSummary();
3+
// function anInternalFunction() internal returns (uint) envfree; <-- This will fail compilation: 'The envfree qualifier is not allowed on internal functions'
4+
}
5+
6+
function cvlSummary() returns (uint) {
7+
return 1;
8+
}
9+
10+
rule internalFunctionCall {
11+
env e;
12+
13+
assert anInternalFunction(e) == 0;
14+
assert summarizedInternal(e) == 1;
15+
16+
// A.S s;
17+
// internalFunctionWithStorageInput(e, s); <-- This will fail compilation: 'could not type expression "internalFunctionWithStorageInput(e,s)", message: Cannot call internal function internalFunctionWithStorageInput from spec because input parameter '_s' has storage location'
18+
// internalFunctionWithStorageOutput(e); <-- This will fail compilation: 'could not type expression "internalFunctionWithStorageOutput(e)", message: Cannot call internal function internalFunctionWithStorageOutput from spec because output parameter #0 has storage location'
19+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Demonstrating Calling an internal function directly from CVL
2+
3+
## Overview
4+
5+
This repository provides an example of calling internal functions directly from a CVL specification file.
6+
7+
## Solidity Contracts
8+
9+
This example includes a simple Solidity contract, `A`, which has a few internal functions with different signatures
10+
11+
### Contract A
12+
13+
```solidity
14+
contract A {
15+
struct S {
16+
int i;
17+
}
18+
19+
S s;
20+
21+
function anInternalFunction() internal returns (uint) { return 0; }
22+
function summarizedInternal() internal returns (uint) { return 0; }
23+
24+
function internalFunctionWithStorageInput(S storage _s) internal { s = _s; }
25+
function internalFunctionWithStorageOutput() internal returns (S storage) { return s; }
26+
}
27+
```
28+
29+
## Specification
30+
31+
The specification demonstrates how one can call the internal functions directly from spec.
32+
33+
### Specification
34+
35+
```cvl
36+
methods {
37+
function summarizedInternal() internal returns (uint) => cvlSummary();
38+
// function anInternalFunction() internal returns (uint) envfree; <-- This will fail compilation: 'The envfree qualifier is not allowed on internal functions'
39+
}
40+
41+
function cvlSummary() returns (uint) {
42+
return 1;
43+
}
44+
45+
rule internalFunctionCall {
46+
env e;
47+
48+
assert anInternalFunction(e) == 0;
49+
assert summarizedInternal(e) == 1;
50+
51+
// A.S s;
52+
// internalFunctionWithStorageInput(e, s); <-- This will fail compilation: 'could not type expression "internalFunctionWithStorageInput(e,s)", message: Cannot call internal function internalFunctionWithStorageInput from spec because input parameter '_s' has storage location'
53+
// internalFunctionWithStorageOutput(e); <-- This will fail compilation: 'could not type expression "internalFunctionWithStorageOutput(e)", message: Cannot call internal function internalFunctionWithStorageOutput from spec because output parameter #0 has storage location'
54+
}
55+
```
56+
57+
### Specification Breakdown
58+
59+
- **`methods` block**:
60+
- Summarize the internal function `summarizedInternal` to a CVL function that returns a constant `1`.
61+
- Demonstrates that one cannot declare an internal function as `envfree`.
62+
63+
- **Rule `internalFunctionCall`**:
64+
- Call the internal function `anInternalFunction`. Notice how the syntax is exactly the same as calling an external function.
65+
- Call the internal function `summarizedInternal`. This call demonstrates that in contrast to how external function calls work, where the contract
66+
implementation is always inlined when the function is called from spec (even if it has a summary), in the internal function case the summary will be inlined.
67+
- Demonstrate that calling internal functions with input or output parameters with `storage` location won't compile.
68+
69+
## How to Run the Example
70+
71+
1. **Run Certora Prover**:
72+
- Command:
73+
```bash
74+
certoraRun InternalFunctionCall.conf
75+
```
76+
77+
2. **Check the Output**: The execution shows how the internal function (or its summary) is inlined in the CVL rule.
78+
79+
### Execution Links
80+
81+
- [Certora Run Output](https://prover.certora.com/output/97560/85cdc83bc611411da28ac63f76e2e445?anonymousKey=64077f14f694570579878704b14adb86c7581724)

0 commit comments

Comments
 (0)