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

Feat/univ3 multisig #204

Open
wants to merge 37 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
0306383
fix: impersonate function
MisterMard Sep 24, 2022
ac16022
add velo usdc-tusd strategy
MisterMard Sep 24, 2022
9c5765e
add prettier rules for typescript
MisterMard Sep 24, 2022
53d46b7
optimism chainlink keeper
MisterMard Oct 4, 2022
e77a829
add multiple strats to keeper watchlist at once
MisterMard Oct 5, 2022
dab7912
add beetx ib-reth strategy
MisterMard Oct 5, 2022
e424003
fix: fix strategist address for v3 keeper test
MisterMard Oct 29, 2022
9843ed9
fix: chainlinkKeeper test typo
MisterMard Nov 8, 2022
8288d77
Minichef proxy contract
MisterMard Nov 8, 2022
473aa22
chef proxy test cleanup
MisterMard Nov 21, 2022
6f006a6
INITIAL
MisterMard Nov 25, 2022
abb4b2e
fix: accurate univ3 rebalances
MisterMard Dec 5, 2022
37bb7d9
remove duplicate polygon univ3 bases and interfaces
MisterMard Dec 5, 2022
df8a436
fix: less ambiguous cache variable names
MisterMard Dec 12, 2022
4e6049a
fix: more accurate rebalance implementation
MisterMard Jan 30, 2023
7250527
fix: univ3 jar and strategy uses the correct calculation for users de…
MisterMard Feb 12, 2023
dced5a3
chore: duplicate v3 jar so it can compile, root src requires much cle…
MisterMard Feb 12, 2023
fdeda00
fix: arbitrum univ3 strategies
MisterMard Feb 12, 2023
d3d0b2c
fix: optimism univ3 strategies
MisterMard Feb 12, 2023
2bf7d62
fix: mainnet univ3 strategies
MisterMard Feb 16, 2023
a26ec43
adjust the default performance fees for univ3 strategies to 20%
MisterMard Feb 16, 2023
41e655b
fix: polygon univ3 strategies
MisterMard Feb 16, 2023
35087c8
add deployer script files
MisterMard Feb 16, 2023
38fbace
add v3 migration script
MisterMard Feb 16, 2023
280170c
fix: typos
MisterMard Feb 16, 2023
bfa7b10
fix: univ3 jar users shares calculation upon deposits
MisterMard Feb 25, 2023
542337f
restructure strategy-base-v2
MisterMard Mar 26, 2023
4e079ab
remove problematic jar converters tests
MisterMard Mar 26, 2023
75d1cce
add new velo strategies
MisterMard Mar 26, 2023
f6379ff
add base strategy for sushi bento pools
MisterMard Mar 26, 2023
84fb18d
add base unit test for sushi strategies
MisterMard Mar 26, 2023
0ff4dd1
add arbitrum sushi strategies and tests
MisterMard Mar 26, 2023
1dd6fe2
add polygon sushi strategies and tests
MisterMard Mar 27, 2023
6a63c0c
add kava sushi strategies and tests
MisterMard Mar 27, 2023
c0f15e0
add optimism sushi strategies and tests
MisterMard Mar 27, 2023
b57b8dc
delete optimism v3 jar code
MisterMard Mar 29, 2023
d5097e1
fix: saddle d4 strategy swap native through a better route
MisterMard Apr 13, 2023
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,5 @@ out.sol
out.sol
pickleJarOut.sol

