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

Foundry test suite #3

Open
wants to merge 51 commits into
base: usds
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
921cac4
foundry fixtures
giovannidisiena Aug 26, 2024
3cf23b6
format contracts
giovannidisiena Aug 26, 2024
99976ab
fix workflow
giovannidisiena Aug 26, 2024
014af80
wip: foundry tests
giovannidisiena Aug 27, 2024
dc2ca76
wip: invariant tests
giovannidisiena Aug 28, 2024
72a37d1
small fix
giovannidisiena Aug 29, 2024
6111e42
avoid stack too deep
giovannidisiena Aug 29, 2024
9274a2a
mock nft generator
giovannidisiena Aug 29, 2024
56ffb30
merge new _swapToRatio impl & rejig stack
giovannidisiena Aug 30, 2024
a4884fc
wip: differential test
giovannidisiena Aug 30, 2024
9b9a132
wip: differential test snapshots
giovannidisiena Aug 30, 2024
0d57879
differential test complete
giovannidisiena Sep 1, 2024
c714172
change out _swapToRatio() implementation
giovannidisiena Sep 1, 2024
fb11d95
almost finished test setup
giovannidisiena Sep 2, 2024
db46686
added fork tests
0ximmeas Sep 4, 2024
8796881
working
giovannidisiena Sep 4, 2024
f35ce50
closer, left to add liquidity in the usdc/usds pool
viktorols Sep 4, 2024
a31f837
more fork testing, still fails though
viktorols Sep 6, 2024
98e5cc1
fix token manager tests
giovannidisiena Sep 7, 2024
5706e8a
more smart vault unit tests
giovannidisiena Sep 7, 2024
44c81f3
remove collateral tests
giovannidisiena Sep 8, 2024
a463a41
fixed deposit yield
viktorols Sep 9, 2024
da5bf3f
support up to 36 decimal tokens in _swapToRatio
viktorols Sep 9, 2024
b2daf54
more concentrated liquidity, removed twap override
viktorols Sep 9, 2024
4744a55
cleanup
viktorols Sep 9, 2024
0a9982b
cleanup
viktorols Sep 9, 2024
84d2225
fix smart vault tests
giovannidisiena Sep 9, 2024
5b45925
changed the test to both deposit and withdraw
viktorols Sep 9, 2024
ef2e58f
format
giovannidisiena Sep 9, 2024
683ca97
Merge branch 'cyfrin-audit/forge-fork-tests' into cyfrin-audit/foundry
giovannidisiena Sep 9, 2024
b71f396
mock unit test commit & forge config
giovannidisiena Sep 9, 2024
51feffc
fixed depositYield and some other tests, withdraw still fails
viktorols Sep 10, 2024
8e45095
added covering in eth for every weth minted
viktorols Sep 10, 2024
11ea64d
almost working for invariants
giovannidisiena Sep 10, 2024
e3a080a
fixed path encoding
giovannidisiena Sep 10, 2024
742b4b9
some tidying before merge
giovannidisiena Sep 11, 2024
3d77030
Merge branch 'cyfrin-audit/foundry-tests-with-mock-pools' into cyfrin…
giovannidisiena Sep 11, 2024
c712b8b
Merge branch 'cyfrin-audit/swap-to-ratio-differential-test' into cyfr…
giovannidisiena Sep 11, 2024
a36b209
fixed PAXG and SUSHI
viktorols Sep 11, 2024
7f7916e
working on fixing diff test
viktorols Sep 12, 2024
a35336d
higher accuracy in the mocked swaps
viktorols Sep 12, 2024
4b1ef44
some cleanup
viktorols Sep 12, 2024
6ed7639
wip invariant tests
giovannidisiena Sep 12, 2024
05f1ff2
be a little bit more allowing to always pass
viktorols Sep 12, 2024
62b0727
more invariants progress
giovannidisiena Sep 13, 2024
b22fd05
invariants – needs more bounding
giovannidisiena Sep 14, 2024
1e42f8c
accounting for pool fee in swap
viktorols Sep 15, 2024
14ec5f5
invariants
giovannidisiena Sep 15, 2024
0ac596c
Merge branch 'cyfrin-audit/foundry-diff-test' into cyfrin-audit/foundry
giovannidisiena Sep 15, 2024
40e8e45
good place to stop invariants
giovannidisiena Sep 15, 2024
2f1a8a4
add readme files
giovannidisiena Sep 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

env:
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Show Forge version
run: |
forge --version

- name: Run Forge fmt
run: |
forge fmt --check
id: fmt

- name: Install npm dependencies
run: |
npm install
id: npmi

- name: Run Forge build
run: |
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test -vvv
id: test
10 changes: 9 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ cache
artifacts

.DS_Store
.idea/
.idea/

