Skip to content

docs: properties for invariant testing#12

Closed
0xteddybear wants to merge 1 commit intodefi-wonderland:sc/superchain-erc20from
0xteddybear:test/superc20-invariants
Closed

docs: properties for invariant testing#12
0xteddybear wants to merge 1 commit intodefi-wonderland:sc/superchain-erc20from
0xteddybear:test/superc20-invariants

Conversation

@0xteddybear
Copy link
Copy Markdown

I'm not quite sure how to go about specifying the invariants for supERC20, since:

  • the ethereum-optimism/optimism repo in packages/contracts-bedrock already has invariant tests, but written in foundry
  • invariants are programatically generated from the @Custom:invariant tags in code, and we're gonna write invariant defs before their test code

any feedback is welcome ✨


| id | description | halmos | echidna |
| ----- | ----- | ----- | ----- |
| 4 | sum of total supply across all chains is always `<=` to `convert()`ed amount | | |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
| 4 | sum of total supply across all chains is always `<=` to `convert()`ed amount | | |
| 4 | sum of total supply across all chains is always `<=` to `convert()`-ed and `mint()`-ed amount | | |

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I'm not sure I follow you on this one, what mint() are you referring to?

with this property I'm trying to describe the high-level behaviour of the whole system, where the only place where tokens can be minted should be inside convert

I guess we could also define a separate 'Valid State' property local to the supERC20 where we check total supply is the sum of all mints, if we don't get that for free by including ToB ERC20 properties

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm referring to the OptimismSuperchainERC20#mint function, that is only callable by the standard bridge on the L1 -> L2 flow.
Should we take that into consideration when defining the total amount of the token invariant?


| id | description | halmos | echidna |
| ----- | ----- | ----- | ----- |
| 0 | calls to sendERC20 succeed as long as caller has enough balance | | |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
| 0 | calls to sendERC20 succeed as long as caller has enough balance | | |
| 0 | calls to `sendERC20` succeed as long as caller has enough balance | | |

Comment on lines +16 to +18
| 1 | sendERC20 decreases the token's totalSupply in the source chain | | |
| 2 | relayERC20 increases the token's totalSupply in the destination chain | | |
| 3 | only calls to `convert()` can increase the total supply across chains | | |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
| 1 | sendERC20 decreases the token's totalSupply in the source chain | | |
| 2 | relayERC20 increases the token's totalSupply in the destination chain | | |
| 3 | only calls to `convert()` can increase the total supply across chains | | |
| 1 | `sendERC20` decreases the token's total supply in the source chain | | |
| 2 | `relayERC20` increases the token's total supply in the destination chain | | |
| 3 | only calls to `convert()` and `mint()` can increase the total supply across chains | | |


| id | description | halmos | echidna |
| ----- | ----- | ----- | ----- |
| 6 | supERC20 token address does not depend on chainID | | |
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The invariant wouldn't be something like

Suggested change
| 6 | supERC20 token address does not depend on chainID | | |
| 6 | supERC20 token addresses are the same in all the different chains | | |

?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I believe this is currently clearer to map to a halmos proof, like so:

check_addressDoesNotDependOnChainId(remote, name, symbol, decimals, chainId1, chainID2){
  vm.assume(chainId1 != chainId2);
  assertEq(factory.deploy(remote, name, symbol, chainId1),  factory.deploy(remote, name, symbol, chainId2));
}

wdyt? it certainly feels math-ier

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

ah perfect, if that's simpler for halmos let's keep like that

0xiamflux pushed a commit that referenced this pull request Jan 27, 2026
0xOneTony pushed a commit that referenced this pull request Mar 4, 2026
…16 (ethereum-optimism#19271)

Add missing @param blueprint NatSpec to OpcmContractRef struct (#2).
Add comments about pause blocking interop upgrades (#3). Document
migrate() scope limitations and re-migration risks (#7, #15). Update
PERMIT_ALL_CONTRACTS_INSTRUCTION comment (#12). Document intentional
use of chainSystemConfigs[0] for shared contracts (#16).

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
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.

2 participants