typechain-types/
typechain-types/
.vim
24 changes: 10 additions & 14 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
{
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
"explicitTypes": "always",
"overrides": [
{
"files": "*.sol",
"options": {
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
"explicitTypes": "always"
"tabWidth": 4
}
},
{
"files": "*.js",
"files": "*.ts",
"options": {
"printWidth": 120,
"tabWidth": 2,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false,
"explicitTypes": "always"
"parser": "typescript"
}
}
]
}
}
17 changes: 9 additions & 8 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,11 @@ const config: HardhatUserConfig = {
networks: {
hardhat: {
forking: {
url: `https://evm.kava.io`,
// ignoreUnknownTxType: true, // needed to work with patched Hardhat + Arbitrum Nitro
blockNumber: 2464633,
url: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY_POLYGON}`,
blockNumber: 35318702,//35366299,
},
chainId: 137,

accounts: {
mnemonic: process.env.MNEMONIC,
},
Expand All @@ -50,7 +51,7 @@ const config: HardhatUserConfig = {
// },
hardfork: "london",
gasPrice: "auto",
gas: 6500000,
blockGasLimit: 30_000_000,
},
mainnet: {
// url: `https://rpc.flashbots.net`,
Expand All @@ -59,7 +60,7 @@ const config: HardhatUserConfig = {
chainId: 1,
},
matic: {
url: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY_MATIC}`,
url: `https://polygon-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY_POLYGON}`,
accounts: [process.env.PRIVATE_KEY ?? ""],
chainId: 137,
},
Expand Down Expand Up @@ -110,16 +111,16 @@ const config: HardhatUserConfig = {
},
etherscan: {
apiKey: {
mainnet: process.env.ETHERSCAN_APIKEY ?? "",
aurora: process.env.AURORASCAN_APIKEY ?? "",
mainnet: process.env.ETHERSCAN_APIKEY_ETHEREUM ?? "",
aurora: process.env.ETHERSCAN_APIKEY_AURORA ?? "",
xdai: process.env.BLOCKSCOUT_APIKEY_GNOSIS ?? "",
optimisticEthereum: process.env.ETHERSCAN_APIKEY_OPTIMISM ?? "",
arbitrumOne: process.env.ETHERSCAN_APIKEY_ARBISCAN ?? "",
opera: process.env.ETHERSCAN_APIKEY_FANTOM ?? "",
},
},
paths: {
sources: "./src/strategies/kava",
sources: "./src/strategies/polygon",
tests: "./src/tests/strategies",
cache: "./cache",
artifacts: "./artifacts",
Expand Down
23 changes: 13 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
"dill:wait": "npx hardhat run ./hardhat-scripts/dill-test/3.wait.js --network localhost"
},
"devDependencies": {
"@ethersproject/abi": "^5.6.4",
"@ethersproject/hardware-wallets": "^5.6.1",
"@ethersproject/providers": "^5.6.8",
"@gnosis.pm/safe-core-sdk": "^3.1.1",
"@gnosis.pm/safe-ethers-lib": "^1.6.1",
"@ethersproject/abi": "^5.7.0",
"@ethersproject/bytes": "^5.7.0",
"@ethersproject/hardware-wallets": "^5.7.0",
"@ethersproject/providers": "^5.7.2",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.2",
"@nomicfoundation/hardhat-network-helpers": "^1.0.3",
"@nomicfoundation/hardhat-toolbox": "^1.0.2",
Expand All @@ -28,27 +31,27 @@
"@openzeppelin/contracts": "^3.4.1",
"@openzeppelin/contracts-upgradeable": "^3.4.1",
"@openzeppelin/test-helpers": "^0.5.10",
"@typechain/ethers-v5": "^10.1.0",
"@typechain/hardhat": "^6.1.2",
"@typechain/ethers-v5": "^10.1.1",
"@typechain/hardhat": "^6.1.4",
"@types/chai": "^4.3.1",
"@types/mocha": "^9.1.1",
"@types/node": "^18.6.2",
"bn.js": "^5.2.1",
"bn.js": "^4.2.1",
"chai": "^4.3.4",
"dotenv": "^8.2.0",
"eslint": "^7.10.0",
"ethers": "^5.1.3",
"hardhat": "npm:@gzeoneth/[email protected]",
"ethers": "^5.7.2",
"hardhat": "^2.12.2",
"hardhat-contract-sizer": "^2.1.1",
"hardhat-deploy": "^0.11.12",
"hardhat-deploy": "^0.11.20",
"hardhat-gas-reporter": "^1.0.4",
"hardhat-preprocessor": "^0.1.4",
"mocha": "^9.0.2",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.9",
"solidity-coverage": "^0.7.16",
"ts-node": "^10.9.1",
"typechain": "^8.1.0",
"typechain": "^8.1.1",
"typescript": "^4.7.4",
"web3": "^1.7.4"
},
Expand Down
3 changes: 1 addition & 2 deletions src/interfaces/controllerv2.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;
pragma solidity >=0.6.12;

interface IControllerV2 {
function jars(address) external view returns (address);
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/univ3/IERC165.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;
pragma solidity >=0.6.12;

/**
* @dev Interface of the ERC165 standard, as defined in the
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/univ3/IERC721.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.12;
pragma solidity >=0.6.12;

import "./IERC165.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/univ3/ISwapRouter02.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.6.12;
pragma solidity >=0.6.12;
pragma experimental ABIEncoderV2;

/// @title Router token swapping functionality
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/univ3/IUniswapV3PositionsNFT.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.6.12;
pragma solidity >=0.6.12;
pragma experimental ABIEncoderV2;

import "./IERC721.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/univ3/IUniswapV3Staker.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.6.12;
pragma solidity >=0.6.12;
pragma experimental ABIEncoderV2;

import "./IUniswapV3Pool.sol";
Expand Down
1 change: 0 additions & 1 deletion src/lib/context.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0;

/*
Expand Down
4 changes: 2 additions & 2 deletions src/lib/univ3/FullMath.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
pragma solidity >=0.4.0 <0.8.0;

/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
Expand Down Expand Up @@ -121,4 +121,4 @@ library FullMath {
result++;
}
}
}
}
2 changes: 1 addition & 1 deletion src/lib/univ3/LowGasSafeMath.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.6.12;
pragma solidity >=0.6.12;

/// @title Optimized overflow and underflow safe math operations
/// @notice Contains methods for doing math operations that revert on overflow or underflow for minimal gas cost
Expand Down
2 changes: 1 addition & 1 deletion src/lib/univ3/PoolActions.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.6.12;
pragma solidity >=0.6.12;
pragma experimental ABIEncoderV2;

import "../../interfaces/univ3/IUniswapV3Pool.sol";
Expand Down
4 changes: 2 additions & 2 deletions src/lib/univ3/TickMath.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.6.0;
pragma solidity >=0.5.0 <0.8.0;

/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
Expand Down Expand Up @@ -202,4 +202,4 @@ library TickMath {

tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
}
}
}
131 changes: 131 additions & 0 deletions src/optimism/chainlinkKeeper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./interfaces/chainlink/AutomationCompatibleInterface.sol";
import "./interfaces/strategyv2.sol";
import "./interfaces/univ3/pool/IUniswapV3PoolState.sol";

contract PickleRebalancingKeeper is AutomationCompatibleInterface {
address[] public strategies;
address public keeperRegistry = 0x75c0530885F385721fddA23C539AF3701d6183D4;
int24 public threshold = 10;

address public governance;
bool public disabled = false;

modifier onlyGovernance() {
require(msg.sender == governance, "!Governance");
_;
}

modifier whenNotDisabled() {
require(!disabled, "Disabled");
_;
}

constructor(address _governance) {
governance = _governance;
}

function strategiesLength() external view returns(uint256 length) {
length = strategies.length;
}

function setGovernance(address _governance) external onlyGovernance {
governance = _governance;
}

function setKeeperRegistry(address _keeperRegistry) external onlyGovernance {
keeperRegistry = _keeperRegistry;
}

function setThreshold(int24 _threshold) external onlyGovernance {
threshold = _threshold;
}

function setDisabled(bool _disabled) external onlyGovernance {
disabled = _disabled;
}

function addStrategies(address[] calldata _addresses) external onlyGovernance {
for (uint256 i = 0; i < _addresses.length; i++) {
require(!_search(_addresses[i]), "Address Already Watched");
strategies.push(_addresses[i]);
}
}

function removeStrategy(address _address) external onlyGovernance {
require(_search(_address), "Address Not Watched");

for (uint256 i = 0; i < strategies.length; i++) {
if (strategies[i] == _address) {
strategies[i] = strategies[strategies.length - 1];
strategies.pop();
break;
}
}
}

function checkUpkeep(bytes calldata)
external
view
override
whenNotDisabled
returns (bool upkeepNeeded, bytes memory performData)
{
address[] memory _stratsToUpkeep = new address[](strategies.length);

uint24 counter = 0;
for (uint256 i = 0; i < strategies.length; i++) {
bool shouldRebalance = _checkValidToCall(strategies[i]);
if (shouldRebalance == true) {
_stratsToUpkeep[counter] = strategies[i];
upkeepNeeded = true;
counter++;
}
}

if (upkeepNeeded == true) {
address[] memory stratsToUpkeep = new address[](counter);
for (uint256 i = 0; i < counter; i++) {
stratsToUpkeep[i] = _stratsToUpkeep[i];
}
performData = abi.encode(stratsToUpkeep);
}
}

function performUpkeep(bytes calldata performData) external override whenNotDisabled {
address[] memory stratsToUpkeep = abi.decode(performData, (address[]));

for (uint24 i = 0; i < stratsToUpkeep.length; i++) {
require(_checkValidToCall(stratsToUpkeep[i]), "!Valid");
IStrategyV2(stratsToUpkeep[i]).rebalance();
}
}

function _search(address _address) internal view returns (bool) {
for (uint256 i = 0; i < strategies.length; i++) {
if (strategies[i] == _address) {
return true;
}
}
return false;
}

function _checkValidToCall(address _strategy) internal view returns (bool) {
require(_search(_strategy), "Address Not Watched");

int24 _lowerTick = IStrategyV2(_strategy).tick_lower();
int24 _upperTick = IStrategyV2(_strategy).tick_upper();
int24 _range = _upperTick - _lowerTick;
int24 _limitVar = _range / threshold;
int24 _lowerLimit = _lowerTick + _limitVar;
int24 _upperLimit = _upperTick - _limitVar;

(, int24 _currentTick, , , , , ) = IUniswapV3PoolState(IStrategyV2(_strategy).pool()).slot0();
if (_currentTick < _lowerLimit || _currentTick > _upperLimit) {
return true;
}
return false;
}
}
Loading