# crytic
crytic-export/
echidna/
medusa/

# python
venv/
9 changes: 9 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "lib/chimera"]
path = lib/chimera
url = https://github.com/recon-fuzz/chimera
[submodule "lib/properties"]
path = lib/properties
url = https://github.com/crytic/properties
44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,73 @@
# The Standard: Smart Vaults

## Installation
### Hardhat
If you have npm installed, you can install the required project dependencies
```
npm install
```

### Foundry
If you have Foundry installed, you can install the required project dependencies
```
forge install
```

## Testing
### Hardhat
If you are in root, you can run the project's full test suite
```
npx hardhat test
```
Since this project uses Hardhat, you can use its default ways to run tests, should you prefer it.

### Foundry
```
forge test
```

## Coverage
### Hardhat
Run the code coverage suite with
```
npx hardhat coverage
```

### Foundry
```
forge coverage
```

## Contract size benchmark
Run the contract sizer with
```
npx hardhat size-contracts
```

## Format
Format using the forge formatter with
```
forge fmt
```

## Gas Snapshots
Output gas usage snapshots with
```
forge snapshot
```

## Anvil
Run a local chain with
```
anvil
```

## Chisel
Open a Solidity REPL with
```
chisel
```

## Documentation
- [Testnet guide](docs/TESTNET)
- [Deployed addresses](docs/addresses.json)
11 changes: 7 additions & 4 deletions contracts/PriceCalculator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol" as C
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "contracts/interfaces/IPriceCalculator.sol";

import {console} from "forge-std/console.sol";

contract PriceCalculator is IPriceCalculator {
bytes32 private immutable NATIVE;

constructor (bytes32 _native) {
constructor(bytes32 _native) {
NATIVE = _native;
}

Expand All @@ -19,13 +21,14 @@ contract PriceCalculator is IPriceCalculator {
function tokenToUSD(ITokenManager.Token memory _token, uint256 _tokenValue) external view returns (uint256) {
Chainlink.AggregatorV3Interface tokenUsdClFeed = Chainlink.AggregatorV3Interface(_token.clAddr);
uint256 scaledCollateral = _tokenValue * 10 ** getTokenScaleDiff(_token.symbol, _token.addr);
(,int256 _tokenUsdPrice,,,) = tokenUsdClFeed.latestRoundData();
(, int256 _tokenUsdPrice,,,) = tokenUsdClFeed.latestRoundData();
return scaledCollateral * uint256(_tokenUsdPrice) / 10 ** _token.clDec;
}

function USDToToken(ITokenManager.Token memory _token, uint256 _usdValue) external view returns (uint256) {
Chainlink.AggregatorV3Interface tokenUsdClFeed = Chainlink.AggregatorV3Interface(_token.clAddr);
(, int256 tokenUsdPrice,,,) = tokenUsdClFeed.latestRoundData();
return _usdValue * 10 ** _token.clDec / uint256(tokenUsdPrice) / 10 ** getTokenScaleDiff(_token.symbol, _token.addr);
return _usdValue * 10 ** _token.clDec / uint256(tokenUsdPrice)
/ 10 ** getTokenScaleDiff(_token.symbol, _token.addr);
}
}
}
4 changes: 2 additions & 2 deletions contracts/SmartVaultDeployerV4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ import "contracts/SmartVaultV4.sol";
import "contracts/PriceCalculator.sol";
import "contracts/interfaces/ISmartVaultDeployer.sol";

contract SmartVaultDeployerV4 is ISmartVaultDeployer {
contract SmartVaultDeployerV4 is ISmartVaultDeployer {
bytes32 private immutable NATIVE;
address private immutable priceCalculator;

constructor(bytes32 _native) {
NATIVE = _native;
priceCalculator = address(new PriceCalculator(_native));
}

function deploy(address _manager, address _owner, address _usds) external returns (address) {
return address(new SmartVaultV4(NATIVE, _manager, _owner, _usds, priceCalculator));
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/SmartVaultIndex.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ contract SmartVaultIndex is ISmartVaultIndex, Ownable {
mapping(address => uint256[]) private tokenIds;
mapping(uint256 => address payable) private vaultAddresses;

modifier onlyManager {
modifier onlyManager() {
require(msg.sender == manager, "err-unauthorised");
_;
}
Expand Down
68 changes: 45 additions & 23 deletions contracts/SmartVaultManagerV6.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,15 @@ import "contracts/interfaces/IUSDs.sol";
// TODO describe changes
// TODO upgraded zz/zz/zz
//
contract SmartVaultManagerV6 is ISmartVaultManager, ISmartVaultManagerV2, Initializable, ERC721Upgradeable, OwnableUpgradeable {
contract SmartVaultManagerV6 is
ISmartVaultManager,
ISmartVaultManagerV2,
Initializable,
ERC721Upgradeable,
OwnableUpgradeable
{
using SafeERC20 for IERC20;

uint256 public constant HUNDRED_PC = 1e5;

address public protocol;
Expand All @@ -43,16 +49,32 @@ contract SmartVaultManagerV6 is ISmartVaultManager, ISmartVaultManagerV2, Initia
event VaultLiquidated(address indexed vaultAddress);
event VaultTransferred(uint256 indexed tokenId, address from, address to);

struct SmartVaultData {
uint256 tokenId; uint256 collateralRate; uint256 mintFeeRate;
uint256 burnFeeRate; ISmartVault.Status status;
struct SmartVaultData {
uint256 tokenId;
uint256 collateralRate;
uint256 mintFeeRate;
uint256 burnFeeRate;
ISmartVault.Status status;
}

function initialize(
uint256 _collateralRate, uint256 _feeRate, address _usds, address _protocol, address _liquidator, address _tokenManager,
address _smartVaultDeployer, address _smartVaultIndex, address _nftMetadataGenerator, address _yieldManager, uint16 _userVaultLimit,
address _swapRouter, address _weth
) initializer public {
uint256 _collateralRate,
uint256 _feeRate,
address _usds,
address _protocol,
address _liquidator,
address _tokenManager,
address _smartVaultDeployer,
address _smartVaultIndex,
address _nftMetadataGenerator,
// address _yieldManager,
uint16 _userVaultLimit
)
// address _swapRouter,
// address _weth
public
initializer
{
__ERC721_init("The Standard Smart Vault Manager (USDs)", "TS-VAULTMAN-USDs");
__Ownable_init();
collateralRate = _collateralRate;
Expand All @@ -66,13 +88,13 @@ contract SmartVaultManagerV6 is ISmartVaultManager, ISmartVaultManagerV2, Initia
smartVaultDeployer = _smartVaultDeployer;
smartVaultIndex = ISmartVaultIndex(_smartVaultIndex);
nftMetadataGenerator = _nftMetadataGenerator;
yieldManager = _yieldManager;
// yieldManager = _yieldManager;
userVaultLimit = _userVaultLimit;
swapRouter = _swapRouter;
weth = _weth;
// swapRouter = _swapRouter;
// weth = _weth;
}

modifier onlyLiquidator {
modifier onlyLiquidator() {
require(msg.sender == liquidator, "err-invalid-liquidator");
_;
}
Expand Down Expand Up @@ -129,42 +151,42 @@ contract SmartVaultManagerV6 is ISmartVaultManager, ISmartVaultManagerV2, Initia
}

function setBurnFeeRate(uint256 _rate) external onlyOwner {
burnFeeRate = _rate;
burnFeeRate = _rate;
}

function setSwapFeeRate(uint256 _rate) external onlyOwner {
swapFeeRate = _rate;
}

function setWethAddress(address _weth) external onlyOwner() {
function setWethAddress(address _weth) external onlyOwner {
weth = _weth;
}

function setSwapRouter(address _swapRouter) external onlyOwner() {
function setSwapRouter(address _swapRouter) external onlyOwner {
swapRouter = _swapRouter;
}

function setNFTMetadataGenerator(address _nftMetadataGenerator) external onlyOwner() {
function setNFTMetadataGenerator(address _nftMetadataGenerator) external onlyOwner {
nftMetadataGenerator = _nftMetadataGenerator;
}

function setSmartVaultDeployer(address _smartVaultDeployer) external onlyOwner() {
function setSmartVaultDeployer(address _smartVaultDeployer) external onlyOwner {
smartVaultDeployer = _smartVaultDeployer;
}

function setProtocolAddress(address _protocol) external onlyOwner() {
function setProtocolAddress(address _protocol) external onlyOwner {
protocol = _protocol;
}

function setLiquidatorAddress(address _liquidator) external onlyOwner() {
function setLiquidatorAddress(address _liquidator) external onlyOwner {
liquidator = _liquidator;
}

function setUserVaultLimit(uint16 _userVaultLimit) external onlyOwner() {
function setUserVaultLimit(uint16 _userVaultLimit) external onlyOwner {
userVaultLimit = _userVaultLimit;
}

function setYieldManager(address _yieldManager) external onlyOwner() {
function setYieldManager(address _yieldManager) external onlyOwner {
yieldManager = _yieldManager;
}

Expand All @@ -175,4 +197,4 @@ contract SmartVaultManagerV6 is ISmartVaultManager, ISmartVaultManagerV2, Initia
if (address(_from) != address(0)) ISmartVault(smartVaultIndex.getVaultAddress(_tokenId)).setOwner(_to);
emit VaultTransferred(_tokenId, _from, _to);
}
}
}
Loading
Loading