From f376059e0365ab6290e9d00ac398b49013c9b4ea Mon Sep 17 00:00:00 2001 From: Mati Date: Tue, 23 May 2023 13:58:43 -0300 Subject: [PATCH] Add foundry for invariant testing --- .gitmodules | 3 +++ foundry.toml | 15 ++++++++++++ hardhat.config.ts | 1 + lib/forge-std | 1 + package-lock.json | 22 +++++++++++++++++ package.json | 3 ++- remappings.txt | 7 ++++++ test/USDMTest.t.sol | 59 +++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 .gitmodules create mode 100644 foundry.toml create mode 160000 lib/forge-std create mode 100644 remappings.txt create mode 100644 test/USDMTest.t.sol diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..888d42d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "lib/forge-std"] + path = lib/forge-std + url = https://github.com/foundry-rs/forge-std diff --git a/foundry.toml b/foundry.toml new file mode 100644 index 0000000..ea3272d --- /dev/null +++ b/foundry.toml @@ -0,0 +1,15 @@ +[profile.default] +src = 'contracts' +out = 'out' +libs = ['node_modules', 'lib'] +test = 'test' +cache_path = 'cache_forge' +solc = '0.8.18' + +[fuzz] +runs = 1_000 +depth = 100 + +# Extreme Fuzzing CI Profile +[profile.ci] +runs = 100_000 diff --git a/hardhat.config.ts b/hardhat.config.ts index 961d6f7..0bb1520 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,6 +1,7 @@ import { HardhatUserConfig } from 'hardhat/config'; import '@nomicfoundation/hardhat-toolbox'; import '@nomicfoundation/hardhat-chai-matchers'; +import "@nomicfoundation/hardhat-foundry"; import '@openzeppelin/hardhat-upgrades'; import dotenv from 'dotenv'; diff --git a/lib/forge-std b/lib/forge-std new file mode 160000 index 0000000..fc560fa --- /dev/null +++ b/lib/forge-std @@ -0,0 +1 @@ +Subproject commit fc560fa34fa12a335a50c35d92e55a6628ca467c diff --git a/package-lock.json b/package-lock.json index e06f6b5..732531b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ }, "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", + "@nomicfoundation/hardhat-foundry": "^1.0.1", "@nomicfoundation/hardhat-toolbox": "^2.0.1", "@openzeppelin/hardhat-upgrades": "^1.22.1", "@openzeppelin/test-helpers": "^0.5.16", @@ -1851,6 +1852,18 @@ "hardhat": "^2.9.4" } }, + "node_modules/@nomicfoundation/hardhat-foundry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-foundry/-/hardhat-foundry-1.0.1.tgz", + "integrity": "sha512-sQEaX3rik6Gclmek4MqCyOc9+vOM0ZS40eUARrB6K9t6wthqCwJ29CClfxLdbrjn/3MM5hX8ioD+/9OqdGVxSQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2" + }, + "peerDependencies": { + "hardhat": "^2.12.6" + } + }, "node_modules/@nomicfoundation/hardhat-network-helpers": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.7.tgz", @@ -16153,6 +16166,15 @@ "ordinal": "^1.0.3" } }, + "@nomicfoundation/hardhat-foundry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-foundry/-/hardhat-foundry-1.0.1.tgz", + "integrity": "sha512-sQEaX3rik6Gclmek4MqCyOc9+vOM0ZS40eUARrB6K9t6wthqCwJ29CClfxLdbrjn/3MM5hX8ioD+/9OqdGVxSQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + } + }, "@nomicfoundation/hardhat-network-helpers": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.7.tgz", diff --git a/package.json b/package.json index 0b8f018..565fcbc 100644 --- a/package.json +++ b/package.json @@ -20,13 +20,14 @@ "url": "git+https://github.com/mountainprotocol/tokens.git" }, "author": "Mati ", - "license": "UNLICENSED", + "license": "MIT", "bugs": { "url": "https://github.com/mountainprotocol/tokens/issues" }, "homepage": "https://github.com/mountainprotocol/tokens#readme", "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "^1.0.6", + "@nomicfoundation/hardhat-foundry": "^1.0.1", "@nomicfoundation/hardhat-toolbox": "^2.0.1", "@openzeppelin/hardhat-upgrades": "^1.22.1", "@openzeppelin/test-helpers": "^0.5.16", diff --git a/remappings.txt b/remappings.txt new file mode 100644 index 0000000..80e1180 --- /dev/null +++ b/remappings.txt @@ -0,0 +1,7 @@ +@ensdomains/=node_modules/@ensdomains/ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ +@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/ +ds-test/=lib/forge-std/lib/ds-test/src/ +eth-gas-reporter/=node_modules/eth-gas-reporter/ +forge-std/=lib/forge-std/src/ +hardhat/=node_modules/hardhat/ diff --git a/test/USDMTest.t.sol b/test/USDMTest.t.sol new file mode 100644 index 0000000..c19b8d2 --- /dev/null +++ b/test/USDMTest.t.sol @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +import {Test} from "forge-std/Test.sol"; +import {console} from "forge-std/console.sol"; +import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +import "../contracts/USDM.sol"; + +contract UUPSProxy is ERC1967Proxy { + constructor(address _implementation, bytes memory _data) + ERC1967Proxy(_implementation, _data) + {} +} + +contract Handler { + USDM public usdm; + + constructor(USDM _usdm) { + usdm = _usdm; + } +} + +contract USDMInvariants is Test { + USDM implementation; + UUPSProxy proxy; + USDM usdm; + Handler handler; + + function setUp() public { + // deploy implementation contract + implementation = new USDM(); + + // deploy proxy contract and point it to implementation + proxy = new UUPSProxy(address(implementation), ""); + + // wrap in ABI to support easier calls + usdm = USDM(address(proxy)); + + usdm.initialize("Mountain Protocol USD", "USDM", 0); + + handler = new Handler(usdm); + + // targetContract(address(handler)); + // targetContract(address(implementation)); + } + + function invariant_totalSupply() public { + assertEq(usdm.balanceOf(address(this)), usdm.totalSupply()); + } + + function invariant_totalShares() public { + assertEq(usdm.sharesOf(address(this)), usdm.totalShares()); + } + + function invariant_totalShares_totalSupply() public { + assertEq(usdm.totalSupply(), usdm.totalShares()); + } +}