-
Notifications
You must be signed in to change notification settings - Fork 1
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
feat(test): fuzzed and symbolic tests #146
Changes from 14 commits
21bc497
5b1182b
bec1de2
1d0d05d
013f72f
388c657
caf3c62
b01b4e6
3753371
d12abd4
8cde0c0
0d0ca16
87a9acb
e946f09
59c2686
462c38e
68a6b59
fdd4617
cad698a
c143808
a65a9c0
350c39d
c60f5fa
c5c263f
09d332d
888ebe9
0c0e1c4
00cd7d1
ea280d9
5555afc
637aa83
42d2a04
302463c
23a8264
b3f2cf6
5abef51
a793e9d
61a0930
df49eb9
7bbb6cc
9d976ff
b101648
cd1ef62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,3 +19,6 @@ broadcast/*/*/* | |
|
||
# Out dir | ||
out | ||
|
||
# echidna corpuses | ||
**/corpuses/* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
test/smock/* | ||
test/manual-smock/* | ||
test/invariants/* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we need this file? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ¯_(ツ)_/¯ |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,15 +9,16 @@ multiline_func_header = 'params_first' | |
sort_imports = true | ||
|
||
[profile.default] | ||
solc_version = '0.8.25' | ||
wei3erHase marked this conversation as resolved.
Show resolved
Hide resolved
|
||
solc_version = '0.8.23' | ||
libs = ["node_modules", "lib"] | ||
optimizer_runs = 500 | ||
evm_version = 'cancun' | ||
fs_permissions = [{ access = "read-write", path = ".forge-snapshots/"}] | ||
# 2018: function can be view, so far only caused by mocks | ||
# 2394: solc insists on reporting on every transient storage use | ||
# 5574, 3860: bytecode size limit, so far only caused by test contracts | ||
ignored_error_codes = [2018, 2394, 5574, 3860] | ||
# 1858: Some imports don't have the license identifier | ||
ignored_error_codes = [2018, 2394, 5574, 3860, 1878] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WHICH ONES??! 👀 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ToB properties... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1858 or 1878? |
||
deny_warnings = true | ||
|
||
[profile.optimized] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -40,6 +40,7 @@ | |
}, | ||
"dependencies": { | ||
"@cowprotocol/contracts": "github:cowprotocol/contracts.git#a10f40788a", | ||
"@crytic/properties": "https://github.com/crytic/properties.git", | ||
"@openzeppelin/contracts": "5.0.2", | ||
"composable-cow": "github:cowprotocol/composable-cow.git#24d556b", | ||
"solmate": "github:transmissions11/solmate#c892309" | ||
|
@@ -50,7 +51,8 @@ | |
"@defi-wonderland/natspec-smells": "1.1.3", | ||
"@defi-wonderland/smock-foundry": "1.5.0", | ||
"forge-gas-snapshot": "github:marktoda/forge-gas-snapshot#9161f7c", | ||
"forge-std": "github:foundry-rs/forge-std#5475f85", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this will change the deployed build... |
||
"forge-std": "github:foundry-rs/forge-std#1.8.2", | ||
"halmos-cheatcodes": "github:a16z/halmos-cheatcodes#c0d8655", | ||
"husky": ">=8", | ||
"lint-staged": ">=10", | ||
"solhint-community": "4.0.0", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
pragma solidity 0.8.25; | ||
pragma solidity 0.8.23; | ||
|
||
/* | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Tests Summary | ||
|
||
There are 9 solidity files, totalling 939 sloc. | ||
|
||
| filename | language | code | comment | blank | total | | ||
| :---------------------------- | :------- | :--- | :------ | :---- | :---- | | ||
| src/contracts/BCoWConst.sol | solidity | 4 | 10 | 2 | 16 | | ||
| src/contracts/BCoWFactory.sol | solidity | 20 | 13 | 7 | 40 | | ||
| src/contracts/BCoWPool.sol | solidity | 90 | 41 | 24 | 155 | | ||
| src/contracts/BConst.sol | solidity | 23 | 29 | 9 | 61 | | ||
| src/contracts/BFactory.sol | solidity | 44 | 17 | 11 | 72 | | ||
| src/contracts/BMath.sol | solidity | 128 | 156 | 18 | 302 | | ||
| src/contracts/BNum.sol | solidity | 133 | 40 | 28 | 201 | | ||
| src/contracts/BPool.sol | solidity | 473 | 104 | 107 | 684 | | ||
| src/contracts/BToken.sol | solidity | 24 | 27 | 7 | 58 | | ||
|
||
|
||
## Interdependencies | ||
BCoWFactory deploys a bcowpool | ||
BCoWPool is a bpool which adds signature validation | ||
Factory deploys a pool and can "collect" from the pool | ||
Pool inherit btoken (which represents a LP) and bmath | ||
Bmath uses bnum | ||
|
||
# Unit tests | ||
Current coverage is XXX % for the 9 contracts, accross XXX tests. All tests are passing. Unit tests are writtent using the branched-tree technique and Bulloak as templating tool. | ||
simon-something marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
< TABLE > | ||
|
||
# Integration tests | ||
|
||
# Property tests | ||
We identified 24 properties. We challenged these either in a long-running fuzzing campaign (targeting 23 of these in XXX runs) or via symbolic execution (for 8 properties). | ||
|
||
## Fuzzing campaign | ||
|
||
We used echidna to test these 23 properties. In addition to these, another fuzzing campaign as been led against the mathematical contracts (BNum and BMath), insuring the operation properties were holding. | ||
|
||
Limitations/future improvements | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should this be a section? |
||
Currently, the swap logic are tested against the swap in/out functions (and, in a similar way, liquidity management via the join/exit function). The combined equivalent (joinswapExternAmountIn, joinswapPoolAmountOut, etc) should be tested too. | ||
|
||
## Formal verification: Symbolic Execution | ||
We managed to test 10 properties out of the 23. Properties not tested are either not easily challenged with symbolic execution (statefullness needed) or limited by Halmos itself (hitting loops in the implementation for instance). | ||
|
||
Additional properties from BNum were tested independently too (with severe limitations due to loop unrolling boundaries). | ||
|
||
|
||
## Notes | ||
The bmath corresponding equations are: | ||
|
||
`Spot price:` | ||
$\text{spotPrice} = \frac{\text{tokenBalanceIn}/\text{tokenWeightIn}}{\text{tokenBalanceOut}/\text{tokenWeightOut}} \cdot \frac{1}{1 - \text{swapFee}}$ | ||
|
||
|
||
`Out given in:` | ||
$\text{tokenAmountOut} = \text{tokenBalanceOut} \cdot \left( 1 - \left( \frac{\text{tokenBalanceIn}}{\text{tokenBalanceIn} + \left( \text{tokenAmountIn} \cdot \left(1 - \text{swapFee}\right)\right)} \right)^{\frac{\text{tokenWeightIn}}{\text{tokenWeightOut}}} \right)$ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this expression doesn't seem to be renderable Also, perhaps expressions as blocks would be easier to read? text in inline expressions gets real small There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. true true |
||
|
||
|
||
`In given out:` | ||
$\text{tokenAmountIn} = \frac{\text{tokenBalanceIn} \cdot \left( \frac{\text{tokenBalanceOut}}{\text{tokenBalanceOut} - \text{tokenAmountOut}} \right)^{\frac{\text{tokenWeightOut}}{\text{tokenWeightIn}}} - 1}{1 - \text{swapFee}}$ | ||
|
||
|
||
`Pool out given single in` | ||
$\text{poolAmountOut} = \left(\frac{\text{tokenAmountIn} \cdot \left(1 - \left(1 - \frac{\text{tokenWeightIn}}{\text{totalWeight}}\right) \cdot \text{swapFee}\right) + \text{tokenBalanceIn}}{\text{tokenBalanceIn}}\right)^{\frac{\text{tokenWeightIn}}{\text{totalWeight}}} \cdot \text{poolSupply} - \text{poolSupply}$ | ||
|
||
|
||
`Single in given pool out` | ||
$\text{tokenAmountIn} = \frac{\left(\frac{\text{poolSupply} + \text{poolAmountOut}}{\text{poolSupply}}\right)^{\frac{1}{\frac{\text{weightIn}}{\text{totalWeight}}}} \cdot \text{balanceIn} - \text{balanceIn}}{\left(1 - \frac{\text{weightIn}}{\text{totalWeight}}\right) \cdot \text{swapFee}}$ | ||
|
||
|
||
`Single out given pool in` | ||
$\text{tokenAmountOut} = \left( \text{tokenBalanceOut} - \left( \frac{\text{poolSupply} - \left(\text{poolAmountIn} \cdot \left(1 - \text{exitFee}\right)\right)}{\text{poolSupply}} \right)^{\frac{1}{\frac{\text{tokenWeightOut}}{\text{totalWeight}}}} \cdot \text{tokenBalanceOut} \right) \cdot \left(1 - \left(1 - \frac{\text{tokenWeightOut}}{\text{totalWeight}}\right) \cdot \text{swapFee}\right)$ | ||
|
||
|
||
`Pool in given single out` | ||
$\text{poolAmountIn} = \frac{\text{poolSupply} - \left( \frac{\text{tokenBalanceOut} - \frac{\text{tokenAmountOut}}{1 - \left(1 - \frac{\text{tokenWeightOut}}{\text{totalWeight}}\right) \cdot \text{swapFee}}}{\text{tokenBalanceOut}} \right)^{\frac{\text{tokenWeightOut}}{\text{totalWeight}}} \cdot \text{poolSupply}}{1 - \text{exitFee}}$ | ||
|
||
|
||
BNum bpow is based on exponentiation by squaring and hold true because (see dapphub dsmath): https://github.com/dapphub/ds-math/blob/e70a364787804c1ded9801ed6c27b440a86ebd32/src/math.sol#L62 | ||
``` | ||
// If n is even, then x^n = (x^2)^(n/2). | ||
// If n is odd, then x^n = x * x^(n-1), | ||
// and applying the equation for even x gives | ||
// x^n = x * (x^2)^((n-1) / 2). | ||
// | ||
// Also, EVM division is flooring and | ||
// floor[(n-1) / 2] = floor[n / 2]. | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there are not that many warnings, we could disable some rules (such as
custom-errors
) for the entire directory and add a few inline ignores (in the case ofno-empty-blocks
, for example)