Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sum/usum Example #154

Closed
wants to merge 1 commit into from
Closed

Conversation

liav-certora
Copy link
Contributor

No description provided.

Copy link
Contributor

@naftali-g naftali-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if there's a simple real-world example that could be used here instead of all the synthetic tests.

Comment on lines +4 to +5
* `sum` - Used to sum elements with signed values (e.g. int).
* `usum` - Used to sum elements with unsigned values (e.g. uint) including `mathint`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one can use sum also on unsigned values. usum adds some more assumptions that promise that the sum is always greater than its parts, but it might be harder on the prover so if that property isn't needed one may prefer to use the normal sum also on unsigned.

One more thing is that when using usum on mathint then we add internal assertions that all writes to the ghost are indeed non-negative.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks I noted that.

Restrictions:
* We can only sum ghosts, not e.g. direct storage access of mappings.
* The summed variables must be used, and can only be used as indices to the ghost (so e.g. sum uint u. myGhost[a][u*2] won't work).
* We only sum values that were written to the ghost, we don't know what there is in the other slots.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is true for sum, for usum it's more nuanced since we also look at reads to promise the "sum is greater than its parts" property

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks.

Copy link
Contributor

@nd-certora nd-certora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really really hard. I would redo this and have:

  1. very simple solidity case that there is a total field and then spec that has the mirror ghost and verify that the sum is total
  2. same spec with persistent, should fail to verify
  3. the nested ghost spec in a different file with the example of quantifiers

@@ -0,0 +1,7 @@
{
files: ["ghostSums.sol:C"],
process: "emv",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
process: "emv",

files: ["ghostSums.sol:C"],
process: "emv",
rule_sanity: "basic",
solc: "solc8.24",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
solc: "solc8.24",

mapping(address => int) _n;
bool internal _b;

function ghostUpdater(address a, int n) external {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function ghostUpdater(address a, int n) external {
function storageUpdater(address a, int n) external {

_n[a] = n;
}

function ghostUpdaterReverts(address a, int n) external {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
function ghostUpdaterReverts(address a, int n) external {
function storageUpdaterReverts(address a, int n) external {

function ghostUpdaterReverts(address a, int n) external envfree;
}

ghost mapping(address => int) ghostAddrToInt256;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a mirror ghost, right? lets keep it simple


ghost mapping(address => int) ghostAddrToInt256;
ghost mapping(uint8 => mapping(bytes4 => mapping(mathint => mapping(address => int8)))) ghostNestedMapping;
persistent ghost mapping(address => int) persistentGhostAddrToInt256;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

persistent behave differently so lets have a copy of the spec with persistent mirror and show the difference

@@ -0,0 +1,15 @@
contract C {
mapping(address => int) _n;
bool internal _b;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

int256 total

bool internal _b;

function ghostUpdater(address a, int n) external {
_n[a] = n;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update total


function ghostUpdaterReverts(address a, int n) external {
_n[a] = n;
if (!_b) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update total

// Verify we "hook" onto reads of the ghost also when in an assigning command _to_ that ghost.
ghostAddrToInt256[addr] = require_int256(ghostAddrToInt256[addr] * 2);
assert (sum address a. ghostAddrToInt256[a]) == initialSum + (newVal * 2) - oldVal;
satisfy true; // to force creation of calltrace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just show that total is the sum of mirrorghost

@liav-certora
Copy link
Contributor Author

I ended up doing a much much simpler solution in a new PR. Closing this one.

@liav-certora liav-certora deleted the liav/cert-8247-sum-usum-examples branch February 13, 2025 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants