From 8daa22b772f04921b6b30aaf0795e13e7014dedc Mon Sep 17 00:00:00 2001 From: lakonema2000 <156841739+lakonema2000@users.noreply.github.com> Date: Sat, 1 Jun 2024 18:50:15 +0200 Subject: [PATCH] Add prettier to format solidity code (#19) --- .github/workflows/check.yml | 34 +++++++++++++ .gitignore | 1 + .prettierignore | 2 + git_hooks/pre-commit | 16 ++++-- package-lock.json | 78 +++++++++++++++++++++++++++++ package.json | 22 ++++++++ src/NovaAdapterBase.sol | 37 +++++++------- src/NovaAdapterVelo.sol | 7 ++- src/NovaVault.sol | 40 ++++++++------- src/interfaces/IERC20.sol | 18 +++++-- src/interfaces/INovaAdapterBase.sol | 4 +- src/interfaces/INovaVault.sol | 2 +- src/interfaces/IVelodromePool.sol | 2 +- src/libraries/Errors.sol | 3 +- test/NovaAdapterVelo.t.sol | 51 ++++++++++++------- test/NovaVault.t.sol | 29 +++++++---- 16 files changed, 266 insertions(+), 80 deletions(-) create mode 100644 .github/workflows/check.yml create mode 100644 .prettierignore create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..5156e79 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,34 @@ +name: Code Format Check + +on: + push: + branches: + - main + pull_request: + +jobs: + prettier-check: + runs-on: ubuntu-latest + + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Node.js + uses: actions/setup-node@v4 + with: + node-version: '14' # You can specify any version of Node.js that matches your project requirements + + - name: Cache Node.js modules + uses: actions/cache@v4 + with: + path: ~/.npm + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + + - name: Install dependencies + run: npm install + + - name: Run Prettier check + run: npm run prettier:check diff --git a/.gitignore b/.gitignore index 85198aa..d4dfc4c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Compiler files cache/ out/ +node_modules/ # Ignores development broadcast logs !/broadcast diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..3be8890 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +lib/ +out/ diff --git a/git_hooks/pre-commit b/git_hooks/pre-commit index 1e9929d..8e2dc9c 100644 --- a/git_hooks/pre-commit +++ b/git_hooks/pre-commit @@ -1,20 +1,27 @@ #!/bin/sh +# Get the current branch name branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,') -# Make sure branch != main branch - +# Block commits to the main branch if [ "$branch" = "main" ]; then echo "You are on the main branch. Commit blocked." exit 1 fi -exit 0 +# Run Prettier and add all changed files to the commit +npm run prettier:check +if [ $? -ne 0 ]; then + echo "Prettier found issues that need to be resolved." + exit 1 +fi -# Make sure branch name starts will allowed prefixes +git add -A +# Allowed branch prefixes PREFIXES="feat/ fix/ doc/ chore/ refactor/ test/" +# Check if branch name starts with an allowed prefix for prefix in $PREFIXES; do case $branch in $prefix*) @@ -23,5 +30,6 @@ for prefix in $PREFIXES; do esac done +# If none of the prefixes match, block the commit echo "Commit blocked: Branch name must start with one of the following prefixes: $PREFIXES" exit 1 diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..1af7d9c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,78 @@ +{ + "name": "nova-vault", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "nova-vault", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.17.0.tgz", + "integrity": "sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==", + "dev": true, + "license": "MIT" + }, + "node_modules/prettier": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.5.tgz", + "integrity": "sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-solidity": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.3.1.tgz", + "integrity": "sha512-MN4OP5I2gHAzHZG1wcuJl0FsLS3c4Cc5494bbg+6oQWBPuEamjwDvmGfFMZ6NFzsh3Efd9UUxeT7ImgjNH4ozA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@solidity-parser/parser": "^0.17.0", + "semver": "^7.5.4", + "solidity-comments-extractor": "^0.0.8" + }, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "prettier": ">=2.3.0" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solidity-comments-extractor": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.8.tgz", + "integrity": "sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac5aaa1 --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "nova-vault", + "version": "1.0.0", + "description": "## introduction", + "main": "index.js", + "directories": { + "lib": "lib", + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "prettier:check": "prettier --plugin=prettier-plugin-solidity --check \"src/**/*.sol\" \"test/**/*.sol\" \"script/**/*.sol\"", + "prettier:write": "prettier --plugin=prettier-plugin-solidity --write \"src/**/*.sol\" \"test/**/*.sol\" \"script/**/*.sol\"" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "prettier": "^3.2.5", + "prettier-plugin-solidity": "^1.3.1" + } +} diff --git a/src/NovaAdapterBase.sol b/src/NovaAdapterBase.sol index 1d76ba2..edd4424 100644 --- a/src/NovaAdapterBase.sol +++ b/src/NovaAdapterBase.sol @@ -4,32 +4,28 @@ pragma solidity ^0.8.13; import {IERC20} from "./interfaces/IERC20.sol"; abstract contract NovaAdapterBase { - - error TransferFailed( - address sender, - address recipient, - uint256 amount - ); + error TransferFailed(address sender, address recipient, uint256 amount); address immutable sDAI; address immutable asset; - constructor( - address _asset, - address _sDAI - ) { + constructor(address _asset, address _sDAI) { asset = _asset; sDAI = _sDAI; } function deposit(uint256 assets) external returns (bool, uint256) { - bool successFirst = IERC20(asset).transferFrom(msg.sender, address(this), assets); + bool successFirst = IERC20(asset).transferFrom( + msg.sender, + address(this), + assets + ); (, int256 sDaiOut) = _swap(int256(assets), true); uint256 sDaiToTransfer = uint256(-sDaiOut); bool successSecond = IERC20(sDAI).transfer(msg.sender, sDaiToTransfer); - if(!successFirst || !successSecond){ + if (!successFirst || !successSecond) { revert TransferFailed(msg.sender, address(this), assets); } @@ -37,13 +33,20 @@ abstract contract NovaAdapterBase { } function withdraw(uint256 shares) external returns (bool, uint256) { - bool successFirst = IERC20(sDAI).transferFrom(msg.sender, address(this), shares); + bool successFirst = IERC20(sDAI).transferFrom( + msg.sender, + address(this), + shares + ); (int256 assets, ) = _swap(int256(shares), false); uint256 assetsToTransfer = uint256(-assets); - bool successSecond = IERC20(asset).transfer(msg.sender, assetsToTransfer); + bool successSecond = IERC20(asset).transfer( + msg.sender, + assetsToTransfer + ); - if(!successFirst || !successSecond){ + if (!successFirst || !successSecond) { revert TransferFailed(msg.sender, address(this), assetsToTransfer); } @@ -54,7 +57,7 @@ abstract contract NovaAdapterBase { * @notice Performs a swap operation between the stable asset and sDAI. * @dev This function interacts with the pool to execute the swap. * @param amount The amount to be swapped. - * @param fromStableTosDai A boolean indicating the direction of the swap. + * @param fromStableTosDai A boolean indicating the direction of the swap. * - `true` for swapping from the stable asset to sDAI. * - `false` for swapping from sDAI to the stable asset. * @return amount0 The amount of token0 involved in the swap. @@ -64,4 +67,4 @@ abstract contract NovaAdapterBase { int256 amount, bool fromStableTosDai ) internal virtual returns (int256, int256); -} \ No newline at end of file +} diff --git a/src/NovaAdapterVelo.sol b/src/NovaAdapterVelo.sol index e00232f..6672236 100644 --- a/src/NovaAdapterVelo.sol +++ b/src/NovaAdapterVelo.sol @@ -6,7 +6,6 @@ import {IERC20} from "./interfaces/IERC20.sol"; import {NovaAdapterBase} from "./NovaAdapterBase.sol"; contract NovaAdapterVelo is NovaAdapterBase { - bool private isStableFirst; address immutable veloToken0; address immutable veloToken1; @@ -38,10 +37,10 @@ contract NovaAdapterVelo is NovaAdapterBase { ) external { require(msg.sender == address(veloPool), "Caller is not VelodromePool"); - if (amount0Delta > 0){ + if (amount0Delta > 0) { IERC20(veloToken0).transfer(msg.sender, uint256(amount0Delta)); } - if (amount1Delta > 0){ + if (amount1Delta > 0) { IERC20(veloToken1).transfer(msg.sender, uint256(amount1Delta)); } } @@ -53,7 +52,7 @@ contract NovaAdapterVelo is NovaAdapterBase { (uint160 sqrtPriceX96, , , , , ) = veloPool.slot0(); uint160 num = fromStableTosDai ? 95 : 105; int256 sign = isStableFirst ? int256(1) : int256(-1); - + (int256 amount0, int256 amount1) = veloPool.swap( address(this), fromStableTosDai, diff --git a/src/NovaVault.sol b/src/NovaVault.sol index 7add329..9a6caeb 100644 --- a/src/NovaVault.sol +++ b/src/NovaVault.sol @@ -33,10 +33,7 @@ contract NovaVault is INovaVault { } } - function _approveAdapter( - address stable, - address adapter - ) internal { + function _approveAdapter(address stable, address adapter) internal { require(stable != address(0), Errors.INVALID_ADDRESS); require( @@ -45,7 +42,7 @@ contract NovaVault is INovaVault { ); address underlyingAsset = INovaAdapterBase(adapter).getAsset(); - + require( underlyingAsset == stable, Errors.INVALID_STABLE_TO_ADAPTER_MAPPING @@ -55,12 +52,13 @@ contract NovaVault is INovaVault { emit AdapterApproval(stable, adapter); } - function deposit(address stable, uint256 assets, uint16 referral) external returns (bool, uint256) { + function deposit( + address stable, + uint256 assets, + uint16 referral + ) external returns (bool, uint256) { address adapter = _novaAdapters[stable]; - require( - adapter != address(0), - Errors.NO_ADAPTER_APPROVED - ); + require(adapter != address(0), Errors.NO_ADAPTER_APPROVED); IERC20(stable).transferFrom(msg.sender, address(this), assets); IERC20(stable).approve(adapter, assets); @@ -68,7 +66,10 @@ contract NovaVault is INovaVault { (bool success, bytes memory data) = adapter.call( abi.encodeWithSignature("deposit(uint256)", assets) ); - (bool successDeposit, uint256 sDaiAmount) = abi.decode(data, (bool, uint256)); + (bool successDeposit, uint256 sDaiAmount) = abi.decode( + data, + (bool, uint256) + ); require(success && successDeposit, "Deposit failed"); IERC20(sDAI).transfer(msg.sender, sDaiAmount); @@ -78,12 +79,12 @@ contract NovaVault is INovaVault { return (true, sDaiAmount); } - function withdraw(address stable, uint256 shares) external returns (bool, uint256) { + function withdraw( + address stable, + uint256 shares + ) external returns (bool, uint256) { address adapter = _novaAdapters[stable]; - require( - adapter != address(0), - Errors.NO_ADAPTER_APPROVED - ); + require(adapter != address(0), Errors.NO_ADAPTER_APPROVED); IERC20(sDAI).transferFrom(msg.sender, address(this), shares); IERC20(sDAI).approve(adapter, shares); @@ -91,7 +92,10 @@ contract NovaVault is INovaVault { (bool success, bytes memory data) = adapter.call( abi.encodeWithSignature("withdraw(uint256)", shares) ); - (bool successWithdraw, uint256 assetsAmount) = abi.decode(data, (bool, uint256)); + (bool successWithdraw, uint256 assetsAmount) = abi.decode( + data, + (bool, uint256) + ); require(success && successWithdraw, "Withdraw failed"); @@ -99,4 +103,4 @@ contract NovaVault is INovaVault { return (true, assetsAmount); } -} \ No newline at end of file +} diff --git a/src/interfaces/IERC20.sol b/src/interfaces/IERC20.sol index d38a42a..dcec1a0 100644 --- a/src/interfaces/IERC20.sol +++ b/src/interfaces/IERC20.sol @@ -2,9 +2,19 @@ pragma solidity ^0.8.13; interface IERC20 { - function transfer(address recipient, uint256 amount) external returns (bool); - function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); + function transfer( + address recipient, + uint256 amount + ) external returns (bool); + function transferFrom( + address sender, + address recipient, + uint256 amount + ) external returns (bool); function approve(address spender, uint256 amount) external returns (bool); - function allowance(address owner, address spender) external view returns (uint256); + function allowance( + address owner, + address spender + ) external view returns (uint256); function balanceOf(address account) external view returns (uint256); -} \ No newline at end of file +} diff --git a/src/interfaces/INovaAdapterBase.sol b/src/interfaces/INovaAdapterBase.sol index 82b3845..17d3dee 100644 --- a/src/interfaces/INovaAdapterBase.sol +++ b/src/interfaces/INovaAdapterBase.sol @@ -3,6 +3,6 @@ pragma solidity ^0.8.13; interface INovaAdapterBase { function getAsset() external view returns (address); - function deposit(uint256 assets) external returns (bool , uint256); + function deposit(uint256 assets) external returns (bool, uint256); function withdraw(uint256 shares) external returns (bool, uint256); -} \ No newline at end of file +} diff --git a/src/interfaces/INovaVault.sol b/src/interfaces/INovaVault.sol index d0eb792..b1e34f2 100644 --- a/src/interfaces/INovaVault.sol +++ b/src/interfaces/INovaVault.sol @@ -3,4 +3,4 @@ pragma solidity ^0.8.13; interface INovaVault { event AdapterApproval(address stable, address adapter); -} \ No newline at end of file +} diff --git a/src/interfaces/IVelodromePool.sol b/src/interfaces/IVelodromePool.sol index c2765f1..0e22000 100644 --- a/src/interfaces/IVelodromePool.sol +++ b/src/interfaces/IVelodromePool.sol @@ -25,4 +25,4 @@ interface IVelodromePool { uint16 observationCardinalityNext, bool unlocked ); -} \ No newline at end of file +} diff --git a/src/libraries/Errors.sol b/src/libraries/Errors.sol index 97bd9e6..9a17f29 100644 --- a/src/libraries/Errors.sol +++ b/src/libraries/Errors.sol @@ -1,11 +1,10 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; - library Errors { string public constant INVALID_ADDRESS = "1"; string public constant ADAPTER_ALREADY_APPROVED = "2"; string public constant MISMATCHING_ARRAYS_LENGTH = "3"; string public constant INVALID_STABLE_TO_ADAPTER_MAPPING = "4"; string public constant NO_ADAPTER_APPROVED = "5"; -} \ No newline at end of file +} diff --git a/test/NovaAdapterVelo.t.sol b/test/NovaAdapterVelo.t.sol index 0d50241..362ca81 100644 --- a/test/NovaAdapterVelo.t.sol +++ b/test/NovaAdapterVelo.t.sol @@ -29,14 +29,10 @@ contract NovaAdapterVeloTest is Test { revert("Velodrome pool should be made of `asset` and `sDAI`!"); } - adapter = new NovaAdapterVelo( - underlyingAddress, - sDAI, - POOL - ); + adapter = new NovaAdapterVelo(underlyingAddress, sDAI, POOL); } - function testDeposit() public{ + function testDeposit() public { uint256 aliceUnderlyingAmount = 100 * 1e6; address alice = address(0xABCD); @@ -44,18 +40,26 @@ contract NovaAdapterVeloTest is Test { IERC20(underlyingAddress).transfer(alice, aliceUnderlyingAmount); vm.prank(alice); - IERC20(underlyingAddress).approve(address(adapter), aliceUnderlyingAmount); - assertEq(IERC20(underlyingAddress).allowance(alice, address(adapter)), aliceUnderlyingAmount); + IERC20(underlyingAddress).approve( + address(adapter), + aliceUnderlyingAmount + ); + assertEq( + IERC20(underlyingAddress).allowance(alice, address(adapter)), + aliceUnderlyingAmount + ); vm.prank(alice); - (bool success, uint256 sDaiMinted) = adapter.deposit(aliceUnderlyingAmount); - + (bool success, uint256 sDaiMinted) = adapter.deposit( + aliceUnderlyingAmount + ); + assert(success); assertEq(IERC20(underlyingAddress).balanceOf(alice), 0); assertEq(IERC20(sDAI).balanceOf(alice), sDaiMinted); } - function testWithdraw() public{ + function testWithdraw() public { uint256 aliceUnderlyingAmount = 100 * 1e6; address alice = address(0xABCD); @@ -63,11 +67,19 @@ contract NovaAdapterVeloTest is Test { IERC20(underlyingAddress).transfer(alice, aliceUnderlyingAmount); vm.prank(alice); - IERC20(underlyingAddress).approve(address(adapter), aliceUnderlyingAmount); - assertEq(IERC20(underlyingAddress).allowance(alice, address(adapter)), aliceUnderlyingAmount); + IERC20(underlyingAddress).approve( + address(adapter), + aliceUnderlyingAmount + ); + assertEq( + IERC20(underlyingAddress).allowance(alice, address(adapter)), + aliceUnderlyingAmount + ); vm.prank(alice); - (bool succesDeposit, uint256 sDaiMinted) = adapter.deposit(aliceUnderlyingAmount); + (bool succesDeposit, uint256 sDaiMinted) = adapter.deposit( + aliceUnderlyingAmount + ); assert(succesDeposit); assertEq(IERC20(underlyingAddress).balanceOf(alice), 0); assertEq(IERC20(sDAI).balanceOf(alice), sDaiMinted); @@ -75,10 +87,15 @@ contract NovaAdapterVeloTest is Test { vm.prank(alice); IERC20(sDAI).approve(address(adapter), sDaiMinted); vm.prank(alice); - (bool successWithdraw, uint256 underlyingWithdrawn) = adapter.withdraw(sDaiMinted); + (bool successWithdraw, uint256 underlyingWithdrawn) = adapter.withdraw( + sDaiMinted + ); assert(successWithdraw); - assertEq(IERC20(underlyingAddress).balanceOf(alice), underlyingWithdrawn); + assertEq( + IERC20(underlyingAddress).balanceOf(alice), + underlyingWithdrawn + ); assertEq(IERC20(sDAI).balanceOf(alice), 0); assertEq(IERC20(underlyingAddress).balanceOf(address(adapter)), 0); } -} \ No newline at end of file +} diff --git a/test/NovaVault.t.sol b/test/NovaVault.t.sol index 1e68550..abfb7cf 100644 --- a/test/NovaVault.t.sol +++ b/test/NovaVault.t.sol @@ -34,11 +34,7 @@ contract NovaVaultTest is Test { revert("Velodrome pool should be made of `asset` and `sDAI`!"); } - adapter = new NovaAdapterVelo( - underlyingAddress, - sDAI, - POOL - ); + adapter = new NovaAdapterVelo(underlyingAddress, sDAI, POOL); stables.push(underlyingAddress); novaAdapters.push(address(adapter)); @@ -54,14 +50,24 @@ contract NovaVaultTest is Test { IERC20(underlyingAddress).transfer(alice, aliceUnderlyingAmount); vm.prank(alice); - IERC20(underlyingAddress).approve(address(vault), aliceUnderlyingAmount); - assertEq(IERC20(underlyingAddress).allowance(alice, address(vault)), aliceUnderlyingAmount); + IERC20(underlyingAddress).approve( + address(vault), + aliceUnderlyingAmount + ); + assertEq( + IERC20(underlyingAddress).allowance(alice, address(vault)), + aliceUnderlyingAmount + ); vm.expectEmit(address(vault)); emit Referral(111, alice, aliceUnderlyingAmount); vm.prank(alice); - (bool successDeposit, uint256 sDaiAmount) = vault.deposit(underlyingAddress, aliceUnderlyingAmount, 111); + (bool successDeposit, uint256 sDaiAmount) = vault.deposit( + underlyingAddress, + aliceUnderlyingAmount, + 111 + ); assert(successDeposit); assertEq(IERC20(underlyingAddress).allowance(alice, address(vault)), 0); assertEq(IERC20(underlyingAddress).balanceOf(alice), 0); @@ -72,10 +78,13 @@ contract NovaVaultTest is Test { assertEq(IERC20(sDAI).allowance(alice, address(vault)), sDaiAmount); vm.prank(alice); - (bool successWithdraw, uint256 assetsAmount) = vault.withdraw(underlyingAddress, sDaiAmount); + (bool successWithdraw, uint256 assetsAmount) = vault.withdraw( + underlyingAddress, + sDaiAmount + ); assert(successWithdraw); assertEq(IERC20(sDAI).allowance(alice, address(vault)), 0); assertEq(IERC20(sDAI).balanceOf(alice), 0); assertEq(IERC20(underlyingAddress).balanceOf(alice), assetsAmount); } -} \ No newline at end of file +}