From 4ebc0bf8d1746466286b4ef51e1bc8d96654e315 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Fri, 22 Sep 2023 17:46:42 -0600 Subject: [PATCH 01/26] implement mint cover callback --- ...wapCallback.sol => ICoverPoolCallback.sol} | 14 ++ ...wapCallback.sol => ILimitPoolCallback.sol} | 13 ++ contracts/interfaces/cover/ICoverPool.sol | 6 + contracts/interfaces/limit/ILimitPool.sol | 33 +-- .../interfaces/limit/ILimitPoolFactory.sol | 23 ++ contracts/interfaces/range/IRangePool.sol | 42 ++++ .../interfaces/structs/PoolsharkStructs.sol | 51 ++++ contracts/libraries/pool/MintCall.sol | 47 +++- contracts/libraries/pool/SwapCall.sol | 2 +- contracts/utils/PoolsharkRouter.sol | 221 +++++++++++++----- test/contracts/coverpool.ts | 1 + test/utils/contracts/coverpool.ts | 50 ++-- 12 files changed, 409 insertions(+), 94 deletions(-) rename contracts/interfaces/callbacks/{ICoverPoolSwapCallback.sol => ICoverPoolCallback.sol} (58%) rename contracts/interfaces/callbacks/{ILimitPoolSwapCallback.sol => ILimitPoolCallback.sol} (58%) create mode 100644 contracts/interfaces/limit/ILimitPoolFactory.sol create mode 100644 contracts/interfaces/range/IRangePool.sol diff --git a/contracts/interfaces/callbacks/ICoverPoolSwapCallback.sol b/contracts/interfaces/callbacks/ICoverPoolCallback.sol similarity index 58% rename from contracts/interfaces/callbacks/ICoverPoolSwapCallback.sol rename to contracts/interfaces/callbacks/ICoverPoolCallback.sol index 4bf4f022..bd33aa50 100644 --- a/contracts/interfaces/callbacks/ICoverPoolSwapCallback.sol +++ b/contracts/interfaces/callbacks/ICoverPoolCallback.sol @@ -1,6 +1,20 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.13; +/// @title Callback for mints +/// @notice Any contract that calls the `mint` function must implement this interface. +interface ICoverPoolMintCallback { + /// @notice Called to `msg.sender` after executing a mint. + /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. + /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. + function coverPoolMintCallback( + int256 amount0Delta, + int256 amount1Delta, + bytes calldata data + ) external; +} + + /// @title Callback for swaps /// @notice Any contract that calls the `swap` function must implement this interface. interface ICoverPoolSwapCallback { diff --git a/contracts/interfaces/callbacks/ILimitPoolSwapCallback.sol b/contracts/interfaces/callbacks/ILimitPoolCallback.sol similarity index 58% rename from contracts/interfaces/callbacks/ILimitPoolSwapCallback.sol rename to contracts/interfaces/callbacks/ILimitPoolCallback.sol index fb0a99ac..f98d56c7 100644 --- a/contracts/interfaces/callbacks/ILimitPoolSwapCallback.sol +++ b/contracts/interfaces/callbacks/ILimitPoolCallback.sol @@ -1,6 +1,19 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.13; +/// @title Callback for mints +/// @notice Any contract that calls the `mint` function must implement this interface. +interface ILimitPoolMintCallback { + /// @notice Called to `msg.sender` after executing a mint. + /// @param amount0Delta The amount of token0 either received by (positive) or sent from (negative) the user. + /// @param amount1Delta The amount of token1 either received by (positive) or sent from (negative) the user. + function limitPoolMintCallback( + int256 amount0Delta, + int256 amount1Delta, + bytes calldata data + ) external; +} + /// @title Callback for swaps /// @notice Any contract that calls the `swap` function must implement this interface. interface ILimitPoolSwapCallback { diff --git a/contracts/interfaces/cover/ICoverPool.sol b/contracts/interfaces/cover/ICoverPool.sol index d1cc2167..3d80e4aa 100644 --- a/contracts/interfaces/cover/ICoverPool.sol +++ b/contracts/interfaces/cover/ICoverPool.sol @@ -50,6 +50,12 @@ interface ICoverPool is CoverPoolStructs { * @notice False if depositing token1, the second token address in lexographical order */ bool zeroForOne; + + /** + * @custom:field callbackData + * @notice callback data which gets passed back to msg.sender at the end of a `mint` call + */ + bytes callbackData; } /** diff --git a/contracts/interfaces/limit/ILimitPool.sol b/contracts/interfaces/limit/ILimitPool.sol index 48f4e579..03429ed3 100644 --- a/contracts/interfaces/limit/ILimitPool.sol +++ b/contracts/interfaces/limit/ILimitPool.sol @@ -4,20 +4,27 @@ pragma solidity 0.8.13; import '../structs/PoolsharkStructs.sol'; interface ILimitPool is PoolsharkStructs { - function immutables() external view returns (LimitImmutables memory); - - function swap( - SwapParams memory params - ) external returns ( - int256 amount0, - int256 amount1 + function initialize( + uint160 startPrice + ) external; + + function mintLimit( + MintLimitParams memory params + ) external; + + function burnLimit( + BurnLimitParams memory params + ) external; + + function immutables( + ) external view returns( + LimitImmutables memory ); - function quote( - QuoteParams memory params - ) external view returns ( - int256 inAmount, - int256 outAmount, - uint160 priceAfter + function priceBounds( + int16 tickSpacing + ) external pure returns ( + uint160 minPrice, + uint160 maxPrice ); } diff --git a/contracts/interfaces/limit/ILimitPoolFactory.sol b/contracts/interfaces/limit/ILimitPoolFactory.sol new file mode 100644 index 00000000..d8302452 --- /dev/null +++ b/contracts/interfaces/limit/ILimitPoolFactory.sol @@ -0,0 +1,23 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.13; + +import '../structs/PoolsharkStructs.sol'; + +abstract contract ILimitPoolFactory is PoolsharkStructs { + function createLimitPool( + LimitPoolParams memory params + ) external virtual returns ( + address pool, + address poolToken + ); + + function getLimitPool( + bytes32 poolType, + address tokenIn, + address tokenOut, + uint16 swapFee + ) external view virtual returns ( + address pool, + address poolToken + ); +} diff --git a/contracts/interfaces/range/IRangePool.sol b/contracts/interfaces/range/IRangePool.sol new file mode 100644 index 00000000..a4381c2d --- /dev/null +++ b/contracts/interfaces/range/IRangePool.sol @@ -0,0 +1,42 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.13; + +import '../structs/PoolsharkStructs.sol'; + +interface IRangePool is PoolsharkStructs { + function mintRange( + MintRangeParams memory mintParams + ) external; + + function burnRange( + BurnRangeParams memory burnParams + ) external; + + function swap( + SwapParams memory params + ) external returns ( + int256 amount0, + int256 amount1 + ); + + function quote( + QuoteParams memory params + ) external view returns ( + uint256 inAmount, + uint256 outAmount, + uint160 priceAfter + ); + + function snapshotRange( + uint32 positionId + ) external view returns( + int56 tickSecondsAccum, + uint160 secondsPerLiquidityAccum, + uint128 feesOwed0, + uint128 feesOwed1 + ); + + function increaseSampleLength( + uint16 sampleLengthNext + ) external; +} diff --git a/contracts/interfaces/structs/PoolsharkStructs.sol b/contracts/interfaces/structs/PoolsharkStructs.sol index 698146c9..bb169435 100644 --- a/contracts/interfaces/structs/PoolsharkStructs.sol +++ b/contracts/interfaces/structs/PoolsharkStructs.sol @@ -50,6 +50,57 @@ interface PoolsharkStructs { uint160 priceAfter; } + struct LimitPoolParams { + bytes32 poolType; + address tokenIn; + address tokenOut; + uint160 startPrice; + uint16 swapFee; + } + + struct MintLimitParams { + address to; + uint128 amount; + uint96 mintPercent; + uint32 positionId; + int24 lower; + int24 upper; + bool zeroForOne; + bytes callbackData; + } + + struct BurnLimitParams { + address to; + uint128 burnPercent; + uint32 positionId; + int24 claim; + bool zeroForOne; + } + + struct MintRangeParams { + address to; + int24 lower; + int24 upper; + uint32 positionId; + uint128 amount0; + uint128 amount1; + bytes callbackData; + } + + struct BurnRangeParams { + address to; + uint32 positionId; + uint128 burnPercent; + } + + struct SnapshotLimitParams { + address owner; + uint128 burnPercent; + uint32 positionId; + int24 claim; + bool zeroForOne; + } + /** * @custom:struct QuoteParams */ diff --git a/contracts/libraries/pool/MintCall.sol b/contracts/libraries/pool/MintCall.sol index 9276a218..f2708bb8 100644 --- a/contracts/libraries/pool/MintCall.sol +++ b/contracts/libraries/pool/MintCall.sol @@ -2,11 +2,15 @@ pragma solidity 0.8.13; import '../../interfaces/structs/CoverPoolStructs.sol'; +import '../../interfaces/callbacks/ICoverPoolCallback.sol'; +import '../../interfaces/IERC20Minimal.sol'; import '../Positions.sol'; import '../utils/PositionTokens.sol'; import '../utils/Collect.sol'; +import 'hardhat/console.sol'; library MintCall { + using SafeCast for uint128; event Mint( address indexed to, int24 lower, @@ -32,9 +36,6 @@ library MintCall { CoverPoolStructs.MintCache memory cache ) external returns (CoverPoolStructs.MintCache memory) { if (params.positionId > 0) { - if (PositionTokens.balanceOf(cache.constants, msg.sender, params.positionId) == 0) - // check for balance held - require(false, 'PositionNotFound()'); // load existing position cache.position = positions[params.positionId]; } @@ -59,10 +60,7 @@ library MintCall { // save global state to protect against reentrancy save(cache, globalState, pool0, pool1); // params.amount must be > 0 here - SafeTransfers.transferIn(params.zeroForOne ? cache.constants.token0 - : cache.constants.token1, - params.amount - ); + (cache.state, cache.position) = Positions.add( cache.position, ticks, @@ -80,7 +78,11 @@ library MintCall { cache.constants ); positions[params.positionId] = cache.position; + + // save state for reentrancy protection save(cache, globalState, pool0, pool1); + + // collect sync fees Collect.mint( cache, CoverPoolStructs.CollectParams( @@ -93,6 +95,18 @@ library MintCall { params.zeroForOne ) ); + + // check balance and execute callback + uint256 balanceStart = balance(params, cache); + ICoverPoolMintCallback(msg.sender).coverPoolMintCallback( + params.zeroForOne ? -int256(uint256(params.amount)) : int256(0), + params.zeroForOne ? int256(0) : -int256(uint256(params.amount)), + params.callbackData + ); + + // check balance requirements after callback + if (balance(params, cache) < balanceStart + params.amount) + require(false, 'MintInputAmountTooLow()'); return cache; } @@ -126,4 +140,23 @@ library MintCall { pool1.amountInDeltaMaxClaimed = cache.pool1.amountInDeltaMaxClaimed; pool1.amountOutDeltaMaxClaimed = cache.pool1.amountOutDeltaMaxClaimed; } + + function balance( + ICoverPool.MintParams memory params, + CoverPoolStructs.MintCache memory cache + ) private view returns (uint256) { + ( + bool success, + bytes memory data + ) = (params.zeroForOne ? cache.constants.token0 + : cache.constants.token1) + .staticcall( + abi.encodeWithSelector( + IERC20Minimal.balanceOf.selector, + address(this) + ) + ); + require(success && data.length >= 32); + return abi.decode(data, (uint256)); + } } diff --git a/contracts/libraries/pool/SwapCall.sol b/contracts/libraries/pool/SwapCall.sol index 4e9ddcb5..160fa282 100644 --- a/contracts/libraries/pool/SwapCall.sol +++ b/contracts/libraries/pool/SwapCall.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.13; import '../../interfaces/structs/CoverPoolStructs.sol'; import '../../interfaces/IERC20Minimal.sol'; -import '../../interfaces/callbacks/ICoverPoolSwapCallback.sol'; +import '../../interfaces/callbacks/ICoverPoolCallback.sol'; import '../Epochs.sol'; import '../Positions.sol'; import '../utils/Collect.sol'; diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index 6caed43b..579495be 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -2,10 +2,12 @@ pragma solidity 0.8.13; import '../interfaces/IPool.sol'; +import '../interfaces/range/IRangePool.sol'; import '../interfaces/limit/ILimitPool.sol'; import '../interfaces/cover/ICoverPool.sol'; -import '../interfaces/callbacks/ILimitPoolSwapCallback.sol'; -import '../interfaces/callbacks/ICoverPoolSwapCallback.sol'; +import '../interfaces/limit/ILimitPoolFactory.sol'; +import '../interfaces/callbacks/ILimitPoolCallback.sol'; +import '../interfaces/callbacks/ICoverPoolCallback.sol'; import '../libraries/utils/SafeTransfers.sol'; import '../libraries/utils/SafeCast.sol'; import '../interfaces/structs/PoolsharkStructs.sol'; @@ -13,7 +15,9 @@ import '../external/solady/LibClone.sol'; contract PoolsharkRouter is PoolsharkStructs, + ILimitPoolMintCallback, ILimitPoolSwapCallback, + ICoverPoolMintCallback, ICoverPoolSwapCallback { using SafeCast for uint256; @@ -28,6 +32,10 @@ contract PoolsharkRouter is address coverPoolFactory ); + struct MintCallbackData { + address sender; + } + struct SwapCallbackData { address sender; } @@ -45,32 +53,39 @@ contract PoolsharkRouter is ); } - /// @inheritdoc ILimitPoolSwapCallback - function limitPoolSwapCallback( + /// @inheritdoc ILimitPoolMintCallback + function limitPoolMintCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.LimitImmutables memory constants = ILimitPool(msg.sender).immutables(); - // generate key for pool - bytes32 key = keccak256(abi.encode( - constants.poolImpl, - constants.token0, - constants.token1, - constants.swapFee - )); + // validate sender is a canonical limit pool + canonicalLimitPoolsOnly(constants); - // compute address - address predictedAddress = LibClone.predictDeterministicAddress( - constants.poolImpl, - encodeLimit(constants), - key, - limitPoolFactory - ); + // decode original sender + MintCallbackData memory _data = abi.decode(data, (MintCallbackData)); + + // transfer from swap caller + if (amount0Delta < 0) { + SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); + } + if (amount1Delta < 0) { + SafeTransfers.transferInto(constants.token1, _data.sender, uint256(-amount1Delta)); + } + } - // revert on sender mismatch - if (msg.sender != predictedAddress) require(false, 'InvalidCallerAddress()'); + /// @inheritdoc ILimitPoolSwapCallback + function limitPoolSwapCallback( + int256 amount0Delta, + int256 amount1Delta, + bytes calldata data + ) external override { + PoolsharkStructs.LimitImmutables memory constants = ILimitPool(msg.sender).immutables(); + + // validate sender is a canonical limit pool + canonicalLimitPoolsOnly(constants); // decode original sender SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); @@ -83,33 +98,38 @@ contract PoolsharkRouter is } } - function coverPoolSwapCallback( + /// @inheritdoc ICoverPoolMintCallback + function coverPoolMintCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { PoolsharkStructs.CoverImmutables memory constants = ICoverPool(msg.sender).immutables(); - // generate key for pool - bytes32 key = keccak256(abi.encode( - constants.token0, - constants.token1, - constants.source, - constants.inputPool, - constants.tickSpread, - constants.twapLength - )); + // validate sender is a canonical cover pool + canonicalCoverPoolsOnly(constants); - // compute address - address predictedAddress = LibClone.predictDeterministicAddress( - constants.poolImpl, - encodeCover(constants), - key, - coverPoolFactory - ); + // decode original sender + MintCallbackData memory _data = abi.decode(data, (MintCallbackData)); - // revert on sender mismatch - if (msg.sender != predictedAddress) require(false, 'InvalidCallerAddress()'); + // transfer from swap caller + if (amount0Delta < 0) { + SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); + } else { + SafeTransfers.transferInto(constants.token1, _data.sender, uint256(-amount1Delta)); + } + } + + /// @inheritdoc ICoverPoolSwapCallback + function coverPoolSwapCallback( + int256 amount0Delta, + int256 amount1Delta, + bytes calldata data + ) external override { + PoolsharkStructs.CoverImmutables memory constants = ICoverPool(msg.sender).immutables(); + + // validate sender is a canonical cover pool + canonicalCoverPoolsOnly(constants); // decode original sender SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); @@ -122,6 +142,48 @@ contract PoolsharkRouter is } } + function multiMintLimit( + address[] memory pools, + MintLimitParams[] memory params + ) external { + if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); + for (uint i = 0; i < pools.length;) { + params[i].callbackData = abi.encode(MintCallbackData({sender: msg.sender})); + ILimitPool(pools[i]).mintLimit(params[i]); + unchecked { + ++i; + } + } + } + + function multiMintRange( + address[] memory pools, + MintRangeParams[] memory params + ) external { + if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); + for (uint i = 0; i < pools.length;) { + params[i].callbackData = abi.encode(MintCallbackData({sender: msg.sender})); + IRangePool(pools[i]).mintRange(params[i]); + unchecked { + ++i; + } + } + } + + function multiMintCover( + address[] memory pools, + ICoverPool.MintParams[] memory params + ) external { + if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); + for (uint i = 0; i < pools.length;) { + params[i].callbackData = abi.encode(MintCallbackData({sender: msg.sender})); + ICoverPool(pools[i]).mint(params[i]); + unchecked { + ++i; + } + } + } + function multiQuote( address[] memory pools, QuoteParams[] memory params, @@ -163,20 +225,6 @@ contract PoolsharkRouter is } } - function multiCall( - address[] memory pools, - SwapParams[] memory params - ) external { - if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); - for (uint i = 0; i < pools.length;) { - params[i].callbackData = abi.encode(SwapCallbackData({sender: msg.sender})); - ICoverPool(pools[i]).swap(params[i]); - unchecked { - ++i; - } - } - } - function multiSwapSplit( address[] memory pools, SwapParams[] memory params @@ -218,6 +266,20 @@ contract PoolsharkRouter is } } + function multiCall( + address[] memory pools, + SwapParams[] memory params + ) external { + if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); + for (uint i = 0; i < pools.length;) { + params[i].callbackData = abi.encode(SwapCallbackData({sender: msg.sender})); + ICoverPool(pools[i]).swap(params[i]); + unchecked { + ++i; + } + } + } + function sortQuoteResults( QuoteParams[] memory params, QuoteResults[] memory results @@ -247,7 +309,10 @@ contract PoolsharkRouter is } if (sortIndex != type(uint256).max) { // add the sorted result - sortedResults[sorted] = results[sortIndex]; + sortedResults[sorted].pool = results[sortIndex].pool; + sortedResults[sorted].amountIn = results[sortIndex].amountIn; + sortedResults[sorted].amountOut = results[sortIndex].amountOut; + sortedResults[sorted].priceAfter = results[sortIndex].priceAfter; // indicate this result was already sorted results[sortIndex].priceAfter = 0; @@ -264,6 +329,54 @@ contract PoolsharkRouter is } } + function canonicalLimitPoolsOnly( + PoolsharkStructs.LimitImmutables memory constants + ) private view { + // generate key for pool + bytes32 key = keccak256(abi.encode( + constants.poolImpl, + constants.token0, + constants.token1, + constants.swapFee + )); + + // compute address + address predictedAddress = LibClone.predictDeterministicAddress( + constants.poolImpl, + encodeLimit(constants), + key, + limitPoolFactory + ); + + // revert on sender mismatch + if (msg.sender != predictedAddress) require(false, 'InvalidCallerAddress()'); + } + + function canonicalCoverPoolsOnly( + PoolsharkStructs.CoverImmutables memory constants + ) private view { + // generate key for pool + bytes32 key = keccak256(abi.encode( + constants.token0, + constants.token1, + constants.source, + constants.inputPool, + constants.tickSpread, + constants.twapLength + )); + + // compute address + address predictedAddress = LibClone.predictDeterministicAddress( + constants.poolImpl, + encodeCover(constants), + key, + coverPoolFactory + ); + + // revert on sender mismatch + if (msg.sender != predictedAddress) require(false, 'InvalidCallerAddress()'); + } + function encodeLimit( LimitImmutables memory constants ) private pure returns (bytes memory) { diff --git a/test/contracts/coverpool.ts b/test/contracts/coverpool.ts index 3c33f6dc..159cdfef 100644 --- a/test/contracts/coverpool.ts +++ b/test/contracts/coverpool.ts @@ -3532,6 +3532,7 @@ describe('CoverPool Tests', function () { lowerTickCleared: false, revertMessage: '', }) + if (debugMode) await getTick(false, 600000, true) await validateSync(600000) diff --git a/test/utils/contracts/coverpool.ts b/test/utils/contracts/coverpool.ts index 2d87e2fe..1974ccfe 100644 --- a/test/utils/contracts/coverpool.ts +++ b/test/utils/contracts/coverpool.ts @@ -200,7 +200,7 @@ export async function validateSync(newLatestTick: number, autoSync: boolean = tr /// send a "no op" swap to trigger accumulate const token1Balance = await hre.props.token1.balanceOf(signer.address) - await hre.props.token1.connect(signer).approve(hre.props.coverPool.address, token1Balance) + await hre.props.token1.connect(signer).approve(hre.props.poolRouter.address, token1Balance) if (autoSync) { if (!revertMessage || revertMessage == '') { @@ -383,13 +383,13 @@ export async function validateMint(params: ValidateMintParams): Promise balanceOutBefore = await hre.props.token1.balanceOf(params.signer.address) await hre.props.token0 .connect(params.signer) - .approve(hre.props.coverPool.address, amountDesired) + .approve(hre.props.poolRouter.address, amountDesired) } else { balanceInBefore = await hre.props.token1.balanceOf(params.signer.address) balanceOutBefore = await hre.props.token0.balanceOf(params.signer.address) await hre.props.token1 .connect(params.signer) - .approve(hre.props.coverPool.address, amountDesired) + .approve(hre.props.poolRouter.address, amountDesired) } let lowerTickBefore: Tick @@ -411,29 +411,41 @@ export async function validateMint(params: ValidateMintParams): Promise if (revertMessage == '') { // console.log('MINT CALL') - const txn = await hre.props.coverPool + const txn = await hre.props.poolRouter .connect(params.signer) - .mint({ - to: recipient, - amount: amountDesired, - positionId: positionId, - lower: lower, - upper: upper, - zeroForOne: zeroForOne - }) + .multiMintCover( + [hre.props.coverPool.address], + [ + { + to: recipient, + amount: amountDesired, + positionId: positionId, + lower: lower, + upper: upper, + zeroForOne: zeroForOne, + callbackData: ethers.utils.formatBytes32String('') + } + ] + , {gasLimit: 3000000}) await txn.wait() } else { await expect( - hre.props.coverPool - .connect(params.signer) - .mint({ - to: params.signer.address, + hre.props.poolRouter + .connect(params.signer) + .multiMintCover( + [hre.props.coverPool.address], + [ + { + to: recipient, + amount: amountDesired, positionId: positionId, lower: lower, upper: upper, - amount: amountDesired, - zeroForOne: zeroForOne - }) + zeroForOne: zeroForOne, + callbackData: ethers.utils.formatBytes32String('') + } + ] + , {gasLimit: 3000000}) ).to.be.revertedWith(revertMessage) return expectedPositionId } From 71f9148e5d1668723bd66dd1c4174d375aedf8fa Mon Sep 17 00:00:00 2001 From: alphak3y Date: Fri, 22 Sep 2023 18:14:47 -0600 Subject: [PATCH 02/26] refactor interfaces --- contracts/CoverPool.sol | 6 +- contracts/CoverPoolFactory.sol | 2 +- contracts/interfaces/cover/ICoverPool.sol | 145 +----------------- .../interfaces/structs/PoolsharkStructs.sol | 137 +++++++++++++++++ contracts/libraries/Positions.sol | 4 +- contracts/libraries/pool/BurnCall.sol | 2 +- contracts/libraries/pool/MintCall.sol | 4 +- contracts/utils/PoolsharkRouter.sol | 2 +- 8 files changed, 154 insertions(+), 148 deletions(-) diff --git a/contracts/CoverPool.sol b/contracts/CoverPool.sol index d8d9b8a0..61585f4e 100644 --- a/contracts/CoverPool.sol +++ b/contracts/CoverPool.sol @@ -43,7 +43,7 @@ contract CoverPool is } function mint( - MintParams memory params + MintCoverParams memory params ) external override nonReentrant(globalState) canoncialOnly @@ -83,7 +83,7 @@ contract CoverPool is } function burn( - BurnParams memory params + BurnCoverParams memory params ) external override nonReentrant(globalState) canoncialOnly @@ -190,7 +190,7 @@ contract CoverPool is } function snapshot( - SnapshotParams memory params + SnapshotCoverParams memory params ) external view override returns ( CoverPosition memory ) { diff --git a/contracts/CoverPoolFactory.sol b/contracts/CoverPoolFactory.sol index df19080e..f9030e58 100644 --- a/contracts/CoverPoolFactory.sol +++ b/contracts/CoverPoolFactory.sol @@ -138,7 +138,7 @@ contract CoverPoolFactory is function createCoverPoolAndMint( CoverPoolParams memory params, - ICoverPool.MintParams[] memory mintCoverParams + PoolsharkStructs.MintCoverParams[] memory mintCoverParams ) external returns ( address pool, address poolToken diff --git a/contracts/interfaces/cover/ICoverPool.sol b/contracts/interfaces/cover/ICoverPool.sol index 3d80e4aa..75c88308 100644 --- a/contracts/interfaces/cover/ICoverPool.sol +++ b/contracts/interfaces/cover/ICoverPool.sol @@ -10,53 +10,7 @@ import '../structs/PoolsharkStructs.sol'; * @notice Defines the basic interface for a Cover Pool. */ interface ICoverPool is CoverPoolStructs { - /** - * @custom:struct MintParams - */ - struct MintParams { - /** - * @custom:field to - * @notice Address for the receiver of the minted position - */ - address to; - - /** - * @custom:field amount - * @notice Token amount to be deposited into the minted position - */ - uint128 amount; - - /** - * @custom:field positionId - * @notice 0 if creating a new position; id of previous if adding liquidity - */ - uint32 positionId; - - /** - * @custom:field lower - * @notice The lower price tick for the position range - */ - int24 lower; - - /** - * @custom:field upper - * @notice The upper price tick for the position range - */ - int24 upper; - - /** - * @custom:field zeroForOne - * @notice True if depositing token0, the first token address in lexographical order - * @notice False if depositing token1, the second token address in lexographical order - */ - bool zeroForOne; - - /** - * @custom:field callbackData - * @notice callback data which gets passed back to msg.sender at the end of a `mint` call - */ - bytes callbackData; - } + /** * @notice Deposits `amountIn` of asset to be auctioned off each time price range is crossed further into. @@ -65,59 +19,13 @@ interface ICoverPool is CoverPoolStructs { the user's liquidity within each tick spacing is auctioned off. * @dev The position will be shrunk onto the correct side of latestTick. * @dev The position will be minted with the `to` address as the owner. - * @param params The parameters for the function. See MintParams above. + * @param params The parameters for the function. See MintCoverParams. */ function mint( - MintParams memory params + MintCoverParams memory params ) external; - /** - * @custom:struct BurnParams - */ - struct BurnParams { - /** - * @custom:field to - * @notice Address for the receiver of the collected position amounts - */ - address to; - - /** - * @custom:field burnPercent - * @notice Percent of the remaining liquidity to be removed - * @notice 1e38 represents 100% - * @notice 5e37 represents 50% - * @notice 1e37 represents 10% - */ - uint128 burnPercent; - - /** - * @custom:field positionId - * @notice 0 if creating a new position; id of previous if adding liquidity - */ - uint32 positionId; - - /** - * @custom:field claim - * @notice The most recent tick crossed in this range - * @notice if `zeroForOne` is true, claim tick progresses from upper => lower - * @notice if `zeroForOne` is false, claim tick progresses from lower => upper - */ - int24 claim; - /** - * @custom:field zeroForOne - * @notice True if deposited token0, the first token address in lexographical order - * @notice False if deposited token1, the second token address in lexographical order - */ - bool zeroForOne; - - /** - * @custom:field sync - * @notice True will sync the pool latestTick - * @notice False will skip syncing latestTick - */ - bool sync; - } /** * @notice Withdraws the input token and returns any filled and/or unfilled amounts to the 'to' address specified. @@ -127,10 +35,10 @@ interface ICoverPool is CoverPoolStructs { * @dev The position will be shrunk based on the claim tick passed. * @dev The position amounts will be returned to the `to` address specified. * @dev The `sync` flag can be set to false so users can exit safely without syncing latestTick. - * @param params The parameters for the function. See BurnParams above. + * @param params The parameters for the function. See BurnCoverParams. */ function burn( - BurnParams memory params + BurnCoverParams memory params ) external; /** @@ -140,7 +48,7 @@ interface ICoverPool is CoverPoolStructs { The pool price represents token1 per token0. The pool price will decrease if `zeroForOne` is true. The pool price will increase if `zeroForOne` is false. - * @param params The parameters for the function. See SwapParams above. + * @param params The parameters for the function. See SwapParams. * @return amount0Delta The amount of token0 spent (negative) or received (positive) by the user * @return amount1Delta The amount of token1 spent (negative) or received (positive) by the user */ @@ -171,46 +79,7 @@ interface ICoverPool is CoverPoolStructs { uint256 priceAfter ); - /** - * @custom:struct SnapshotParams - */ - struct SnapshotParams { - /** - * @custom:field to - * @notice Address of the position owner - */ - address owner; - - /** - * @custom:field positionId - * @notice id of position - */ - uint32 positionId; - - /** - * @custom:field burnPercent - * @notice Percent of the remaining liquidity to be removed - * @notice 1e38 represents 100% - * @notice 5e37 represents 50% - * @notice 1e37 represents 10% - */ - uint128 burnPercent; - - /** - * @custom:field claim - * @notice The most recent tick crossed in this range - * @notice if `zeroForOne` is true, claim tick progresses from upper => lower - * @notice if `zeroForOne` is false, claim tick progresses from lower => upper - */ - int24 claim; - /** - * @custom:field zeroForOne - * @notice True if deposited token0, the first token address in lexographical order - * @notice False if deposited token1, the second token address in lexographical order - */ - bool zeroForOne; - } /** * @notice Snapshots the current state of an existing position. @@ -219,7 +88,7 @@ interface ICoverPool is CoverPoolStructs { * @dev positions amounts reflected will be collected by the user if `burn` is called */ function snapshot( - SnapshotParams memory params + SnapshotCoverParams memory params ) external view returns ( CoverPosition memory position ); diff --git a/contracts/interfaces/structs/PoolsharkStructs.sol b/contracts/interfaces/structs/PoolsharkStructs.sol index bb169435..aef64c24 100644 --- a/contracts/interfaces/structs/PoolsharkStructs.sol +++ b/contracts/interfaces/structs/PoolsharkStructs.sol @@ -101,6 +101,143 @@ interface PoolsharkStructs { bool zeroForOne; } + /** + * @custom:struct MintCoverParams + */ + struct MintCoverParams { + /** + * @custom:field to + * @notice Address for the receiver of the minted position + */ + address to; + + /** + * @custom:field amount + * @notice Token amount to be deposited into the minted position + */ + uint128 amount; + + /** + * @custom:field positionId + * @notice 0 if creating a new position; id of previous if adding liquidity + */ + uint32 positionId; + + /** + * @custom:field lower + * @notice The lower price tick for the position range + */ + int24 lower; + + /** + * @custom:field upper + * @notice The upper price tick for the position range + */ + int24 upper; + + /** + * @custom:field zeroForOne + * @notice True if depositing token0, the first token address in lexographical order + * @notice False if depositing token1, the second token address in lexographical order + */ + bool zeroForOne; + + /** + * @custom:field callbackData + * @notice callback data which gets passed back to msg.sender at the end of a `mint` call + */ + bytes callbackData; + } + + /** + * @custom:struct BurnCoverParams + */ + struct BurnCoverParams { + /** + * @custom:field to + * @notice Address for the receiver of the collected position amounts + */ + address to; + + /** + * @custom:field burnPercent + * @notice Percent of the remaining liquidity to be removed + * @notice 1e38 represents 100% + * @notice 5e37 represents 50% + * @notice 1e37 represents 10% + */ + uint128 burnPercent; + + /** + * @custom:field positionId + * @notice 0 if creating a new position; id of previous if adding liquidity + */ + uint32 positionId; + + /** + * @custom:field claim + * @notice The most recent tick crossed in this range + * @notice if `zeroForOne` is true, claim tick progresses from upper => lower + * @notice if `zeroForOne` is false, claim tick progresses from lower => upper + */ + int24 claim; + + /** + * @custom:field zeroForOne + * @notice True if deposited token0, the first token address in lexographical order + * @notice False if deposited token1, the second token address in lexographical order + */ + bool zeroForOne; + + /** + * @custom:field sync + * @notice True will sync the pool latestTick + * @notice False will skip syncing latestTick + */ + bool sync; + } + + /** + * @custom:struct SnapshotCoverParams + */ + struct SnapshotCoverParams { + /** + * @custom:field to + * @notice Address of the position owner + */ + address owner; + + /** + * @custom:field positionId + * @notice id of position + */ + uint32 positionId; + + /** + * @custom:field burnPercent + * @notice Percent of the remaining liquidity to be removed + * @notice 1e38 represents 100% + * @notice 5e37 represents 50% + * @notice 1e37 represents 10% + */ + uint128 burnPercent; + + /** + * @custom:field claim + * @notice The most recent tick crossed in this range + * @notice if `zeroForOne` is true, claim tick progresses from upper => lower + * @notice if `zeroForOne` is false, claim tick progresses from lower => upper + */ + int24 claim; + + /** + * @custom:field zeroForOne + * @notice True if deposited token0, the first token address in lexographical order + * @notice False if deposited token1, the second token address in lexographical order + */ + bool zeroForOne; + } + /** * @custom:struct QuoteParams */ diff --git a/contracts/libraries/Positions.sol b/contracts/libraries/Positions.sol index af48d934..f61f403d 100644 --- a/contracts/libraries/Positions.sol +++ b/contracts/libraries/Positions.sol @@ -49,11 +49,11 @@ library Positions { function resize( CoverPoolStructs.CoverPosition memory position, - ICoverPool.MintParams memory params, + PoolsharkStructs.MintCoverParams memory params, CoverPoolStructs.GlobalState memory state, PoolsharkStructs.CoverImmutables memory constants ) internal pure returns ( - ICoverPool.MintParams memory, + PoolsharkStructs.MintCoverParams memory, uint256 ) { diff --git a/contracts/libraries/pool/BurnCall.sol b/contracts/libraries/pool/BurnCall.sol index 093474e6..94004c78 100644 --- a/contracts/libraries/pool/BurnCall.sol +++ b/contracts/libraries/pool/BurnCall.sol @@ -33,7 +33,7 @@ library BurnCall { CoverPoolStructs.GlobalState storage globalState, CoverPoolStructs.PoolState storage pool0, CoverPoolStructs.PoolState storage pool1, - ICoverPool.BurnParams memory params, + PoolsharkStructs.BurnCoverParams memory params, CoverPoolStructs.BurnCache memory cache ) external returns (CoverPoolStructs.BurnCache memory) { cache.position = positions[params.positionId]; diff --git a/contracts/libraries/pool/MintCall.sol b/contracts/libraries/pool/MintCall.sol index f2708bb8..f8179c39 100644 --- a/contracts/libraries/pool/MintCall.sol +++ b/contracts/libraries/pool/MintCall.sol @@ -32,7 +32,7 @@ library MintCall { CoverPoolStructs.GlobalState storage globalState, CoverPoolStructs.PoolState storage pool0, CoverPoolStructs.PoolState storage pool1, - ICoverPool.MintParams memory params, + PoolsharkStructs.MintCoverParams memory params, CoverPoolStructs.MintCache memory cache ) external returns (CoverPoolStructs.MintCache memory) { if (params.positionId > 0) { @@ -142,7 +142,7 @@ library MintCall { } function balance( - ICoverPool.MintParams memory params, + PoolsharkStructs.MintCoverParams memory params, CoverPoolStructs.MintCache memory cache ) private view returns (uint256) { ( diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index 579495be..bbc6f9b6 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -172,7 +172,7 @@ contract PoolsharkRouter is function multiMintCover( address[] memory pools, - ICoverPool.MintParams[] memory params + PoolsharkStructs.MintCoverParams[] memory params ) external { if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); for (uint i = 0; i < pools.length;) { From ced897c463bad3ee18e51bdee7406435e48feb0c Mon Sep 17 00:00:00 2001 From: alphak3y Date: Fri, 22 Sep 2023 18:49:31 -0600 Subject: [PATCH 03/26] update router --- contracts/CoverPoolFactory.sol | 32 ---------- contracts/interfaces/cover/ICoverPool.sol | 4 -- contracts/utils/PoolsharkRouter.sol | 76 +++++++++++++++++++++++ 3 files changed, 76 insertions(+), 36 deletions(-) diff --git a/contracts/CoverPoolFactory.sol b/contracts/CoverPoolFactory.sol index f9030e58..7fbb0bc1 100644 --- a/contracts/CoverPoolFactory.sol +++ b/contracts/CoverPoolFactory.sol @@ -136,38 +136,6 @@ contract CoverPoolFactory is ); } - function createCoverPoolAndMint( - CoverPoolParams memory params, - PoolsharkStructs.MintCoverParams[] memory mintCoverParams - ) external returns ( - address pool, - address poolToken - ) { - // check if pool exists - ( - pool, - poolToken - ) = getCoverPool( - params - ); - // create if pool doesn't exist - if (pool == address(0)) { - ( - pool, - poolToken - ) = createCoverPool( - params - ); - } - // mint initial cover positions - for (uint i = 0; i < mintCoverParams.length;) { - ICoverPool(pool).mint(mintCoverParams[i]); - unchecked { - ++i; - } - } - } - function getCoverPool( CoverPoolParams memory params ) public view override returns ( diff --git a/contracts/interfaces/cover/ICoverPool.sol b/contracts/interfaces/cover/ICoverPool.sol index 75c88308..872dc41a 100644 --- a/contracts/interfaces/cover/ICoverPool.sol +++ b/contracts/interfaces/cover/ICoverPool.sol @@ -25,8 +25,6 @@ interface ICoverPool is CoverPoolStructs { MintCoverParams memory params ) external; - - /** * @notice Withdraws the input token and returns any filled and/or unfilled amounts to the 'to' address specified. * - E.g. User supplies 1 WETH in the range 1500 USDC per WETH to 1400 USDC per WETH @@ -79,8 +77,6 @@ interface ICoverPool is CoverPoolStructs { uint256 priceAfter ); - - /** * @notice Snapshots the current state of an existing position. * @param params The parameters for the function. See SwapParams above. diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index bbc6f9b6..5a81cf41 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -5,6 +5,7 @@ import '../interfaces/IPool.sol'; import '../interfaces/range/IRangePool.sol'; import '../interfaces/limit/ILimitPool.sol'; import '../interfaces/cover/ICoverPool.sol'; +import '../interfaces/cover/ICoverPoolFactory.sol'; import '../interfaces/limit/ILimitPoolFactory.sol'; import '../interfaces/callbacks/ILimitPoolCallback.sol'; import '../interfaces/callbacks/ICoverPoolCallback.sol'; @@ -280,6 +281,81 @@ contract PoolsharkRouter is } } + function createLimitPoolAndMint( + ILimitPoolFactory.LimitPoolParams memory params, + MintRangeParams[] memory mintRangeParams, + MintLimitParams[] memory mintLimitParams + ) external returns ( + address pool, + address poolToken + ) { + // check if pool exists + ( + pool, + poolToken + ) = ILimitPoolFactory(limitPoolFactory).getLimitPool( + params.poolType, + params.tokenIn, + params.tokenOut, + params.swapFee + ); + // create if pool doesn't exist + if (pool == address(0)) { + ( + pool, + poolToken + ) = ILimitPoolFactory(limitPoolFactory).createLimitPool( + params + ); + } + // mint initial range positions + for (uint i = 0; i < mintRangeParams.length;) { + IRangePool(pool).mintRange(mintRangeParams[i]); + unchecked { + ++i; + } + } + // mint initial limit positions + for (uint i = 0; i < mintLimitParams.length;) { + ILimitPool(pool).mintLimit(mintLimitParams[i]); + unchecked { + ++i; + } + } + } + + function createCoverPoolAndMint( + ICoverPoolFactory.CoverPoolParams memory params, + MintCoverParams[] memory mintCoverParams + ) external returns ( + address pool, + address poolToken + ) { + // check if pool exists + ( + pool, + poolToken + ) = ICoverPoolFactory(coverPoolFactory).getCoverPool( + params + ); + // create if pool doesn't exist + if (pool == address(0)) { + ( + pool, + poolToken + ) = ICoverPoolFactory(coverPoolFactory).createCoverPool( + params + ); + } + // mint initial cover positions + for (uint i = 0; i < mintCoverParams.length;) { + ICoverPool(pool).mint(mintCoverParams[i]); + unchecked { + ++i; + } + } + } + function sortQuoteResults( QuoteParams[] memory params, QuoteResults[] memory results From 8157d0a9b8397c97bfa6228a76eabc60bd9e9672 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sat, 23 Sep 2023 10:57:35 -0600 Subject: [PATCH 04/26] update poolshark limit sampling; split deployment for local and testnet --- .../external/poolshark/limit/ILimitPool.sol | 55 ++++ .../poolshark/limit/ILimitPoolFactory.sol | 16 + .../poolshark/limit/ILimitPoolManager.sol | 19 ++ .../external/poolshark/range/IRangePool.sol | 45 --- .../poolshark/range/IRangePoolFactory.sol | 10 - .../poolshark/range/IRangePoolManager.sol | 9 - ...ngeSource.sol => PoolsharkLimitSource.sol} | 44 +-- ...ctoryMock.sol => LimitPoolFactoryMock.sol} | 25 +- .../{RangePoolMock.sol => LimitPoolMock.sol} | 66 ++--- hardhat.config.ts | 23 +- scripts/autogen/contract-deployments.json | 14 + scripts/config/networkConfigs.ts | 14 + scripts/constants/supportedNetworks.ts | 4 +- test/utils/setup/initialSetup.ts | 278 +++++++++++------- 14 files changed, 368 insertions(+), 254 deletions(-) create mode 100644 contracts/interfaces/external/poolshark/limit/ILimitPool.sol create mode 100644 contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol create mode 100644 contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol delete mode 100644 contracts/interfaces/external/poolshark/range/IRangePool.sol delete mode 100644 contracts/interfaces/external/poolshark/range/IRangePoolFactory.sol delete mode 100644 contracts/interfaces/external/poolshark/range/IRangePoolManager.sol rename contracts/libraries/sources/{PoolsharkRangeSource.sol => PoolsharkLimitSource.sol} (80%) rename contracts/test/{RangePoolFactoryMock.sol => LimitPoolFactoryMock.sol} (56%) rename contracts/test/{RangePoolMock.sol => LimitPoolMock.sol} (66%) diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPool.sol b/contracts/interfaces/external/poolshark/limit/ILimitPool.sol new file mode 100644 index 00000000..a6d2840b --- /dev/null +++ b/contracts/interfaces/external/poolshark/limit/ILimitPool.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.13; + +interface ILimitPool { + struct RangePoolState { + SampleState samples; + uint200 feeGrowthGlobal0; + uint200 feeGrowthGlobal1; + uint160 secondsPerLiquidityAccum; + uint160 price; /// @dev Starting price current + uint128 liquidity; /// @dev Liquidity currently active + int56 tickSecondsAccum; + int24 tickAtPrice; + uint16 protocolSwapFee0; + uint16 protocolSwapFee1; + } + + struct SampleState { + uint16 index; + uint16 length; + uint16 lengthNext; + } + + struct LimitPoolState { + uint160 price; /// @dev Starting price current + uint128 liquidity; /// @dev Liquidity currently active + uint128 protocolFees; + uint16 protocolFillFee; + int24 tickAtPrice; + } + + function sample( + uint32[] memory secondsAgo + ) external view returns ( + int56[] memory tickSecondsAccum, + uint160[] memory secondsPerLiquidityAccum, + uint160 averagePrice, + uint128 averageLiquidity, + int24 averageTick + ); + + function increaseSampleLength( + uint16 sampleLengthNext + ) external; + + function globalState() external view returns ( + RangePoolState memory pool, + LimitPoolState memory pool0, + LimitPoolState memory pool1, + uint128 liquidityGlobal, + uint32 positionIdNext, + uint32 epoch, + uint8 unlocked + ); +} diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol b/contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol new file mode 100644 index 00000000..86f2a2b6 --- /dev/null +++ b/contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: BUSL-1.1 +pragma solidity 0.8.13; + +import '../../../structs/PoolsharkStructs.sol'; + +abstract contract ILimitPoolFactory is PoolsharkStructs { + function getLimitPool( + bytes32 poolType, + address tokenIn, + address tokenOut, + uint16 swapFee + ) external view virtual returns ( + address pool, + address poolToken + ); +} diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol b/contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol new file mode 100644 index 00000000..cc616f33 --- /dev/null +++ b/contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.13; + +/// @notice LimitPoolManager interface +interface ILimitPoolManager { + function owner() external view returns (address); + function feeTo() external view returns (address); + function implementations( + bytes32 poolType + ) external view returns ( + address poolImpl, + address tokenImpl + ); + function feeTiers( + uint16 swapFee + ) external view returns ( + int16 tickSpacing + ); +} diff --git a/contracts/interfaces/external/poolshark/range/IRangePool.sol b/contracts/interfaces/external/poolshark/range/IRangePool.sol deleted file mode 100644 index bac966ff..00000000 --- a/contracts/interfaces/external/poolshark/range/IRangePool.sol +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.13; - -interface IRangePool { - - struct ProtocolFees { - uint128 token0; - uint128 token1; - } - - struct SampleState { - uint16 index; - uint16 length; - uint16 lengthNext; - } - - function sample( - uint32[] memory secondsAgo - ) external view returns ( - int56[] memory tickSecondsAccum, - uint160[] memory secondsPerLiquidityAccum, - uint160 averagePrice, - uint128 averageLiquidity, - int24 averageTick - ); - - function increaseSampleLength( - uint16 sampleLengthNext - ) external; - - function poolState() external view returns ( - uint8, - uint16, - int24, - int56, - uint160, - uint160, - uint128, - uint128, - uint200, - uint200, - SampleState memory, - ProtocolFees memory - ); -} diff --git a/contracts/interfaces/external/poolshark/range/IRangePoolFactory.sol b/contracts/interfaces/external/poolshark/range/IRangePoolFactory.sol deleted file mode 100644 index d5ada067..00000000 --- a/contracts/interfaces/external/poolshark/range/IRangePoolFactory.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: GPLv3 -pragma solidity 0.8.13; - -interface IRangePoolFactory { - function getRangePool( - address fromToken, - address destToken, - uint16 fee - ) external view returns (address); -} diff --git a/contracts/interfaces/external/poolshark/range/IRangePoolManager.sol b/contracts/interfaces/external/poolshark/range/IRangePoolManager.sol deleted file mode 100644 index 6c8b3ef7..00000000 --- a/contracts/interfaces/external/poolshark/range/IRangePoolManager.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.13; - -interface IRangePoolManager { - function owner() external view returns (address); - function feeTo() external view returns (address); - function protocolFees(address pool) external view returns (uint16); - function feeTiers(uint16 swapFee) external view returns (int24); -} diff --git a/contracts/libraries/sources/PoolsharkRangeSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol similarity index 80% rename from contracts/libraries/sources/PoolsharkRangeSource.sol rename to contracts/libraries/sources/PoolsharkLimitSource.sol index 386626bb..323dc524 100644 --- a/contracts/libraries/sources/PoolsharkRangeSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -1,28 +1,31 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import '../../interfaces/external/poolshark/range/IRangePoolManager.sol'; -import '../../interfaces/external/poolshark/range/IRangePoolFactory.sol'; -import '../../interfaces/external/poolshark/range/IRangePool.sol'; +import '../../interfaces/external/poolshark/limit/ILimitPoolManager.sol'; +import '../../interfaces/external/poolshark/limit/ILimitPoolFactory.sol'; +import '../../interfaces/external/poolshark/limit/ILimitPool.sol'; import '../../interfaces/structs/CoverPoolStructs.sol'; import '../../interfaces/modules/sources/ITwapSource.sol'; import '../math/ConstantProduct.sol'; -contract PoolsharkRangeSource is ITwapSource { +contract PoolsharkLimitSource is ITwapSource { error WaitUntilBelowMaxTick(); error WaitUntilAboveMinTick(); - address public immutable rangePoolFactory; - address public immutable rangePoolManager; + bytes32 public immutable poolType; + address public immutable limitPoolFactory; + address public immutable limitPoolManager; /// @dev - set for Arbitrum mainnet uint32 public constant oneSecond = 1000; constructor( - address _rangePoolFactory, - address _rangePoolManager + address _limitPoolFactory, + address _limitPoolManager, + bytes32 _poolType ) { - rangePoolFactory = _rangePoolFactory; - rangePoolManager = _rangePoolManager; + limitPoolFactory = _limitPoolFactory; + limitPoolManager = _limitPoolManager; + poolType = _poolType; } function initialize( @@ -55,7 +58,7 @@ contract PoolsharkRangeSource is ITwapSource { } function factory() external view returns (address) { - return rangePoolFactory; + return limitPoolFactory; } function feeTierTickSpacing( @@ -64,7 +67,7 @@ contract PoolsharkRangeSource is ITwapSource { int24 ) { - return IRangePoolManager(rangePoolManager).feeTiers(feeTier); + return ILimitPoolManager(limitPoolManager).feeTiers(feeTier); } function getPool( @@ -74,7 +77,7 @@ contract PoolsharkRangeSource is ITwapSource { ) external view returns( address pool ) { - return IRangePoolFactory(rangePoolFactory).getRangePool(token0, token1, feeTier); + (pool,) = ILimitPoolFactory(limitPoolFactory).getLimitPool(poolType, token0, token1, feeTier); } function calculateAverageTick( @@ -112,7 +115,7 @@ contract PoolsharkRangeSource is ITwapSource { secondsAgos[1] = timeDelta; secondsAgos[2] = constants.twapLength - timeDelta; secondsAgos[3] = constants.twapLength; - (int56[] memory tickSecondsAccum,,,,) = IRangePool(constants.inputPool).sample(secondsAgos); + (int56[] memory tickSecondsAccum,,,,) = ILimitPool(constants.inputPool).sample(secondsAgos); /// @dev take the smallest absolute value of 4 samples averageTicks[0] = int24(((tickSecondsAccum[0] - tickSecondsAccum[2]) / (int32(secondsAgos[2] - secondsAgos[0])))); @@ -140,13 +143,16 @@ contract PoolsharkRangeSource is ITwapSource { ) { ( - ,,,,,,,,,, - IRangePool.SampleState memory samples, - ) = IRangePool(pool).poolState(); - return (samples.length >= blockCount, samples.lengthNext >= blockCount); + ILimitPool.RangePoolState memory poolState, + ,,,,, + ) = ILimitPool(pool).globalState(); + return ( + poolState.samples.length >= blockCount, + poolState.samples.lengthNext >= blockCount + ); } function _increaseSampleLength(address pool, uint32 blockCount) internal { - IRangePool(pool).increaseSampleLength(uint16(blockCount)); + ILimitPool(pool).increaseSampleLength(uint16(blockCount)); } } diff --git a/contracts/test/RangePoolFactoryMock.sol b/contracts/test/LimitPoolFactoryMock.sol similarity index 56% rename from contracts/test/RangePoolFactoryMock.sol rename to contracts/test/LimitPoolFactoryMock.sol index 20fb7cab..ae10118c 100644 --- a/contracts/test/RangePoolFactoryMock.sol +++ b/contracts/test/LimitPoolFactoryMock.sol @@ -1,16 +1,16 @@ //SPDX-License-Identifier: Unlicense pragma solidity 0.8.13; -import '../interfaces/external/poolshark/range/IRangePoolFactory.sol'; -import './RangePoolMock.sol'; +import '../interfaces/external/poolshark/limit/ILimitPoolFactory.sol'; +import './LimitPoolMock.sol'; -contract RangePoolFactoryMock is IRangePoolFactory { +contract LimitPoolFactoryMock is ILimitPoolFactory { address mockPool; address mockPool2; address owner; mapping(uint24 => int24) public feeTierTickSpacing; - mapping(address => mapping(address => mapping(uint24 => address))) public rangePools; + mapping(address => mapping(address => mapping(uint24 => address))) public limitPools; constructor(address tokenA, address tokenB) { owner = msg.sender; @@ -21,22 +21,25 @@ contract RangePoolFactoryMock is IRangePoolFactory { feeTierTickSpacing[10000] = 200; // create mock pool 1 - mockPool = address(new RangePoolMock(tokenA, tokenB, 500, 10)); - rangePools[tokenA][tokenB][500] = mockPool; + mockPool = address(new LimitPoolMock(tokenA, tokenB, 500, 10)); + limitPools[tokenA][tokenB][500] = mockPool; // create mock pool 2 - mockPool2 = address(new RangePoolMock(tokenA, tokenB, 3000, 60)); - rangePools[tokenA][tokenB][3000] = mockPool2; + mockPool2 = address(new LimitPoolMock(tokenA, tokenB, 3000, 60)); + limitPools[tokenA][tokenB][3000] = mockPool2; } - function getRangePool( + function getLimitPool( + bytes32 poolType, address tokenIn, address tokenOut, uint16 feeTier - ) external view override returns (address) { + ) external view override returns (address pool, address poolToken) { address token0 = tokenIn < tokenOut ? tokenIn : tokenOut; address token1 = tokenIn < tokenOut ? tokenOut : tokenIn; + poolType; + poolToken; - return rangePools[token0][token1][feeTier]; + pool = limitPools[token0][token1][feeTier]; } } diff --git a/contracts/test/RangePoolMock.sol b/contracts/test/LimitPoolMock.sol similarity index 66% rename from contracts/test/RangePoolMock.sol rename to contracts/test/LimitPoolMock.sol index ba9a8220..b36966c9 100644 --- a/contracts/test/RangePoolMock.sol +++ b/contracts/test/LimitPoolMock.sol @@ -1,18 +1,18 @@ //SPDX-License-Identifier: Unlicense pragma solidity 0.8.13; -import '../interfaces/external/poolshark/range/IRangePool.sol'; +import '../interfaces/external/poolshark/limit/ILimitPool.sol'; import './UniswapV3PoolMock.sol'; -contract RangePoolMock is IRangePool { +contract LimitPoolMock is ILimitPool { address internal admin; address public token0; address public token1; int24 public tickSpacing; uint256 swapFee; - uint16 observationCardinality; - uint16 observationCardinalityNext; + uint16 sampleLength; + uint16 sampleLengthNext; int56 tickCumulative0; int56 tickCumulative1; @@ -31,50 +31,38 @@ contract RangePoolMock is IRangePool { token1 = _token1; swapFee = _swapFee; tickSpacing = _tickSpacing; - observationCardinality = 4; - observationCardinalityNext = 4; + sampleLength = 4; + sampleLengthNext = 4; tickCumulative0 = 10; tickCumulative1 = 9; tickCumulative2 = 6; tickCumulative3 = 5; } - function poolState() + function globalState() external view override returns ( - uint8, - uint16, - int24, - int56, - uint160, - uint160, - uint128, - uint128, - uint200, - uint200, - SampleState memory, - ProtocolFees memory + RangePoolState memory pool, + LimitPoolState memory pool0, + LimitPoolState memory pool1, + uint128 liquidityGlobal, + uint32 positionIdNext, + uint32 epoch, + uint8 unlocked ) { - return ( - 1, - 0, - 0, - 0, - 0, - 1 << 96, - 0, - 0, - 0, - 0, - SampleState( + pool.samples = SampleState( 4, - observationCardinality, - observationCardinalityNext - ), - ProtocolFees(0,0) + sampleLength, + sampleLengthNext ); + pool0; + pool1; + liquidityGlobal; + positionIdNext; + epoch; + unlocked; } function sample( @@ -104,7 +92,7 @@ contract RangePoolMock is IRangePool { } function increaseSampleLength(uint16 cardinalityNext) external { - observationCardinalityNext = cardinalityNext; + sampleLengthNext = cardinalityNext; } function setTickCumulatives(int56 _tickCumulative0, int56 _tickCumulative1, int56 _tickCumulative2, int56 _tickCumulative3) external { @@ -114,8 +102,8 @@ contract RangePoolMock is IRangePool { tickCumulative3 = _tickCumulative3; } - function setObservationCardinality(uint16 _observationCardinality, uint16 _observationCardinalityNext) external { - observationCardinality = _observationCardinality; - observationCardinalityNext = _observationCardinalityNext; + function setObservationCardinality(uint16 _sampleLength, uint16 _sampleLengthNext) external { + sampleLength = _sampleLength; + sampleLengthNext = _sampleLengthNext; } } diff --git a/hardhat.config.ts b/hardhat.config.ts index ca9f04f6..c494043e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -41,13 +41,12 @@ const config: HardhatUserConfig = { timeout: 60000, allowUnlimitedContractSize: true, }, - scroll_alpha: { - chainId: 534353, - gasPrice: 4000000, - url: process.env.SCROLL_ALPHA_URL || '', - accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], - timeout: 60000, - allowUnlimitedContractSize: true, + scrollSepolia: { + chainId: 534351, + url: "https://sepolia-rpc.scroll.io/" || "", + gasPrice: 1_500_000_000, + accounts: + process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], }, op_goerli: { chainId: 420, @@ -61,15 +60,15 @@ const config: HardhatUserConfig = { etherscan: { apiKey: { arbitrumGoerli: process.env.ARBITRUM_GOERLI_API_KEY, - scroll_alpha: 'abc', + scrollSepolia: 'abc', }, customChains: [ { - network: 'scroll_alpha', - chainId: 534353, + network: 'scrollSepolia', + chainId: 534351, urls: { - apiURL: 'https://blockscout.scroll.io/api', - browserURL: 'https://blockscout.scroll.io/', + apiURL: 'https://sepolia-blockscout.scroll.io/api', + browserURL: 'https://sepolia-blockscout.scroll.io/', }, }, ], diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index cdff0fe8..440d8fc6 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -177,6 +177,20 @@ "0x479C2Df7eD63ea26146Ac2092C55047C3928A5A6" ], "created": "2023-09-14T16:33:18.642Z" + }, + "limitPoolManager": { + "contractName": "LimitPoolManager", + "contractAddress": "0xcf90a2148b8fe67dab958b75cd358890c4b4a891", + "constructorArguments": [], + "created": "2023-09-23T15:58:08.332Z" + }, + "limitPoolFactory": { + "contractName": "LimitPoolFactory", + "contractAddress": "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", + "constructorArguments": [ + "0xCF90A2148b8FE67dAB958b75cD358890c4B4a891" + ], + "created": "2023-09-23T15:58:09.898Z" } }, "scroll_alpha": { diff --git a/scripts/config/networkConfigs.ts b/scripts/config/networkConfigs.ts index 311be7c6..fc490818 100644 --- a/scripts/config/networkConfigs.ts +++ b/scripts/config/networkConfigs.ts @@ -33,4 +33,18 @@ export const NETWORK_CONFIGS: NetworkConfigs = { url: process.env.GOERLI_URL || '', accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], }, + arb_goerli: { + chainId: 421613, + gas: 9000000, + gasPrice: 10_000_000_000, + url: process.env.ARBITRUM_GOERLI_URL || '', + accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], + }, + scrollSepolia : { + chainId: 534353, + gas: 9000000, + gasPrice: 4000000, + url: process.env.SCROLL_ALPHA_URL || '', + accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], + } } diff --git a/scripts/constants/supportedNetworks.ts b/scripts/constants/supportedNetworks.ts index 8f4a6cf8..86a43fdf 100644 --- a/scripts/constants/supportedNetworks.ts +++ b/scripts/constants/supportedNetworks.ts @@ -5,13 +5,13 @@ export enum SUPPORTED_NETWORKS { /* Testnet Supported Networks */ GOERLI = 'goerli', ARB_GOERLI = 'arb_goerli', - SCROLL_ALPHA = 'scroll_alpha' + SCROLL_SEPOLIA = 'scrollSepolia' } export enum TESTNET_NETWORKS { GOERLI = 'goerli', ARB_GOERLI = 'arb_goerli', - SCROLL_ALPHA = 'scroll_alpha' + SCROLL_SEPOLIA = 'scrollSepolia' } export enum LOCAL_NETWORKS { diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index 7db52ce0..f7bc9045 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -2,7 +2,7 @@ import { SUPPORTED_NETWORKS } from '../../../scripts/constants/supportedNetworks import { DeployAssist } from '../../../scripts/util/deployAssist' import { ContractDeploymentsKeys } from '../../../scripts/util/files/contractDeploymentKeys' import { ContractDeploymentsJson } from '../../../scripts/util/files/contractDeploymentsJson' -import { CoverPool__factory, PoolsharkRouter__factory, PositionERC1155__factory, QuoteCall__factory, Token20Batcher__factory } from '../../../typechain' +import { CoverPool__factory, PoolsharkLimitSource__factory, PoolsharkRouter__factory, PositionERC1155__factory, QuoteCall__factory, Token20Batcher__factory } from '../../../typechain' import { BurnCall__factory } from '../../../typechain' import { SwapCall__factory } from '../../../typechain' import { MintCall__factory } from '../../../typechain' @@ -31,6 +31,14 @@ export class InitialSetup { private contractDeploymentsJson: ContractDeploymentsJson private contractDeploymentsKeys: ContractDeploymentsKeys + /// DEPLOY CONFIG + private deployRouter = false + private deployTokens = false + private deployPools = true + private deployContracts = true + private deployPoolsharkLimitSource = true + private deployUniswapV3Source = false + constructor() { this.deployAssist = new DeployAssist() this.contractDeploymentsJson = new ContractDeploymentsJson() @@ -40,117 +48,173 @@ export class InitialSetup { public async initialCoverPoolSetup(): Promise { const network = SUPPORTED_NETWORKS[hre.network.name.toUpperCase()] - - // const token0Address = ( - // await this.contractDeploymentsJson.readContractDeploymentsJsonFile( - // { - // networkName: hre.network.name, - // objectName: 'token0', - // }, - // 'readRangePoolSetup' - // ) - // ).contractAddress - // const token1Address = ( - // await this.contractDeploymentsJson.readContractDeploymentsJsonFile( - // { - // networkName: hre.network.name, - // objectName: 'token1', - // }, - // 'readRangePoolSetup' - // ) - // ).contractAddress - // hre.props.token0 = await hre.ethers.getContractAt('Token20', token0Address) - // hre.props.token1 = await hre.ethers.getContractAt('Token20', token1Address) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Token20Batcher__factory, - 'token20Batcher', - [] - ) - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Token20__factory, - 'tokenA', - ['Wrapped Ether', 'WETH', this.token0Decimals] - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Token20__factory, - 'tokenB', - ['Dai Stablecoin', 'DAI', this.token1Decimals] - ) - - const tokenOrder = hre.props.tokenA.address.localeCompare(hre.props.tokenB.address) < 0 - let token0Args - let token1Args - if (tokenOrder) { - hre.props.token0 = hre.props.tokenA - hre.props.token1 = hre.props.tokenB - token0Args = ['Wrapped Ether', 'WETH', this.token0Decimals] - token1Args = ['Dai Stablecoin', 'DAI', this.token1Decimals] + if (!this.deployTokens && hre.network.name != 'hardhat') { + + const token0Address = ( + await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + { + networkName: hre.network.name, + objectName: 'token0', + }, + 'initialSetup' + ) + ).contractAddress + const token1Address = ( + await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + { + networkName: hre.network.name, + objectName: 'token1', + }, + 'initialSetup' + ) + ).contractAddress + hre.props.token0 = await hre.ethers.getContractAt('Token20', token0Address) + hre.props.token1 = await hre.ethers.getContractAt('Token20', token1Address) } else { - hre.props.token0 = hre.props.tokenB - hre.props.token1 = hre.props.tokenA - token0Args = ['Dai Stablecoin', 'DAI', this.token1Decimals] - token1Args = ['Wrapped Ether', 'WETH', this.token0Decimals] + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Token20Batcher__factory, + 'token20Batcher', + [] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Token20__factory, + 'tokenA', + ['Wrapped Ether', 'WETH', this.token0Decimals] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Token20__factory, + 'tokenB', + ['Dai Stablecoin', 'DAI', this.token1Decimals] + ) + + const tokenOrder = hre.props.tokenA.address.localeCompare(hre.props.tokenB.address) < 0 + let token0Args + let token1Args + if (tokenOrder) { + hre.props.token0 = hre.props.tokenA + hre.props.token1 = hre.props.tokenB + token0Args = ['Wrapped Ether', 'WETH', this.token0Decimals] + token1Args = ['Dai Stablecoin', 'DAI', this.token1Decimals] + } else { + hre.props.token0 = hre.props.tokenB + hre.props.token1 = hre.props.tokenA + token0Args = ['Dai Stablecoin', 'DAI', this.token1Decimals] + token1Args = ['Wrapped Ether', 'WETH', this.token0Decimals] + } + this.deployAssist.saveContractDeployment( + network, + 'Token20', + 'token0', + hre.props.token0, + token0Args + ) + this.deployAssist.saveContractDeployment( + network, + 'Token20', + 'token1', + hre.props.token1, + token1Args + ) + this.deployAssist.deleteContractDeployment(network, 'tokenA') + this.deployAssist.deleteContractDeployment(network, 'tokenB') } - this.deployAssist.saveContractDeployment( - network, - 'Token20', - 'token0', - hre.props.token0, - token0Args - ) - this.deployAssist.saveContractDeployment( - network, - 'Token20', - 'token1', - hre.props.token1, - token1Args - ) - this.deployAssist.deleteContractDeployment(network, 'tokenA') - this.deployAssist.deleteContractDeployment(network, 'tokenB') - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - UniswapV3FactoryMock__factory, - 'uniswapV3FactoryMock', - [ + if (hre.network.name == 'hardhat') { + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + UniswapV3FactoryMock__factory, + 'uniswapV3FactoryMock', + [ + hre.props.token0.address, + hre.props.token1.address + ] + ) + const mockPoolAddress = await hre.props.uniswapV3FactoryMock.getPool( hre.props.token0.address, - hre.props.token1.address - ] - ) - const mockPoolAddress = await hre.props.uniswapV3FactoryMock.getPool( - hre.props.token0.address, - hre.props.token1.address, - '500' - ) - - hre.props.uniswapV3PoolMock = await hre.ethers.getContractAt('UniswapV3PoolMock', mockPoolAddress) - await this.deployAssist.saveContractDeployment( - network, - 'UniswapV3PoolMock', - 'uniswapV3PoolMock', - hre.props.uniswapV3PoolMock, - [hre.props.token0.address, hre.props.token1.address, '500', '10'] - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - UniswapV3Source__factory, - 'uniswapV3Source', - [ - hre.props.uniswapV3FactoryMock.address - ] - ) + hre.props.token1.address, + '500' + ) + hre.props.uniswapV3PoolMock = await hre.ethers.getContractAt('UniswapV3PoolMock', mockPoolAddress) + await this.deployAssist.saveContractDeployment( + network, + 'UniswapV3PoolMock', + 'uniswapV3PoolMock', + hre.props.uniswapV3PoolMock, + [hre.props.token0.address, hre.props.token1.address, '500', '10'] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + UniswapV3Source__factory, + 'uniswapV3Source', + [ + hre.props.uniswapV3FactoryMock.address + ] + ) + } else if (this.deployPoolsharkLimitSource) { + const limitPoolFactoryAddress = ( + await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + { + networkName: hre.network.name, + objectName: 'limitPoolFactory', + }, + 'initialSetup' + ) + ).contractAddress + + const limitPoolManagerAddress = ( + await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + { + networkName: hre.network.name, + objectName: 'limitPoolManager', + }, + 'initialSetup' + ) + ).contractAddress + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + PoolsharkLimitSource__factory, + 'poolsharkLimitSource', + [ + limitPoolFactoryAddress, + limitPoolManagerAddress, + this.constantProductString + ] + ) + } else if (this.deployUniswapV3Source) { + const uniswapV3FactoryAddress = ( + await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + { + networkName: hre.network.name, + objectName: 'uniswapV3Factory', + }, + 'initialSetup' + ) + ).contractAddress + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + UniswapV3Source__factory, + 'uniswapV3Source', + [ + uniswapV3FactoryAddress + ] + ) + } await this.deployAssist.deployContractWithRetry( network, From 8487b7b06c95efb7b71997958e06ea0d7feb9a19 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sat, 23 Sep 2023 11:10:32 -0600 Subject: [PATCH 05/26] cleanup initial setup --- test/contracts/coverpool.ts | 2 +- test/utils/setup/initialSetup.ts | 553 +++++++++++++++---------------- 2 files changed, 268 insertions(+), 287 deletions(-) diff --git a/test/contracts/coverpool.ts b/test/contracts/coverpool.ts index 159cdfef..b1f0a8b9 100644 --- a/test/contracts/coverpool.ts +++ b/test/contracts/coverpool.ts @@ -61,7 +61,7 @@ describe('CoverPool Tests', function () { const latestTick = globalState.latestTick expect(liquidity).to.be.equal(BN_ZERO) - expect(coverImmutables.genesisTime).to.be.equal(currentTime - 2) + expect(coverImmutables.genesisTime).to.be.equal(currentTime) expect(amountInDelta).to.be.equal(BN_ZERO) expect(latestTick).to.be.equal(BN_ZERO) diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index f7bc9045..900e9f7e 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -162,6 +162,9 @@ export class InitialSetup { hre.props.uniswapV3FactoryMock.address ] ) + await hre.props.uniswapV3PoolMock.setObservationCardinality('10', '10') + + hre.nonce += 1; } else if (this.deployPoolsharkLimitSource) { const limitPoolFactoryAddress = ( await this.contractDeploymentsJson.readContractDeploymentsJsonFile( @@ -216,302 +219,280 @@ export class InitialSetup { ) } - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - TickMap__factory, - 'tickMapLib', - [] - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - EpochMap__factory, - 'epochMapLib', - [] - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Deltas__factory, - 'deltasLib', - [], - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Epochs__factory, - 'epochsLib', - [], - { - 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, - 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, - 'contracts/libraries/EpochMap.sol:EpochMap': hre.props.epochMapLib.address - } - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Ticks__factory, - 'ticksLib', - [], - { - 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address - } - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Claims__factory, - 'claimsLib', - [], - { - 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, - 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, - 'contracts/libraries/EpochMap.sol:EpochMap': hre.props.epochMapLib.address - } - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - Positions__factory, - 'positionsLib', - [], - { - 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, - 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, - 'contracts/libraries/Claims.sol:Claims': hre.props.claimsLib.address - } - ) + if (this.deployContracts || hre.network.name == 'hardhat') { + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + TickMap__factory, + 'tickMapLib', + [] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + EpochMap__factory, + 'epochMapLib', + [] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Deltas__factory, + 'deltasLib', + [], + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Epochs__factory, + 'epochsLib', + [], + { + 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, + 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, + 'contracts/libraries/EpochMap.sol:EpochMap': hre.props.epochMapLib.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Ticks__factory, + 'ticksLib', + [], + { + 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Claims__factory, + 'claimsLib', + [], + { + 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, + 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, + 'contracts/libraries/EpochMap.sol:EpochMap': hre.props.epochMapLib.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + Positions__factory, + 'positionsLib', + [], + { + 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, + 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, + 'contracts/libraries/Claims.sol:Claims': hre.props.claimsLib.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + CoverPoolManager__factory, + 'coverPoolManager', + [] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + CoverPoolFactory__factory, + 'coverPoolFactory', + [ + hre.props.coverPoolManager.address + ] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + MintCall__factory, + 'mintCall', + [], + { + 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, + 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, + 'contracts/libraries/EpochMap.sol:EpochMap': hre.props.epochMapLib.address, + 'contracts/libraries/Ticks.sol:Ticks': hre.props.ticksLib.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + BurnCall__factory, + 'burnCall', + [], + { + 'contracts/libraries/Positions.sol:Positions': hre.props.positionsLib.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + SwapCall__factory, + 'swapCall', + [] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + QuoteCall__factory, + 'quoteCall', + [] + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + CoverPool__factory, + 'coverPoolImpl', + [ + hre.props.coverPoolFactory.address + ], + { + 'contracts/libraries/Positions.sol:Positions': hre.props.positionsLib.address, + 'contracts/libraries/Ticks.sol:Ticks': hre.props.ticksLib.address, + 'contracts/libraries/Epochs.sol:Epochs': hre.props.epochsLib.address, + 'contracts/libraries/pool/MintCall.sol:MintCall': hre.props.mintCall.address, + 'contracts/libraries/pool/BurnCall.sol:BurnCall': hre.props.burnCall.address, + 'contracts/libraries/pool/SwapCall.sol:SwapCall': hre.props.swapCall.address, + 'contracts/libraries/pool/QuoteCall.sol:QuoteCall': hre.props.quoteCall.address + } + ) + + await this.deployAssist.deployContractWithRetry( + network, + // @ts-ignore + PositionERC1155__factory, + 'positionERC1155', + [ + hre.props.coverPoolFactory.address + ] + ) + + const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( + this.uniV3String, + hre.props.coverPoolImpl.address, + hre.props.positionERC1155.address, + hre.props.uniswapV3Source.address + ) + await enableImplTxn.wait(); + + hre.nonce += 1; + } - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - CoverPoolManager__factory, - 'coverPoolManager', - [] - ) + if (this.deployRouter || hre.network.name == 'hardhat') { + await this.deployAssist.deployContractWithRetry( + network, + //@ts-ignore + PoolsharkRouter__factory, + 'poolRouter', + [ + '0xbd6d010bcecc7440a72889546411e0edbb333ea2', // limitPoolFactory + hre.props.coverPoolFactory.address + ] + ) + } - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - CoverPoolFactory__factory, - 'coverPoolFactory', - [ - hre.props.coverPoolManager.address - ] - ) + let coverPoolAddress; let coverPoolTokenAddress; - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - MintCall__factory, - 'mintCall', - [], - { - 'contracts/libraries/Deltas.sol:Deltas': hre.props.deltasLib.address, - 'contracts/libraries/TickMap.sol:TickMap': hre.props.tickMapLib.address, - 'contracts/libraries/EpochMap.sol:EpochMap': hre.props.epochMapLib.address, - 'contracts/libraries/Ticks.sol:Ticks': hre.props.ticksLib.address + if (this.deployPools && hre.network.name != 'hardhat') { + + } else if (hre.network.name == 'hardhat') { + const volTier1: VolatilityTier = { + minAmountPerAuction: BN_ZERO, + auctionLength: 5, + blockTime: 1000, + syncFee: 0, + fillFee: 0, + minPositionWidth: 1, + minAmountLowerPriced: true } - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - BurnCall__factory, - 'burnCall', - [], - { - 'contracts/libraries/Positions.sol:Positions': hre.props.positionsLib.address + + const enableVolTier1 = await hre.props.coverPoolManager.enableVolatilityTier( + this.uniV3String, + 500, // feeTier + 20, // tickSpread + 5, // auctionLength (seconds) + volTier1 + ) + await enableVolTier1.wait(); + + hre.nonce += 1; + + const volTier2: VolatilityTier = { + minAmountPerAuction: BN_ZERO, + auctionLength: 10, + blockTime: 1000, + syncFee: 500, + fillFee: 5000, + minPositionWidth: 5, + minAmountLowerPriced: false } - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - SwapCall__factory, - 'swapCall', - [] - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - QuoteCall__factory, - 'quoteCall', - [] - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - CoverPool__factory, - 'coverPoolImpl', - [ + + const enableVolTier2 = await hre.props.coverPoolManager.enableVolatilityTier( + this.uniV3String, + 500, // feeTier + 40, // tickSpread + 10, // auctionLength (seconds) + volTier2 + ) + await enableVolTier2.wait(); + + hre.nonce += 1; + + const setFactoryTxn = await hre.props.coverPoolManager.setFactory( hre.props.coverPoolFactory.address - ], - { - 'contracts/libraries/Positions.sol:Positions': hre.props.positionsLib.address, - 'contracts/libraries/Ticks.sol:Ticks': hre.props.ticksLib.address, - 'contracts/libraries/Epochs.sol:Epochs': hre.props.epochsLib.address, - 'contracts/libraries/pool/MintCall.sol:MintCall': hre.props.mintCall.address, - 'contracts/libraries/pool/BurnCall.sol:BurnCall': hre.props.burnCall.address, - 'contracts/libraries/pool/SwapCall.sol:SwapCall': hre.props.swapCall.address, - 'contracts/libraries/pool/QuoteCall.sol:QuoteCall': hre.props.quoteCall.address + ) + await setFactoryTxn.wait() + + hre.nonce += 1 + + const poolParams1: CoverPoolParams = { + poolType: this.uniV3String, + tokenIn: hre.props.token0.address, + tokenOut: hre.props.token1.address, + feeTier: 500, + tickSpread: 20, + twapLength: 5 } - ) - - await this.deployAssist.deployContractWithRetry( - network, - // @ts-ignore - PositionERC1155__factory, - 'positionERC1155', - [ - hre.props.coverPoolFactory.address - ] - ) - - const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( - this.uniV3String, - hre.props.coverPoolImpl.address, - hre.props.positionERC1155.address, - hre.props.uniswapV3Source.address - ) - await enableImplTxn.wait(); - - hre.nonce += 1; - - await this.deployAssist.deployContractWithRetry( - network, - //@ts-ignore - PoolsharkRouter__factory, - 'poolRouter', - [ - '0xbd6d010bcecc7440a72889546411e0edbb333ea2', // limitPoolFactory - hre.props.coverPoolFactory.address - ] - ) - - const volTier1: VolatilityTier = { - minAmountPerAuction: BN_ZERO, - auctionLength: 5, - blockTime: 1000, - syncFee: 0, - fillFee: 0, - minPositionWidth: 1, - minAmountLowerPriced: true - } - - const enableVolTier1 = await hre.props.coverPoolManager.enableVolatilityTier( - this.uniV3String, - 500, // feeTier - 20, // tickSpread - 5, // auctionLength (seconds) - volTier1 - ) - await enableVolTier1.wait(); - - hre.nonce += 1; - - const volTier2: VolatilityTier = { - minAmountPerAuction: BN_ZERO, - auctionLength: 10, - blockTime: 1000, - syncFee: 500, - fillFee: 5000, - minPositionWidth: 5, - minAmountLowerPriced: false - } - - const enableVolTier2 = await hre.props.coverPoolManager.enableVolatilityTier( - this.uniV3String, - 500, // feeTier - 40, // tickSpread - 10, // auctionLength (seconds) - volTier2 - ) - await enableVolTier2.wait(); - - hre.nonce += 1; - - const setFactoryTxn = await hre.props.coverPoolManager.setFactory( - hre.props.coverPoolFactory.address - ) - await setFactoryTxn.wait() - - hre.nonce += 1 + + // create first cover pool + let createPoolTxn = await hre.props.coverPoolFactory.createCoverPool( + poolParams1 + ) + await createPoolTxn.wait(); + + hre.nonce += 1; - const poolParams1: CoverPoolParams = { - poolType: this.uniV3String, - tokenIn: hre.props.token0.address, - tokenOut: hre.props.token1.address, - feeTier: 500, - tickSpread: 20, - twapLength: 5 + [coverPoolAddress, coverPoolTokenAddress] = await hre.props.coverPoolFactory.getCoverPool( + poolParams1 + ); } - - // create first cover pool - let createPoolTxn = await hre.props.coverPoolFactory.createCoverPool( - poolParams1 - ) - await createPoolTxn.wait() - - hre.nonce += 1 - - let coverPoolAddress; let coverPoolTokenAddress; - [coverPoolAddress, coverPoolTokenAddress] = await hre.props.coverPoolFactory.getCoverPool( - poolParams1 - ) - hre.props.coverPool = await hre.ethers.getContractAt('CoverPool', coverPoolAddress) - hre.props.coverPoolToken = await hre.ethers.getContractAt('PositionERC1155', coverPoolTokenAddress) - - await this.deployAssist.saveContractDeployment( - network, - 'CoverPool', - 'coverPool', - hre.props.coverPool, - [hre.props.uniswapV3PoolMock.address] - ) - - const poolParams2: CoverPoolParams = { - poolType: this.uniV3String, - tokenIn: hre.props.token0.address, - tokenOut: hre.props.token1.address, - feeTier: 500, - tickSpread: 40, - twapLength: 10 + if (this.deployPools || hre.network.name == 'hardhat') { + hre.props.coverPool = await hre.ethers.getContractAt('CoverPool', coverPoolAddress) + hre.props.coverPoolToken = await hre.ethers.getContractAt('PositionERC1155', coverPoolTokenAddress) + + await this.deployAssist.saveContractDeployment( + network, + 'CoverPool', + 'coverPool', + hre.props.coverPool, + [hre.props.uniswapV3PoolMock.address] + ) } - - // create second cover pool - createPoolTxn = await hre.props.coverPoolFactory.createCoverPool( - poolParams2 - ) - await createPoolTxn.wait() - - hre.nonce += 1 - - coverPoolAddress = await hre.props.coverPoolFactory.getCoverPool( - poolParams2 - ) - hre.props.coverPool2 = await hre.ethers.getContractAt('CoverPool', coverPoolAddress) - - await this.deployAssist.saveContractDeployment( - network, - 'CoverPool', - 'coverPool2', - hre.props.coverPool2, - [hre.props.uniswapV3PoolMock.address] - ) - - await hre.props.uniswapV3PoolMock.setObservationCardinality('10', '10') - return hre.nonce } From 9cd474e61c68dfcb0e19e9c4f7259f4c01a460b0 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sat, 23 Sep 2023 11:19:16 -0600 Subject: [PATCH 06/26] use poolshark limit for testnet --- scripts/autogen/contract-deployments-keys.ts | 20 +++++++++++-- scripts/autogen/contract-deployments.json | 26 +++++++++++------ test/utils/setup/beforeEachProps.ts | 4 +++ test/utils/setup/initialSetup.ts | 30 +++++++++++++------- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index 5f1ee3af..f8bd3a51 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -3,6 +3,22 @@ import { ContractDeploymentsKey } from "../util/files/contractDeploymentsJson"; export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ { networkName: 'arb_goerli', - objectName: 'positionsLib' - } + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'tickMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'deltasLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochsLib' + }, ]; \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index 440d8fc6..6ae5dec8 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -50,27 +50,27 @@ }, "tickMapLib": { "contractName": "TickMap", - "contractAddress": "0xde06Ae292863ecaD9e1103B40088375FF92d05d6", + "contractAddress": "0x97bE8224bA09c1b8c030f3c64b52Fd6e7FAa92AD", "constructorArguments": [], - "created": "2023-09-14T16:32:39.638Z" + "created": "2023-09-23T17:12:48.080Z" }, "epochMapLib": { "contractName": "EpochMap", - "contractAddress": "0x28771dab8a0D8fEc916E72358aCF34f2B5Da988A", + "contractAddress": "0x154FeD0a85be8ed0E7519c6C4F7CfE4F1B21Fa4a", "constructorArguments": [], - "created": "2023-09-14T16:32:41.280Z" + "created": "2023-09-23T17:12:49.847Z" }, "deltasLib": { "contractName": "Deltas", - "contractAddress": "0xDFC658D78505B48aF471D51fdEd2b4bfab17840e", + "contractAddress": "0xaB30983d2F0D116513e2F4a7466D7355bbfb8E8e", "constructorArguments": [], - "created": "2023-09-14T16:32:43.243Z" + "created": "2023-09-23T17:12:52.194Z" }, "epochsLib": { "contractName": "Epochs", - "contractAddress": "0x44638d74537D5fB7D85f3dBe574D0c6DFad0cEf8", + "contractAddress": "0xef8D69326Be24c1F1cBf59ec1a655C95eF71699F", "constructorArguments": [], - "created": "2023-09-14T16:32:45.936Z" + "created": "2023-09-23T17:12:54.551Z" }, "ticksLib": { "contractName": "Ticks", @@ -191,6 +191,16 @@ "0xCF90A2148b8FE67dAB958b75cD358890c4B4a891" ], "created": "2023-09-23T15:58:09.898Z" + }, + "poolsharkLimitSource": { + "contractName": "PoolsharkLimitSource", + "contractAddress": "0x320B395206b6dfDe00002603b8F18aE677df7feF", + "constructorArguments": [ + "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", + "0xcf90a2148b8fe67dab958b75cd358890c4b4a891", + "0x434f4e5354414e542d50524f4455435400000000000000000000000000000000" + ], + "created": "2023-09-23T17:12:45.614Z" } }, "scroll_alpha": { diff --git a/test/utils/setup/beforeEachProps.ts b/test/utils/setup/beforeEachProps.ts index a03914bc..ec64aada 100644 --- a/test/utils/setup/beforeEachProps.ts +++ b/test/utils/setup/beforeEachProps.ts @@ -18,6 +18,7 @@ import { Token20Batcher, PoolsharkRouter, PositionERC1155, + PoolsharkLimitSource, } from '../../../typechain' import { InitialSetup } from './initialSetup' import { MintCall } from '../../../typechain' @@ -41,6 +42,7 @@ export interface BeforeEachProps { epochsLib: Epochs epochMapLib: EpochMap ticksLib: Ticks + poolsharkLimitSource: PoolsharkLimitSource uniswapV3Source: UniswapV3Source claimsLib: Claims positionsLib: Positions @@ -96,6 +98,7 @@ export class GetBeforeEach { let epochsLib: Epochs let epochMapLib: EpochMap let ticksLib: Ticks + let poolsharkLimitSource: PoolsharkLimitSource let uniswapV3Source: UniswapV3Source let claimsLib: Claims let positionsLib: Positions @@ -129,6 +132,7 @@ export class GetBeforeEach { epochsLib, epochMapLib, ticksLib, + poolsharkLimitSource, uniswapV3Source, claimsLib, positionsLib, diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index 900e9f7e..81799002 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -26,6 +26,7 @@ export class InitialSetup { private token0Decimals = 18 private token1Decimals = 18 private uniV3String = ethers.utils.formatBytes32String('UNI-V3') + private poolsharkString = ethers.utils.formatBytes32String('PSHARK-CPROD') private constantProductString = ethers.utils.formatBytes32String('CONSTANT-PRODUCT') private deployAssist: DeployAssist private contractDeploymentsJson: ContractDeploymentsJson @@ -381,16 +382,25 @@ export class InitialSetup { hre.props.coverPoolFactory.address ] ) - - const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( - this.uniV3String, - hre.props.coverPoolImpl.address, - hre.props.positionERC1155.address, - hre.props.uniswapV3Source.address - ) - await enableImplTxn.wait(); - - hre.nonce += 1; + if (hre.network.name == 'hardhat' || this.deployUniswapV3Source) { + const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( + this.uniV3String, + hre.props.coverPoolImpl.address, + hre.props.positionERC1155.address, + hre.props.uniswapV3Source.address + ) + await enableImplTxn.wait(); + hre.nonce += 1; + } else if (this.deployPoolsharkLimitSource) { + const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( + this.poolsharkString, + hre.props.coverPoolImpl.address, + hre.props.positionERC1155.address, + hre.props.poolsharkLimitSource.address + ) + await enableImplTxn.wait(); + hre.nonce += 1; + } } if (this.deployRouter || hre.network.name == 'hardhat') { From cd97b07d34dfdb1fe9df7ddbba4d336efa91c471 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sat, 23 Sep 2023 12:02:43 -0600 Subject: [PATCH 07/26] arbitrum goerli deployment using poolshark source --- contracts/libraries/Epochs.sol | 4 +- .../sources/PoolsharkLimitSource.sol | 2 +- scripts/autogen/contract-deployments-keys.ts | 264 ++++++++++++++++++ scripts/autogen/contract-deployments.json | 78 +++--- test/utils/setup/initialSetup.ts | 166 +++++++++-- 5 files changed, 441 insertions(+), 73 deletions(-) diff --git a/contracts/libraries/Epochs.sol b/contracts/libraries/Epochs.sol index c07f00be..92777d1f 100644 --- a/contracts/libraries/Epochs.sol +++ b/contracts/libraries/Epochs.sol @@ -372,8 +372,8 @@ library Epochs { else auctionsElapsed = type(int32).max - 1; - // if 3/4 of twapLength or auctionLength has passed allow for latestTick move - if (timeElapsed > 3 * constants.twapLength / 4 || + // if 3/4 of auctionLength or auctionLength has passed allow for latestTick move + if (timeElapsed > 3 * constants.auctionLength / 4 || timeElapsed > constants.auctionLength) auctionsElapsed += 1; if (auctionsElapsed < 1) { return (state.latestTick, true); diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 323dc524..f398f416 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -67,7 +67,7 @@ contract PoolsharkLimitSource is ITwapSource { int24 ) { - return ILimitPoolManager(limitPoolManager).feeTiers(feeTier); + return int24(ILimitPoolManager(limitPoolManager).feeTiers(feeTier)); } function getPool( diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index f8bd3a51..92736c0d 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -21,4 +21,268 @@ export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ networkName: 'arb_goerli', objectName: 'epochsLib' }, + { + networkName: 'arb_goerli', + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'tickMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'deltasLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'ticksLib' + }, + { + networkName: 'arb_goerli', + objectName: 'claimsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'positionsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolManager' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolFactory' + }, + { + networkName: 'arb_goerli', + objectName: 'mintCall' + }, + { + networkName: 'arb_goerli', + objectName: 'burnCall' + }, + { + networkName: 'arb_goerli', + objectName: 'swapCall' + }, + { + networkName: 'arb_goerli', + objectName: 'quoteCall' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolImpl' + }, + { + networkName: 'arb_goerli', + objectName: 'positionERC1155' + }, + { + networkName: 'arb_goerli', + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'tickMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'deltasLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'ticksLib' + }, + { + networkName: 'arb_goerli', + objectName: 'claimsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'positionsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolManager' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolFactory' + }, + { + networkName: 'arb_goerli', + objectName: 'mintCall' + }, + { + networkName: 'arb_goerli', + objectName: 'burnCall' + }, + { + networkName: 'arb_goerli', + objectName: 'swapCall' + }, + { + networkName: 'arb_goerli', + objectName: 'quoteCall' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolImpl' + }, + { + networkName: 'arb_goerli', + objectName: 'positionERC1155' + }, + { + networkName: 'arb_goerli', + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'tickMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'deltasLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'ticksLib' + }, + { + networkName: 'arb_goerli', + objectName: 'claimsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'positionsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolManager' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolFactory' + }, + { + networkName: 'arb_goerli', + objectName: 'mintCall' + }, + { + networkName: 'arb_goerli', + objectName: 'burnCall' + }, + { + networkName: 'arb_goerli', + objectName: 'swapCall' + }, + { + networkName: 'arb_goerli', + objectName: 'quoteCall' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolImpl' + }, + { + networkName: 'arb_goerli', + objectName: 'positionERC1155' + }, + { + networkName: 'arb_goerli', + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'tickMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'deltasLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'ticksLib' + }, + { + networkName: 'arb_goerli', + objectName: 'claimsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'positionsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolManager' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolFactory' + }, + { + networkName: 'arb_goerli', + objectName: 'mintCall' + }, + { + networkName: 'arb_goerli', + objectName: 'burnCall' + }, + { + networkName: 'arb_goerli', + objectName: 'swapCall' + }, + { + networkName: 'arb_goerli', + objectName: 'quoteCall' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolImpl' + }, + { + networkName: 'arb_goerli', + objectName: 'positionERC1155' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPool' + }, ]; \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index 6ae5dec8..52a35ac7 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -50,91 +50,89 @@ }, "tickMapLib": { "contractName": "TickMap", - "contractAddress": "0x97bE8224bA09c1b8c030f3c64b52Fd6e7FAa92AD", + "contractAddress": "0x6027C624cAc4d2fB310D9391FAA613C00B17ABE7", "constructorArguments": [], - "created": "2023-09-23T17:12:48.080Z" + "created": "2023-09-23T18:00:02.311Z" }, "epochMapLib": { "contractName": "EpochMap", - "contractAddress": "0x154FeD0a85be8ed0E7519c6C4F7CfE4F1B21Fa4a", + "contractAddress": "0xa316be0Fb53fA66af1dee65eb49f2Cd8C7881a70", "constructorArguments": [], - "created": "2023-09-23T17:12:49.847Z" + "created": "2023-09-23T18:00:03.833Z" }, "deltasLib": { "contractName": "Deltas", - "contractAddress": "0xaB30983d2F0D116513e2F4a7466D7355bbfb8E8e", + "contractAddress": "0xef6d50A917847324FCa1D80A2B3df865028C546E", "constructorArguments": [], - "created": "2023-09-23T17:12:52.194Z" + "created": "2023-09-23T18:00:05.929Z" }, "epochsLib": { "contractName": "Epochs", - "contractAddress": "0xef8D69326Be24c1F1cBf59ec1a655C95eF71699F", + "contractAddress": "0x6F82fEbaC7C548979C4e37AF071cc38de17554d1", "constructorArguments": [], - "created": "2023-09-23T17:12:54.551Z" + "created": "2023-09-23T18:00:08.382Z" }, "ticksLib": { "contractName": "Ticks", - "contractAddress": "0xBc9a51CF74F8d79cEb569679012C5247451e79e4", + "contractAddress": "0x12d0bE0B198B1BB845aC3d704569bA6B04d058C7", "constructorArguments": [], - "created": "2023-09-14T16:32:47.959Z" + "created": "2023-09-23T18:00:11.066Z" }, "claimsLib": { "contractName": "Claims", - "contractAddress": "0x80449022bA3034756b3FE92846E4873eF1F4ae00", + "contractAddress": "0x4b479970384dB32fb35D8c9f28e30a05f0316b44", "constructorArguments": [], - "created": "2023-09-14T16:32:52.204Z" + "created": "2023-09-23T18:00:12.937Z" }, "positionsLib": { "contractName": "Positions", - "contractAddress": "0x3F7e4e0d21aC909E48f7F38CA1B638512B6AF382", + "contractAddress": "0xEFB3B6dEA25a05b4e3318B1598CAC205966C61D4", "constructorArguments": [], - "created": "2023-09-14T16:32:54.823Z" + "created": "2023-09-23T18:00:15.256Z" }, "coverPoolManager": { "contractName": "CoverPoolManager", - "contractAddress": "0x74db8d63FD2e6FAeA61a7a53bFB5Ab319d17f220", + "contractAddress": "0x745a7664d6445972DDF7D8db007357BE536034EB", "constructorArguments": [], - "created": "2023-09-14T16:32:57.398Z" + "created": "2023-09-23T18:00:16.997Z" }, "mintCall": { "contractName": "MintCall", - "contractAddress": "0x2C918C70b02E49264De7b8c7A7a7B87485726342", + "contractAddress": "0x82CaaCCE948567F484fde6c0d2C321a203c0f4a4", "constructorArguments": [], - "created": "2023-09-14T16:33:05.271Z" + "created": "2023-09-23T18:00:22.820Z" }, "burnCall": { "contractName": "BurnCall", - "contractAddress": "0xDd4D0ca909B883c1F35BD7e55FCeB8D3495f5Dc2", + "contractAddress": "0x67EBdb68D3311cC5430E2228952C07f8ca20A1B7", "constructorArguments": [], - "created": "2023-09-14T16:33:07.906Z" + "created": "2023-09-23T18:00:24.820Z" }, "swapCall": { "contractName": "SwapCall", - "contractAddress": "0x832b611c164058aCfefF09a804D05EB0E6FD9ac4", + "contractAddress": "0xA8593D3ff2C6D01fFE08A9974e577c1Acef9fB60", "constructorArguments": [], - "created": "2023-09-14T16:33:09.977Z" + "created": "2023-09-23T18:00:26.557Z" }, "quoteCall": { "contractName": "QuoteCall", - "contractAddress": "0x7A44Ad4d2A0C6feFc45b49aC9ea7821852Fd814a", + "contractAddress": "0xF65490e07646da6f0356Ea13598671fC6EdD701b", "constructorArguments": [], - "created": "2023-09-14T16:33:12.476Z" + "created": "2023-09-23T18:00:28.186Z" }, "coverPoolFactory": { "contractName": "CoverPoolFactory", - "contractAddress": "0x479C2Df7eD63ea26146Ac2092C55047C3928A5A6", + "contractAddress": "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c", "constructorArguments": [ - "0x74db8d63FD2e6FAeA61a7a53bFB5Ab319d17f220" + "0x745a7664d6445972DDF7D8db007357BE536034EB" ], - "created": "2023-09-14T16:33:00.945Z" + "created": "2023-09-23T18:00:18.854Z" }, "coverPool": { "contractName": "CoverPool", - "contractAddress": "0xa91eb93a6be6e49DBF7aF22f7C04C8B219f0Cc93", - "constructorArguments": [ - "0xF4516C95Ea10cD81000ac7cB12dFcD20bED02955" - ], - "created": "2023-09-14T16:33:34.141Z" + "contractAddress": "0x7cBe93e093dcBE1904EE1643D8BD334798E3C795", + "constructorArguments": [], + "created": "2023-09-23T18:00:45.211Z" }, "coverPool2": { "contractName": "CoverPool", @@ -155,11 +153,11 @@ }, "coverPoolImpl": { "contractName": "CoverPool", - "contractAddress": "0x31e7DE9329b0695fcEAb321D2AA7fB805e1bF4E0", + "contractAddress": "0x231a1b45cC694c28b9e271C75A219fD62396c0F9", "constructorArguments": [ - "0x479C2Df7eD63ea26146Ac2092C55047C3928A5A6" + "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c" ], - "created": "2023-09-14T16:33:15.618Z" + "created": "2023-09-23T18:00:30.047Z" }, "poolRouter": { "contractName": "PoolsharkRouter", @@ -172,11 +170,11 @@ }, "positionERC1155": { "contractName": "PositionERC1155", - "contractAddress": "0x6F31bc34C050817f8d95256841D72FA4bE32c22A", + "contractAddress": "0xFaa4E35794D0d957C5e0327EdD75C38A047896F9", "constructorArguments": [ - "0x479C2Df7eD63ea26146Ac2092C55047C3928A5A6" + "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c" ], - "created": "2023-09-14T16:33:18.642Z" + "created": "2023-09-23T18:00:31.764Z" }, "limitPoolManager": { "contractName": "LimitPoolManager", @@ -194,13 +192,13 @@ }, "poolsharkLimitSource": { "contractName": "PoolsharkLimitSource", - "contractAddress": "0x320B395206b6dfDe00002603b8F18aE677df7feF", + "contractAddress": "0xFcD4C999a83d20DF863E5372e8bbCBE0f26a7374", "constructorArguments": [ "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", "0xcf90a2148b8fe67dab958b75cd358890c4b4a891", "0x434f4e5354414e542d50524f4455435400000000000000000000000000000000" ], - "created": "2023-09-23T17:12:45.614Z" + "created": "2023-09-23T18:00:00.255Z" } }, "scroll_alpha": { diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index 81799002..21e1919a 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -312,6 +312,13 @@ export class InitialSetup { hre.props.coverPoolManager.address ] ) + + const setFactoryTxn = await hre.props.coverPoolManager.setFactory( + hre.props.coverPoolFactory.address + ) + await setFactoryTxn.wait() + + hre.nonce += 1 await this.deployAssist.deployContractWithRetry( network, @@ -382,6 +389,7 @@ export class InitialSetup { hre.props.coverPoolFactory.address ] ) + if (hre.network.name == 'hardhat' || this.deployUniswapV3Source) { const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( this.uniV3String, @@ -400,6 +408,7 @@ export class InitialSetup { ) await enableImplTxn.wait(); hre.nonce += 1; + console.log('impl enabled') } } @@ -419,7 +428,132 @@ export class InitialSetup { let coverPoolAddress; let coverPoolTokenAddress; if (this.deployPools && hre.network.name != 'hardhat') { + let poolParams1: CoverPoolParams; + if (this.deployPoolsharkLimitSource) { + // ENABLE VOL TIER 1 + console.log('vol tier 1') + const volTier1: VolatilityTier = { + minAmountPerAuction: BN_ZERO, + auctionLength: 12, + blockTime: 300, + syncFee: 0, + fillFee: 0, + minPositionWidth: 1, + minAmountLowerPriced: true + } + + const enableVolTier1 = await hre.props.coverPoolManager.enableVolatilityTier( + this.poolsharkString, + 1000, // feeTier + 20, // tickSpread + 12, // twapLength (seconds) = ~40 arbitrum blocks + volTier1 + ) + await enableVolTier1.wait(); + + hre.nonce += 1; + console.log('pool 1') + + // CREATE POOL 1 + poolParams1 = { + poolType: this.poolsharkString, + tokenIn: hre.props.token0.address, + tokenOut: hre.props.token1.address, + feeTier: 1000, + tickSpread: 20, + twapLength: 12 + } + let createPoolTxn = await hre.props.coverPoolFactory.createCoverPool( + poolParams1 + ) + await createPoolTxn.wait(); + + hre.nonce += 1; + + // CREATE VOL TIER 2 + console.log('vol tier 2') + const volTier2: VolatilityTier = { + minAmountPerAuction: BN_ZERO, + auctionLength: 12, + blockTime: 300, + syncFee: 0, + fillFee: 0, + minPositionWidth: 1, + minAmountLowerPriced: true + } + + const enableVolTier2 = await hre.props.coverPoolManager.enableVolatilityTier( + this.poolsharkString, + 3000, // feeTier + 60, // tickSpread + 12, // twapLength (seconds) = ~40 arbitrum blocks + volTier2 + ) + await enableVolTier2.wait(); + + hre.nonce += 1; + + // CREATE POOL 2 + console.log('pool 2') + const poolParams2: CoverPoolParams = { + poolType: this.poolsharkString, + tokenIn: hre.props.token0.address, + tokenOut: hre.props.token1.address, + feeTier: 3000, + tickSpread: 60, + twapLength: 12 + } + let createPoolTxn2 = await hre.props.coverPoolFactory.createCoverPool( + poolParams2 + ) + await createPoolTxn2.wait(); + + hre.nonce += 1; + + // CREATE VOL TIER 3 + console.log('vol tier 3') + const volTier3: VolatilityTier = { + minAmountPerAuction: BN_ZERO, + auctionLength: 5 , + blockTime: 300, + syncFee: 0, + fillFee: 0, + minPositionWidth: 1, + minAmountLowerPriced: true + } + const enableVolTier3 = await hre.props.coverPoolManager.enableVolatilityTier( + this.poolsharkString, + 10000, // feeTier + 200, // tickSpread + 12, // twapLength (seconds) = ~40 arbitrum blocks + volTier3 + ) + await enableVolTier3.wait(); + + hre.nonce += 1; + + // CREATE POOL 3 + console.log('pool 3') + const poolParams3: CoverPoolParams = { + poolType: this.poolsharkString, + tokenIn: hre.props.token0.address, + tokenOut: hre.props.token1.address, + feeTier: 10000, + tickSpread: 200, + twapLength: 12 + } + let createPoolTxn3 = await hre.props.coverPoolFactory.createCoverPool( + poolParams3 + ) + await createPoolTxn3.wait(); + + hre.nonce += 1; + } + + [coverPoolAddress, coverPoolTokenAddress] = await hre.props.coverPoolFactory.getCoverPool( + poolParams1 + ); } else if (hre.network.name == 'hardhat') { const volTier1: VolatilityTier = { minAmountPerAuction: BN_ZERO, @@ -435,41 +569,13 @@ export class InitialSetup { this.uniV3String, 500, // feeTier 20, // tickSpread - 5, // auctionLength (seconds) + 5, // twapLength (seconds) volTier1 ) await enableVolTier1.wait(); hre.nonce += 1; - const volTier2: VolatilityTier = { - minAmountPerAuction: BN_ZERO, - auctionLength: 10, - blockTime: 1000, - syncFee: 500, - fillFee: 5000, - minPositionWidth: 5, - minAmountLowerPriced: false - } - - const enableVolTier2 = await hre.props.coverPoolManager.enableVolatilityTier( - this.uniV3String, - 500, // feeTier - 40, // tickSpread - 10, // auctionLength (seconds) - volTier2 - ) - await enableVolTier2.wait(); - - hre.nonce += 1; - - const setFactoryTxn = await hre.props.coverPoolManager.setFactory( - hre.props.coverPoolFactory.address - ) - await setFactoryTxn.wait() - - hre.nonce += 1 - const poolParams1: CoverPoolParams = { poolType: this.uniV3String, tokenIn: hre.props.token0.address, @@ -500,7 +606,7 @@ export class InitialSetup { 'CoverPool', 'coverPool', hre.props.coverPool, - [hre.props.uniswapV3PoolMock.address] + [] ) } return hre.nonce From 78c88ef77df9786feaf00f1a49fa1bd0d5495a0e Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 08:10:06 -0600 Subject: [PATCH 08/26] refactor initial twap source initialization sequence --- contracts/CoverPool.sol | 26 +- contracts/CoverPoolFactory.sol | 6 +- .../base/events/CoverPoolManagerEvents.sol | 2 +- .../base/storage/CoverPoolImmutables.sol | 2 +- contracts/interfaces/cover/ICoverPool.sol | 5 +- .../external/poolshark/limit/ILimitPool.sol | 8 +- contracts/interfaces/range/IRangePool.sol | 4 +- .../interfaces/structs/CoverPoolStructs.sol | 2 +- .../interfaces/structs/PoolsharkStructs.sol | 2 +- contracts/libraries/Epochs.sol | 2 +- .../sources/PoolsharkLimitSource.sol | 22 +- .../libraries/sources/UniswapV3Source.sol | 8 +- contracts/test/LimitPoolMock.sol | 24 +- contracts/utils/CoverPoolManager.sol | 6 +- contracts/utils/PoolsharkRouter.sol | 2 +- contracts/utils/PositionERC1155.sol | 2 +- scripts/autogen/contract-deployments-keys.ts | 282 +----------------- scripts/autogen/contract-deployments.json | 8 +- tasks/deploy/utils/mintPosition.ts | 4 +- test/contracts/coverpool.ts | 1 - test/contracts/coverpoolmanager.ts | 26 +- test/utils/contracts/coverpool.ts | 4 +- test/utils/setup/initialSetup.ts | 20 +- 23 files changed, 114 insertions(+), 354 deletions(-) diff --git a/contracts/CoverPool.sol b/contracts/CoverPool.sol index 61585f4e..e6da11d3 100644 --- a/contracts/CoverPool.sol +++ b/contracts/CoverPool.sol @@ -30,6 +30,11 @@ contract CoverPool is _; } + modifier factoryOnly() { + _onlyFactory(); + _; + } + modifier canoncialOnly() { _onlyCanoncialClones(); _; @@ -42,6 +47,19 @@ contract CoverPool is factory = factory_; } + function initialize() + external + factoryOnly + { + Ticks.initialize( + tickMap, + pool0, + pool1, + globalState, + ICoverPool(address(this)).immutables() + ); + } + function mint( MintCoverParams memory params ) external override @@ -256,7 +274,7 @@ contract CoverPool is tickSpread(), twapLength(), auctionLength(), - blockTime(), + sampleInterval(), token0Decimals(), token1Decimals(), minAmountLowerPriced() @@ -311,7 +329,7 @@ contract CoverPool is constants.auctionLength ); bytes memory value2 = abi.encodePacked( - constants.blockTime, + constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced @@ -322,4 +340,8 @@ contract CoverPool is function _onlyOwner() private view { if (msg.sender != owner()) revert OwnerOnly(); } + + function _onlyFactory() private view { + if (msg.sender != factory) revert FactoryOnly(); + } } diff --git a/contracts/CoverPoolFactory.sol b/contracts/CoverPoolFactory.sol index 7fbb0bc1..fe846113 100644 --- a/contracts/CoverPoolFactory.sol +++ b/contracts/CoverPoolFactory.sol @@ -75,7 +75,7 @@ contract CoverPoolFactory is if (config.auctionLength == 0) revert VolatilityTierNotSupported(); constants.minAmountPerAuction = config.minAmountPerAuction; constants.auctionLength = config.auctionLength; - constants.blockTime = config.blockTime; + constants.sampleInterval = config.sampleInterval; constants.minPositionWidth = config.minPositionWidth; constants.minAmountLowerPriced = config.minAmountLowerPriced; } @@ -120,6 +120,8 @@ contract CoverPoolFactory is data: encodeCover(constants) }); + ICoverPool(pool).initialize(); + poolToken = constants.poolToken; coverPools[key] = pool; @@ -195,7 +197,7 @@ contract CoverPoolFactory is constants.auctionLength ); bytes memory value2 = abi.encodePacked( - constants.blockTime, + constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced diff --git a/contracts/base/events/CoverPoolManagerEvents.sol b/contracts/base/events/CoverPoolManagerEvents.sol index 21d39dcf..92011d01 100644 --- a/contracts/base/events/CoverPoolManagerEvents.sol +++ b/contracts/base/events/CoverPoolManagerEvents.sol @@ -10,7 +10,7 @@ abstract contract CoverPoolManagerEvents { uint16 twapLength, uint128 minAmountPerAuction, uint16 auctionLength, - uint16 blockTime, + uint16 sampleInterval, uint16 syncFee, uint16 fillFee, int16 minPositionWidth, diff --git a/contracts/base/storage/CoverPoolImmutables.sol b/contracts/base/storage/CoverPoolImmutables.sol index 2ee2a265..6e604826 100644 --- a/contracts/base/storage/CoverPoolImmutables.sol +++ b/contracts/base/storage/CoverPoolImmutables.sol @@ -60,7 +60,7 @@ contract CoverPoolImmutables is Clone { return _getArgUint16(186); } - function blockTime() public pure returns (uint16) { + function sampleInterval() public pure returns (uint16) { return _getArgUint16(188); } diff --git a/contracts/interfaces/cover/ICoverPool.sol b/contracts/interfaces/cover/ICoverPool.sol index 872dc41a..bd03524d 100644 --- a/contracts/interfaces/cover/ICoverPool.sol +++ b/contracts/interfaces/cover/ICoverPool.sol @@ -10,7 +10,10 @@ import '../structs/PoolsharkStructs.sol'; * @notice Defines the basic interface for a Cover Pool. */ interface ICoverPool is CoverPoolStructs { - + /** + * @notice Initializes the TWAP source + */ + function initialize() external; /** * @notice Deposits `amountIn` of asset to be auctioned off each time price range is crossed further into. diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPool.sol b/contracts/interfaces/external/poolshark/limit/ILimitPool.sol index a6d2840b..f4045835 100644 --- a/contracts/interfaces/external/poolshark/limit/ILimitPool.sol +++ b/contracts/interfaces/external/poolshark/limit/ILimitPool.sol @@ -17,8 +17,8 @@ interface ILimitPool { struct SampleState { uint16 index; - uint16 length; - uint16 lengthNext; + uint16 count; + uint16 countMax; } struct LimitPoolState { @@ -39,8 +39,8 @@ interface ILimitPool { int24 averageTick ); - function increaseSampleLength( - uint16 sampleLengthNext + function increaseSampleCount( + uint16 newSampleCountMax ) external; function globalState() external view returns ( diff --git a/contracts/interfaces/range/IRangePool.sol b/contracts/interfaces/range/IRangePool.sol index a4381c2d..ce0f3d08 100644 --- a/contracts/interfaces/range/IRangePool.sol +++ b/contracts/interfaces/range/IRangePool.sol @@ -36,7 +36,7 @@ interface IRangePool is PoolsharkStructs { uint128 feesOwed1 ); - function increaseSampleLength( - uint16 sampleLengthNext + function increaseSampleCount( + uint16 newSampleCountMax ) external; } diff --git a/contracts/interfaces/structs/CoverPoolStructs.sol b/contracts/interfaces/structs/CoverPoolStructs.sol index 8501458f..1abb7854 100644 --- a/contracts/interfaces/structs/CoverPoolStructs.sol +++ b/contracts/interfaces/structs/CoverPoolStructs.sol @@ -66,7 +66,7 @@ interface CoverPoolStructs is PoolsharkStructs { struct VolatilityTier { uint128 minAmountPerAuction; // based on 18 decimals and then converted based on token decimals uint16 auctionLength; - uint16 blockTime; // average block time where 1e3 is 1 second + uint16 sampleInterval; // average block time where 1e3 is 1 second uint16 syncFee; uint16 fillFee; int16 minPositionWidth; diff --git a/contracts/interfaces/structs/PoolsharkStructs.sol b/contracts/interfaces/structs/PoolsharkStructs.sol index aef64c24..f4d1d2bd 100644 --- a/contracts/interfaces/structs/PoolsharkStructs.sol +++ b/contracts/interfaces/structs/PoolsharkStructs.sol @@ -32,7 +32,7 @@ interface PoolsharkStructs { int16 tickSpread; uint16 twapLength; uint16 auctionLength; - uint16 blockTime; + uint16 sampleInterval; uint8 token0Decimals; uint8 token1Decimals; bool minAmountLowerPriced; diff --git a/contracts/libraries/Epochs.sol b/contracts/libraries/Epochs.sol index 92777d1f..247af5db 100644 --- a/contracts/libraries/Epochs.sol +++ b/contracts/libraries/Epochs.sol @@ -373,7 +373,7 @@ library Epochs { auctionsElapsed = type(int32).max - 1; // if 3/4 of auctionLength or auctionLength has passed allow for latestTick move - if (timeElapsed > 3 * constants.auctionLength / 4 || + if (timeElapsed > 3 * constants.twapLength / 4 || timeElapsed > constants.auctionLength) auctionsElapsed += 1; if (auctionsElapsed < 1) { return (state.latestTick, true); diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index f398f416..9bf4bc70 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -36,16 +36,16 @@ contract PoolsharkLimitSource is ITwapSource { ) { // get the number of blocks covered by the twapLength - uint32 blockCount = uint32(constants.twapLength) * oneSecond / constants.blockTime; + uint32 blockCount = uint32(constants.twapLength) * oneSecond / constants.sampleInterval; ( bool sampleCountEnough, bool sampleLengthEnough - ) = _isPoolSamplesEnough( + ) = _isPoolSampleCountEnough( constants.inputPool, blockCount ); if (!sampleLengthEnough) { - _increaseSampleLength(constants.inputPool, blockCount); + _increaseSampleCount(constants.inputPool, blockCount); return (0, 0); } else if (!sampleCountEnough) { return (0, 0); @@ -108,9 +108,9 @@ contract PoolsharkLimitSource is ITwapSource { { uint32[] memory secondsAgos = new uint32[](4); /// @dev - take 4 samples - /// @dev - twapLength must be >= 5 * blockTime - uint32 timeDelta = constants.blockTime / oneSecond == 0 ? 2 - : constants.blockTime * 2 / oneSecond; + /// @dev - twapLength must be >= 5 * sampleInterval + uint32 timeDelta = constants.sampleInterval / oneSecond == 0 ? 2 + : constants.sampleInterval * 2 / oneSecond; secondsAgos[0] = 0; secondsAgos[1] = timeDelta; secondsAgos[2] = constants.twapLength - timeDelta; @@ -134,7 +134,7 @@ contract PoolsharkLimitSource is ITwapSource { } } - function _isPoolSamplesEnough( + function _isPoolSampleCountEnough( address pool, uint32 blockCount ) internal view returns ( @@ -147,12 +147,12 @@ contract PoolsharkLimitSource is ITwapSource { ,,,,, ) = ILimitPool(pool).globalState(); return ( - poolState.samples.length >= blockCount, - poolState.samples.lengthNext >= blockCount + poolState.samples.count >= blockCount, + poolState.samples.countMax >= blockCount ); } - function _increaseSampleLength(address pool, uint32 blockCount) internal { - ILimitPool(pool).increaseSampleLength(uint16(blockCount)); + function _increaseSampleCount(address pool, uint32 blockCount) internal { + ILimitPool(pool).increaseSampleCount(uint16(blockCount)); } } diff --git a/contracts/libraries/sources/UniswapV3Source.sol b/contracts/libraries/sources/UniswapV3Source.sol index 7c7b557a..4131a550 100644 --- a/contracts/libraries/sources/UniswapV3Source.sol +++ b/contracts/libraries/sources/UniswapV3Source.sol @@ -28,7 +28,7 @@ contract UniswapV3Source is ITwapSource { ) { // get the number of blocks covered by the twapLength - uint32 blockCount = uint32(constants.twapLength) * oneSecond / constants.blockTime; + uint32 blockCount = uint32(constants.twapLength) * oneSecond / constants.sampleInterval; ( bool observationsCountEnough, bool observationsLengthEnough @@ -100,9 +100,9 @@ contract UniswapV3Source is ITwapSource { { uint32[] memory secondsAgos = new uint32[](4); /// @dev - take 4 samples - /// @dev - twapLength must be >= 5 * blockTime - uint32 timeDelta = (constants.blockTime / oneSecond == 0) ? 2 - : constants.blockTime * 2 / oneSecond; + /// @dev - twapLength must be >= 5 * sampleInterval + uint32 timeDelta = (constants.sampleInterval / oneSecond == 0) ? 2 + : constants.sampleInterval * 2 / oneSecond; secondsAgos[0] = 0; secondsAgos[1] = timeDelta; secondsAgos[2] = constants.twapLength - timeDelta; diff --git a/contracts/test/LimitPoolMock.sol b/contracts/test/LimitPoolMock.sol index b36966c9..14e1e02a 100644 --- a/contracts/test/LimitPoolMock.sol +++ b/contracts/test/LimitPoolMock.sol @@ -11,8 +11,8 @@ contract LimitPoolMock is ILimitPool { int24 public tickSpacing; uint256 swapFee; - uint16 sampleLength; - uint16 sampleLengthNext; + uint16 sampleCount; + uint16 sampleCountMax; int56 tickCumulative0; int56 tickCumulative1; @@ -31,8 +31,8 @@ contract LimitPoolMock is ILimitPool { token1 = _token1; swapFee = _swapFee; tickSpacing = _tickSpacing; - sampleLength = 4; - sampleLengthNext = 4; + sampleCount = 4; + sampleCountMax = 4; tickCumulative0 = 10; tickCumulative1 = 9; tickCumulative2 = 6; @@ -54,8 +54,8 @@ contract LimitPoolMock is ILimitPool { { pool.samples = SampleState( 4, - sampleLength, - sampleLengthNext + sampleCount, + sampleCountMax ); pool0; pool1; @@ -91,8 +91,10 @@ contract LimitPoolMock is ILimitPool { averageTick; } - function increaseSampleLength(uint16 cardinalityNext) external { - sampleLengthNext = cardinalityNext; + function increaseSampleCount( + uint16 newSampleCountMax + ) external { + sampleCountMax = newSampleCountMax; } function setTickCumulatives(int56 _tickCumulative0, int56 _tickCumulative1, int56 _tickCumulative2, int56 _tickCumulative3) external { @@ -102,8 +104,8 @@ contract LimitPoolMock is ILimitPool { tickCumulative3 = _tickCumulative3; } - function setObservationCardinality(uint16 _sampleLength, uint16 _sampleLengthNext) external { - sampleLength = _sampleLength; - sampleLengthNext = _sampleLengthNext; + function setObservationCardinality(uint16 _sampleCount, uint16 _sampleCountMax) external { + sampleCount = _sampleCount; + sampleCountMax = _sampleCountMax; } } diff --git a/contracts/utils/CoverPoolManager.sol b/contracts/utils/CoverPoolManager.sol index c0298744..9ad2e169 100644 --- a/contracts/utils/CoverPoolManager.sol +++ b/contracts/utils/CoverPoolManager.sol @@ -104,7 +104,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { require (false, 'VolatilityTierAlreadyEnabled()'); } else if (volTier.auctionLength == 0 || volTier.minPositionWidth <= 0) { require (false, 'VolatilityTierCannotBeZero()'); - } else if (twapLength < 5 * volTier.blockTime / oneSecond) { + } else if (twapLength < 5 * volTier.sampleInterval / oneSecond) { require (false, 'VoltatilityTierTwapTooShort()'); } else if (volTier.syncFee > 10000 || volTier.fillFee > 10000) { require (false, 'ProtocolFeeCeilingExceeded()'); @@ -125,7 +125,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { require (false, 'TickSpreadNotAtLeastDoubleTickSpread()'); } } - // twapLength * blockTime should never overflow uint16 + // twapLength * sampleInterval should never overflow uint16 _volatilityTiers[poolType][feeTier][tickSpread][twapLength] = volTier; emit VolatilityTierEnabled( @@ -135,7 +135,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { twapLength, volTier.minAmountPerAuction, volTier.auctionLength, - volTier.blockTime, + volTier.sampleInterval, volTier.syncFee, volTier.fillFee, volTier.minPositionWidth, diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index 5a81cf41..a0bc823b 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -489,7 +489,7 @@ contract PoolsharkRouter is constants.auctionLength ); bytes memory value2 = abi.encodePacked( - constants.blockTime, + constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced diff --git a/contracts/utils/PositionERC1155.sol b/contracts/utils/PositionERC1155.sol index af1ef7e8..2afedbee 100644 --- a/contracts/utils/PositionERC1155.sol +++ b/contracts/utils/PositionERC1155.sol @@ -332,7 +332,7 @@ contract PositionERC1155 is constants.auctionLength ); bytes memory value2 = abi.encodePacked( - constants.blockTime, + constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index 92736c0d..f2656e36 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -1,288 +1,8 @@ import { ContractDeploymentsKey } from "../util/files/contractDeploymentsJson"; export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'tickMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'deltasLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'tickMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'deltasLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'ticksLib' - }, - { - networkName: 'arb_goerli', - objectName: 'claimsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'positionsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolManager' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolFactory' - }, - { - networkName: 'arb_goerli', - objectName: 'mintCall' - }, - { - networkName: 'arb_goerli', - objectName: 'burnCall' - }, - { - networkName: 'arb_goerli', - objectName: 'swapCall' - }, - { - networkName: 'arb_goerli', - objectName: 'quoteCall' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolImpl' - }, - { - networkName: 'arb_goerli', - objectName: 'positionERC1155' - }, - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'tickMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'deltasLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'ticksLib' - }, { networkName: 'arb_goerli', objectName: 'claimsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'positionsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolManager' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolFactory' - }, - { - networkName: 'arb_goerli', - objectName: 'mintCall' - }, - { - networkName: 'arb_goerli', - objectName: 'burnCall' - }, - { - networkName: 'arb_goerli', - objectName: 'swapCall' - }, - { - networkName: 'arb_goerli', - objectName: 'quoteCall' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolImpl' - }, - { - networkName: 'arb_goerli', - objectName: 'positionERC1155' - }, - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'tickMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'deltasLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'ticksLib' - }, - { - networkName: 'arb_goerli', - objectName: 'claimsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'positionsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolManager' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolFactory' - }, - { - networkName: 'arb_goerli', - objectName: 'mintCall' - }, - { - networkName: 'arb_goerli', - objectName: 'burnCall' - }, - { - networkName: 'arb_goerli', - objectName: 'swapCall' - }, - { - networkName: 'arb_goerli', - objectName: 'quoteCall' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolImpl' - }, - { - networkName: 'arb_goerli', - objectName: 'positionERC1155' - }, - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'tickMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'deltasLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'ticksLib' - }, - { - networkName: 'arb_goerli', - objectName: 'claimsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'positionsLib' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolManager' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolFactory' - }, - { - networkName: 'arb_goerli', - objectName: 'mintCall' - }, - { - networkName: 'arb_goerli', - objectName: 'burnCall' - }, - { - networkName: 'arb_goerli', - objectName: 'swapCall' - }, - { - networkName: 'arb_goerli', - objectName: 'quoteCall' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolImpl' - }, - { - networkName: 'arb_goerli', - objectName: 'positionERC1155' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPool' - }, + } ]; \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index 52a35ac7..cc945a36 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -161,12 +161,12 @@ }, "poolRouter": { "contractName": "PoolsharkRouter", - "contractAddress": "0x1759c96aAD9A7E52F6d9c06573e0E0b418Bbdf74", + "contractAddress": "0x4aefd9449f4d827c4e5343a719ed082e68a1e145", "constructorArguments": [ - "0xbd6d010bcecc7440a72889546411e0edbb333ea2", - "0x479C2Df7eD63ea26146Ac2092C55047C3928A5A6" + "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", + "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c" ], - "created": "2023-09-14T16:33:25 .036Z" + "created": "2023-09-23T23:15:36.059Z" }, "positionERC1155": { "contractName": "PositionERC1155", diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index d90596ce..78006184 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -43,8 +43,8 @@ export class MintPosition { await validateMint({ signer: hre.props.alice, recipient: hre.props.alice.address, - lower: '78000', - upper: '79000', + lower: '71000', //1211 + upper: '70000', //1096 amount: token1Amount, zeroForOne: true, balanceInDecrease: token1Amount, diff --git a/test/contracts/coverpool.ts b/test/contracts/coverpool.ts index b1f0a8b9..8dddc810 100644 --- a/test/contracts/coverpool.ts +++ b/test/contracts/coverpool.ts @@ -131,7 +131,6 @@ describe('CoverPool Tests', function () { upperTickCleared: false, revertMessage: 'WaitUntilTwapLengthSufficient()', }) - }) it('pool1 - Should wait until enough observations', async function () { diff --git a/test/contracts/coverpoolmanager.ts b/test/contracts/coverpoolmanager.ts index df5d383c..412b9e4a 100644 --- a/test/contracts/coverpoolmanager.ts +++ b/test/contracts/coverpoolmanager.ts @@ -28,7 +28,9 @@ describe('CoverPoolManager Tests', function () { await gBefore() }) - this.beforeEach(async function () {}) + this.beforeEach(async function () { + await hre.props.uniswapV3PoolMock.setObservationCardinality('5', '5') + }) it('Should be able to change owner', async function () { // check pool contract owner @@ -164,7 +166,7 @@ describe('CoverPoolManager Tests', function () { const volTier: VolatilityTier = { minAmountPerAuction: ethers.utils.parseUnits("1", 18), auctionLength: 40, - blockTime: 1000, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 4, @@ -181,7 +183,7 @@ describe('CoverPoolManager Tests', function () { const volTier: VolatilityTier = { minAmountPerAuction: ethers.utils.parseUnits("1", 18), auctionLength: 20, - blockTime: 1000, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 1, @@ -198,7 +200,7 @@ describe('CoverPoolManager Tests', function () { const volTier: VolatilityTier = { minAmountPerAuction: ethers.utils.parseUnits("1", 18), auctionLength: 20, - blockTime: 1000, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 1, @@ -312,12 +314,13 @@ describe('CoverPoolManager Tests', function () { const volTier: VolatilityTier = { minAmountPerAuction: ethers.utils.parseUnits("1", 18), auctionLength: 30, - blockTime: 1000, + sampleInterval: 1000, syncFee: 50, fillFee: 500, minPositionWidth: 5, minAmountLowerPriced: true } + await expect( hre.props.coverPoolManager .connect(hre.props.bob) @@ -330,22 +333,21 @@ describe('CoverPoolManager Tests', function () { .enableVolatilityTier(uniV3String, "500", "20", "5", volTier) ).to.be.revertedWith('VolatilityTierAlreadyEnabled()') - await expect( + await hre.props.coverPoolManager .connect(hre.props.admin) .enableVolatilityTier(uniV3String, "500", "40", "10", volTier) - ).to.be.revertedWith('VolatilityTierAlreadyEnabled()') let volatilityTierConfig = await hre.props.coverPoolManager .volatilityTiers(uniV3String, "500", "40", "10"); - expect(volatilityTierConfig[0]).to.be.equal(BN_ZERO) - expect(volatilityTierConfig[1]).to.be.equal(10) + expect(volatilityTierConfig[0]).to.be.equal(ethers.utils.parseUnits("1", 18)) + expect(volatilityTierConfig[1]).to.be.equal(30) expect(volatilityTierConfig[2]).to.be.equal(1000) - expect(volatilityTierConfig[3]).to.be.equal(500) - expect(volatilityTierConfig[4]).to.be.equal(5000) + expect(volatilityTierConfig[3]).to.be.equal(50) + expect(volatilityTierConfig[4]).to.be.equal(500) expect(volatilityTierConfig[5]).to.be.equal(5) - expect(volatilityTierConfig[6]).to.be.equal(false) + expect(volatilityTierConfig[6]).to.be.equal(true) expect((await hre.props.coverPoolManager diff --git a/test/utils/contracts/coverpool.ts b/test/utils/contracts/coverpool.ts index 1974ccfe..eed58fc8 100644 --- a/test/utils/contracts/coverpool.ts +++ b/test/utils/contracts/coverpool.ts @@ -23,7 +23,7 @@ export interface PoolState { export interface VolatilityTier { minAmountPerAuction: BigNumber // based on 18 decimals and then converted based on token decimals auctionLength: number - blockTime: number // average block time where 1e3 is 1 second + sampleInterval: number // average block time where 1e3 is 1 second syncFee: number fillFee: number minPositionWidth: number @@ -44,7 +44,7 @@ export interface CoverImmutables { tickSpread: number twapLength: number auctionLength: number - blockTime: number + sampleInterval: number token0Decimals: number token1Decimals: number minAmountLowerPriced: boolean diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index 21e1919a..8ffaf806 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -163,7 +163,7 @@ export class InitialSetup { hre.props.uniswapV3FactoryMock.address ] ) - await hre.props.uniswapV3PoolMock.setObservationCardinality('10', '10') + await hre.props.uniswapV3PoolMock.setObservationCardinality('4', '4') hre.nonce += 1; } else if (this.deployPoolsharkLimitSource) { @@ -435,7 +435,7 @@ export class InitialSetup { const volTier1: VolatilityTier = { minAmountPerAuction: BN_ZERO, auctionLength: 12, - blockTime: 300, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 1, @@ -475,7 +475,7 @@ export class InitialSetup { const volTier2: VolatilityTier = { minAmountPerAuction: BN_ZERO, auctionLength: 12, - blockTime: 300, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 1, @@ -515,7 +515,7 @@ export class InitialSetup { const volTier3: VolatilityTier = { minAmountPerAuction: BN_ZERO, auctionLength: 5 , - blockTime: 300, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 1, @@ -558,7 +558,7 @@ export class InitialSetup { const volTier1: VolatilityTier = { minAmountPerAuction: BN_ZERO, auctionLength: 5, - blockTime: 1000, + sampleInterval: 1000, syncFee: 0, fillFee: 0, minPositionWidth: 1, @@ -669,6 +669,15 @@ export class InitialSetup { 'readCoverPoolSetup' ) ).contractAddress + const poolsharkRouterAddress = ( + await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + { + networkName: hre.network.name, + objectName: 'poolRouter', + }, + 'readCoverPoolSetup' + ) + ).contractAddress hre.props.token0 = await hre.ethers.getContractAt('Token20', token0Address) hre.props.token1 = await hre.ethers.getContractAt('Token20', token1Address) @@ -676,6 +685,7 @@ export class InitialSetup { hre.props.coverPool = await hre.ethers.getContractAt('CoverPool', coverPoolAddress) hre.props.coverPoolFactory = await hre.ethers.getContractAt('CoverPoolFactory', coverPoolFactoryAddress) hre.props.uniswapV3PoolMock = await hre.ethers.getContractAt('UniswapV3PoolMock', uniswapV3PoolMockAddress) + hre.props.poolRouter = await hre.ethers.getContractAt('PoolsharkRouter', poolsharkRouterAddress) return nonce } From 535a4d91682b41bd6c3382daaa125943eeb4b354 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 08:44:10 -0600 Subject: [PATCH 09/26] refactor uniswap v3 source to emit init event --- contracts/base/events/CoverPoolEvents.sol | 6 +++ contracts/interfaces/IPositionERC1155.sol | 2 + .../modules/sources/ITwapSource.sol | 5 +- .../sources/PoolsharkLimitSource.sol | 50 ++++++++++++------- .../libraries/sources/UniswapV3Source.sol | 46 ++++++++++------- contracts/utils/CoverPoolManager.sol | 23 +++++++-- 6 files changed, 89 insertions(+), 43 deletions(-) diff --git a/contracts/base/events/CoverPoolEvents.sol b/contracts/base/events/CoverPoolEvents.sol index 8e01ff49..c8c40f01 100644 --- a/contracts/base/events/CoverPoolEvents.sol +++ b/contracts/base/events/CoverPoolEvents.sol @@ -57,6 +57,12 @@ abstract contract CoverPoolEvents { uint160 pool1Price ); + event SampleCountInitialized ( + uint16 sampleCount, + uint16 sampleCountMax, + uint16 sampleCountRequired + ); + event Sync( uint160 pool0Price, uint160 pool1Price, diff --git a/contracts/interfaces/IPositionERC1155.sol b/contracts/interfaces/IPositionERC1155.sol index a75b002e..ab8da31b 100644 --- a/contracts/interfaces/IPositionERC1155.sol +++ b/contracts/interfaces/IPositionERC1155.sol @@ -74,4 +74,6 @@ interface IPositionERC1155 is IERC165, PoolsharkStructs { uint256[] calldata id, uint256[] calldata amount ) external; + + function poolImpl() external view returns(address); } \ No newline at end of file diff --git a/contracts/interfaces/modules/sources/ITwapSource.sol b/contracts/interfaces/modules/sources/ITwapSource.sol index 20a335ab..190bd982 100644 --- a/contracts/interfaces/modules/sources/ITwapSource.sol +++ b/contracts/interfaces/modules/sources/ITwapSource.sol @@ -33,5 +33,8 @@ interface ITwapSource { ); function factory() - external view returns (address); + external view returns (address); + + function poolType() + external view returns (bytes32); } diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 9bf4bc70..6e07bfb2 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -15,8 +15,13 @@ contract PoolsharkLimitSource is ITwapSource { bytes32 public immutable poolType; address public immutable limitPoolFactory; address public immutable limitPoolManager; - /// @dev - set for Arbitrum mainnet - uint32 public constant oneSecond = 1000; + uint16 public constant oneSecond = 1000; + + event SampleCountInitialized ( + uint16 sampleCount, + uint16 sampleCountMax, + uint16 sampleCountRequired + ); constructor( address _limitPoolFactory, @@ -36,21 +41,29 @@ contract PoolsharkLimitSource is ITwapSource { ) { // get the number of blocks covered by the twapLength - uint32 blockCount = uint32(constants.twapLength) * oneSecond / constants.sampleInterval; + uint16 blockCount = uint16(constants.twapLength) * oneSecond / constants.sampleInterval; ( - bool sampleCountEnough, - bool sampleLengthEnough - ) = _isPoolSampleCountEnough( - constants.inputPool, - blockCount - ); - if (!sampleLengthEnough) { + uint16 sampleCount, + uint16 sampleCountMax + ) = _getSampleCount(constants.inputPool); + + if (sampleCountMax < blockCount) { _increaseSampleCount(constants.inputPool, blockCount); + emit SampleCountInitialized ( + sampleCount, + sampleCountMax, + blockCount + ); return (0, 0); - } else if (!sampleCountEnough) { + } else if (sampleCount < blockCount) { return (0, 0); } - // ready to initialize if we get here + emit SampleCountInitialized ( + sampleCount, + sampleCountMax, + blockCount + ); + // ready to initialize initializable = 1; int24[4] memory averageTicks = _calculateAverageTicks(constants); // take the average of the 4 samples as a starting tick @@ -134,12 +147,11 @@ contract PoolsharkLimitSource is ITwapSource { } } - function _isPoolSampleCountEnough( - address pool, - uint32 blockCount + function _getSampleCount( + address pool ) internal view returns ( - bool, - bool + uint16, + uint16 ) { ( @@ -147,8 +159,8 @@ contract PoolsharkLimitSource is ITwapSource { ,,,,, ) = ILimitPool(pool).globalState(); return ( - poolState.samples.count >= blockCount, - poolState.samples.countMax >= blockCount + poolState.samples.count, + poolState.samples.countMax ); } diff --git a/contracts/libraries/sources/UniswapV3Source.sol b/contracts/libraries/sources/UniswapV3Source.sol index 4131a550..d8f426ec 100644 --- a/contracts/libraries/sources/UniswapV3Source.sol +++ b/contracts/libraries/sources/UniswapV3Source.sol @@ -12,7 +12,13 @@ contract UniswapV3Source is ITwapSource { error WaitUntilAboveMinTick(); address public immutable uniV3Factory; - uint32 public constant oneSecond = 1000; + uint16 public constant oneSecond = 1000; + + event SampleCountInitialized ( + uint16 sampleCount, + uint16 sampleCountMax, + uint16 sampleCountRequired + ); constructor( address _uniV3Factory @@ -28,20 +34,27 @@ contract UniswapV3Source is ITwapSource { ) { // get the number of blocks covered by the twapLength - uint32 blockCount = uint32(constants.twapLength) * oneSecond / constants.sampleInterval; + uint16 blockCount = constants.twapLength * oneSecond / constants.sampleInterval; ( - bool observationsCountEnough, - bool observationsLengthEnough - ) = _isPoolObservationsEnough( - constants.inputPool, - blockCount - ); - if (!observationsLengthEnough) { + uint16 cardinality, + uint16 cardinalityNext + ) = _getObservationsCardinality(constants.inputPool); + if (cardinalityNext < blockCount) { _increaseV3Observations(constants.inputPool, blockCount); + emit SampleCountInitialized( + cardinality, + cardinalityNext, + blockCount + ); return (0, 0); - } else if (!observationsCountEnough) { + } else if (cardinality < blockCount) { return (0, 0); } + emit SampleCountInitialized( + cardinality, + cardinalityNext, + blockCount + ); // ready to initialize if we get here initializable = 1; int24[4] memory averageTicks = _calculateAverageTicks(constants); @@ -126,17 +139,14 @@ contract UniswapV3Source is ITwapSource { } } - function _isPoolObservationsEnough( - address pool, - uint32 blockCount + function _getObservationsCardinality( + address pool ) internal view returns ( - bool, - bool + uint16 cardinality, + uint16 cardinalityNext ) { - - (, , , uint16 observationsCount, uint16 observationsLength, , ) = IUniswapV3Pool(pool).slot0(); - return (observationsCount >= blockCount, observationsLength >= blockCount); + (, , , cardinality, cardinalityNext, , ) = IUniswapV3Pool(pool).slot0(); } function _increaseV3Observations(address pool, uint32 blockCount) internal { diff --git a/contracts/utils/CoverPoolManager.sol b/contracts/utils/CoverPoolManager.sol index 9ad2e169..b479c07f 100644 --- a/contracts/utils/CoverPoolManager.sol +++ b/contracts/utils/CoverPoolManager.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.13; +import '../interfaces/IPositionERC1155.sol'; import '../interfaces/cover/ICoverPool.sol'; import '../interfaces/cover/ICoverPoolFactory.sol'; import '../interfaces/cover/ICoverPoolManager.sol'; @@ -16,7 +17,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { address public factory; uint16 public constant MAX_PROTOCOL_FEE = 1e4; /// @dev - max protocol fee of 1% uint16 public constant oneSecond = 1000; - // sourceName => sourceAddress + // poolType => impl address mapping(bytes32 => address) internal _poolTypes; mapping(bytes32 => address) internal _poolTokens; mapping(bytes32 => address) internal _twapSources; @@ -83,10 +84,22 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { address tokenImpl, address twapImpl ) external onlyOwner { - if (poolType[0] == bytes32("")) require (false, 'TwapSourceNameInvalid()'); - if (poolImpl == address(0) || twapImpl == address(0)) require (false, 'TwapSourceAddressZero()'); - if (_twapSources[poolType] != address(0)) require (false, 'ImplementationAlreadyExists()'); - if (_poolTypes[poolType] != address(0)) require (false, 'ImplementationAlreadyExists()'); + // valid poolType name + if(poolType == bytes32("")) + require (false, 'PoolTypeNameInvalid()'); + // invalid impl address + if(poolImpl == address(0) || twapImpl == address(0) || tokenImpl == address(0)) + require (false, 'TwapSourceAddressZero()'); + // pool type already exists + if(_twapSources[poolType] != address(0) || _poolTypes[poolType] != address(0)) + require (false, 'PoolTypeAlreadyExists()'); + // check for poolType mismatch + if(ITwapSource(twapImpl).poolType() != poolType) + require (false, 'PoolTypeTwapSourceMismatch()'); + // check for poolImpl mismatch + if(IPositionERC1155(tokenImpl).poolImpl() != poolImpl) + require (false, 'PoolImplTokenImplMismatch()'); + _poolTypes[poolType] = poolImpl; _poolTokens[poolType] = tokenImpl; _twapSources[poolType] = twapImpl; From 69d96077933a22ca3890a36c46d2255c657a9236 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 08:49:51 -0600 Subject: [PATCH 10/26] cleanup manager checks --- contracts/interfaces/IPositionERC1155.sol | 2 -- contracts/interfaces/modules/sources/ITwapSource.sol | 3 --- contracts/libraries/sources/PoolsharkLimitSource.sol | 1 + contracts/utils/CoverPoolManager.sol | 7 ------- 4 files changed, 1 insertion(+), 12 deletions(-) diff --git a/contracts/interfaces/IPositionERC1155.sol b/contracts/interfaces/IPositionERC1155.sol index ab8da31b..a75b002e 100644 --- a/contracts/interfaces/IPositionERC1155.sol +++ b/contracts/interfaces/IPositionERC1155.sol @@ -74,6 +74,4 @@ interface IPositionERC1155 is IERC165, PoolsharkStructs { uint256[] calldata id, uint256[] calldata amount ) external; - - function poolImpl() external view returns(address); } \ No newline at end of file diff --git a/contracts/interfaces/modules/sources/ITwapSource.sol b/contracts/interfaces/modules/sources/ITwapSource.sol index 190bd982..fe9a7738 100644 --- a/contracts/interfaces/modules/sources/ITwapSource.sol +++ b/contracts/interfaces/modules/sources/ITwapSource.sol @@ -34,7 +34,4 @@ interface ITwapSource { function factory() external view returns (address); - - function poolType() - external view returns (bytes32); } diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 6e07bfb2..33ee1fa8 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -12,6 +12,7 @@ contract PoolsharkLimitSource is ITwapSource { error WaitUntilBelowMaxTick(); error WaitUntilAboveMinTick(); + // poolType on limitPoolFactory bytes32 public immutable poolType; address public immutable limitPoolFactory; address public immutable limitPoolManager; diff --git a/contracts/utils/CoverPoolManager.sol b/contracts/utils/CoverPoolManager.sol index b479c07f..945f9919 100644 --- a/contracts/utils/CoverPoolManager.sol +++ b/contracts/utils/CoverPoolManager.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.13; -import '../interfaces/IPositionERC1155.sol'; import '../interfaces/cover/ICoverPool.sol'; import '../interfaces/cover/ICoverPoolFactory.sol'; import '../interfaces/cover/ICoverPoolManager.sol'; @@ -93,12 +92,6 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { // pool type already exists if(_twapSources[poolType] != address(0) || _poolTypes[poolType] != address(0)) require (false, 'PoolTypeAlreadyExists()'); - // check for poolType mismatch - if(ITwapSource(twapImpl).poolType() != poolType) - require (false, 'PoolTypeTwapSourceMismatch()'); - // check for poolImpl mismatch - if(IPositionERC1155(tokenImpl).poolImpl() != poolImpl) - require (false, 'PoolImplTokenImplMismatch()'); _poolTypes[poolType] = poolImpl; _poolTokens[poolType] = tokenImpl; From 93a439f6414ac83b3dfb19fa0f40192bd9b6af6f Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 08:50:40 -0600 Subject: [PATCH 11/26] cleanup manager checks --- test/contracts/coverpoolmanager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/coverpoolmanager.ts b/test/contracts/coverpoolmanager.ts index 412b9e4a..5f36cb98 100644 --- a/test/contracts/coverpoolmanager.ts +++ b/test/contracts/coverpoolmanager.ts @@ -254,7 +254,7 @@ describe('CoverPoolManager Tests', function () { hre.props.uniswapV3Source.address, hre.props.uniswapV3Source.address ) - ).to.be.revertedWith('TwapSourceNameInvalid()') + ).to.be.revertedWith('PoolTypeNameInvalid()') }) it('Should update sync and fill fees on pool', async function () { From 2a30ed8f6f068971a1c45452007ba394b0bdb0e4 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 09:33:06 -0600 Subject: [PATCH 12/26] deployment process text file; refactor sample length to count --- scripts/autogen/contract-deployments-keys.ts | 4 +- scripts/autogen/contract-deployments.json | 99 +++++++++----------- scripts/deployment-process.txt | 29 ++++++ 3 files changed, 75 insertions(+), 57 deletions(-) create mode 100644 scripts/deployment-process.txt diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index f2656e36..2ff7525a 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -3,6 +3,6 @@ import { ContractDeploymentsKey } from "../util/files/contractDeploymentsJson"; export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ { networkName: 'arb_goerli', - objectName: 'claimsLib' - } + objectName: 'positionsLib' + }, ]; \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index cc945a36..d7ca3cbe 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -50,100 +50,89 @@ }, "tickMapLib": { "contractName": "TickMap", - "contractAddress": "0x6027C624cAc4d2fB310D9391FAA613C00B17ABE7", + "contractAddress": "0xcE78D14Cd8bCD5eDCA5dA986CFBbF0122ff7729e", "constructorArguments": [], - "created": "2023-09-23T18:00:02.311Z" + "created": "2023-09-24T15:01:41.370Z" }, "epochMapLib": { "contractName": "EpochMap", - "contractAddress": "0xa316be0Fb53fA66af1dee65eb49f2Cd8C7881a70", + "contractAddress": "0x99eD522ac9506946a2997DCff2fcF516063A1463", "constructorArguments": [], - "created": "2023-09-23T18:00:03.833Z" + "created": "2023-09-24T15:01:42.831Z" }, "deltasLib": { "contractName": "Deltas", - "contractAddress": "0xef6d50A917847324FCa1D80A2B3df865028C546E", + "contractAddress": "0x3626A7a9A01655b8794778432368010F8376e604", "constructorArguments": [], - "created": "2023-09-23T18:00:05.929Z" + "created": "2023-09-24T15:01:44.599Z" }, "epochsLib": { "contractName": "Epochs", - "contractAddress": "0x6F82fEbaC7C548979C4e37AF071cc38de17554d1", + "contractAddress": "0x5a11e1a5632Db03EFE569427c55304476d7e5f1C", "constructorArguments": [], - "created": "2023-09-23T18:00:08.382Z" + "created": "2023-09-24T15:01:47.158Z" }, "ticksLib": { "contractName": "Ticks", - "contractAddress": "0x12d0bE0B198B1BB845aC3d704569bA6B04d058C7", + "contractAddress": "0xDC3De1601BcE3E3D19a5af0C0Ed96467389023D2", "constructorArguments": [], - "created": "2023-09-23T18:00:11.066Z" + "created": "2023-09-24T15:01:48.635Z" }, "claimsLib": { "contractName": "Claims", - "contractAddress": "0x4b479970384dB32fb35D8c9f28e30a05f0316b44", + "contractAddress": "0x860841514d314bcc54837cFd0292850fCf5c291e", "constructorArguments": [], - "created": "2023-09-23T18:00:12.937Z" + "created": "2023-09-24T15:01:50.517Z" }, "positionsLib": { "contractName": "Positions", - "contractAddress": "0xEFB3B6dEA25a05b4e3318B1598CAC205966C61D4", + "contractAddress": "0xF8881c880dfF2078442bA4cADb6E8b2FA082Ed4F", "constructorArguments": [], - "created": "2023-09-23T18:00:15.256Z" + "created": "2023-09-24T15:01:52.611Z" }, "coverPoolManager": { "contractName": "CoverPoolManager", - "contractAddress": "0x745a7664d6445972DDF7D8db007357BE536034EB", + "contractAddress": "0x904BDA322fDc790621653F4608E42c07C9bEe5f4", "constructorArguments": [], - "created": "2023-09-23T18:00:16.997Z" + "created": "2023-09-24T15:01:54.257Z" }, "mintCall": { "contractName": "MintCall", - "contractAddress": "0x82CaaCCE948567F484fde6c0d2C321a203c0f4a4", + "contractAddress": "0x372513AfD0f0FF0090462e83FdD56Ef58Fa8C6CF", "constructorArguments": [], - "created": "2023-09-23T18:00:22.820Z" + "created": "2023-09-24T15:02:00.032Z" }, "burnCall": { "contractName": "BurnCall", - "contractAddress": "0x67EBdb68D3311cC5430E2228952C07f8ca20A1B7", + "contractAddress": "0x46eA97E4DcCa69678eA4c2bFC50e484A01A40727", "constructorArguments": [], - "created": "2023-09-23T18:00:24.820Z" + "created": "2023-09-24T15:02:01.689Z" }, "swapCall": { "contractName": "SwapCall", - "contractAddress": "0xA8593D3ff2C6D01fFE08A9974e577c1Acef9fB60", + "contractAddress": "0xF28F7316e204F272D5Bdb8BB254a3E4fd4c6BF84", "constructorArguments": [], - "created": "2023-09-23T18:00:26.557Z" + "created": "2023-09-24T15:02:03.413Z" }, "quoteCall": { "contractName": "QuoteCall", - "contractAddress": "0xF65490e07646da6f0356Ea13598671fC6EdD701b", + "contractAddress": "0xa1855E8d3C70cd6EC84426E4eF6D771a7Ef60a51", "constructorArguments": [], - "created": "2023-09-23T18:00:28.186Z" + "created": "2023-09-24T15:02:05.279Z" }, "coverPoolFactory": { "contractName": "CoverPoolFactory", - "contractAddress": "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c", + "contractAddress": "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198", "constructorArguments": [ - "0x745a7664d6445972DDF7D8db007357BE536034EB" + "0x904BDA322fDc790621653F4608E42c07C9bEe5f4" ], - "created": "2023-09-23T18:00:18.854Z" + "created": "2023-09-24T15:01:56.097Z" }, "coverPool": { "contractName": "CoverPool", - "contractAddress": "0x7cBe93e093dcBE1904EE1643D8BD334798E3C795", + "contractAddress": "0x67497852a7b84Ede0140dD761B15B26042608d25", "constructorArguments": [], - "created": "2023-09-23T18:00:45.211Z" - }, - "coverPool2": { - "contractName": "CoverPool", - "contractAddress": [ - "0xb03aadc6D57428c2bd3a73a859e156C920F04949", - "0x06a75f4E98B8ACB0F8A85f1BAc2E5397D3050b23" - ], - "constructorArguments": [ - "0xF4516C95Ea10cD81000ac7cB12dFcD20bED02955" - ], - "created": "2023-09-14T16:33:36.962Z" + "created": "2023-09-24T15:02:22.012Z" }, "token20Batcher": { "contractName": "Token20Batcher", @@ -153,11 +142,11 @@ }, "coverPoolImpl": { "contractName": "CoverPool", - "contractAddress": "0x231a1b45cC694c28b9e271C75A219fD62396c0F9", + "contractAddress": "0x0b1DCF6e2Fb9962ED8C5712F4491d09964191180", "constructorArguments": [ - "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c" + "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198" ], - "created": "2023-09-23T18:00:30.047Z" + "created": "2023-09-24T15:02:07.252Z" }, "poolRouter": { "contractName": "PoolsharkRouter", @@ -170,35 +159,35 @@ }, "positionERC1155": { "contractName": "PositionERC1155", - "contractAddress": "0xFaa4E35794D0d957C5e0327EdD75C38A047896F9", + "contractAddress": "0x69F1Ed2E0d742e0DD963dd35269756Ebd4FDde72", "constructorArguments": [ - "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c" + "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198" ], - "created": "2023-09-23T18:00:31.764Z" + "created": "2023-09-24T15:02:09.295Z" }, "limitPoolManager": { "contractName": "LimitPoolManager", - "contractAddress": "0xcf90a2148b8fe67dab958b75cd358890c4b4a891", + "contractAddress": "0xecbec0e3f1d12644168f1a0bceaf4142ee97b91b", "constructorArguments": [], - "created": "2023-09-23T15:58:08.332Z" + "created": "2023-09-24T14:56:56.998Z" }, "limitPoolFactory": { "contractName": "LimitPoolFactory", - "contractAddress": "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", + "contractAddress": "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", "constructorArguments": [ - "0xCF90A2148b8FE67dAB958b75cD358890c4B4a891" + "0xEcBeC0E3F1d12644168F1a0bCeAf4142ee97B91B" ], - "created": "2023-09-23T15:58:09.898Z" + "created": "2023-09-24T14:56:59.060Z" }, "poolsharkLimitSource": { "contractName": "PoolsharkLimitSource", - "contractAddress": "0xFcD4C999a83d20DF863E5372e8bbCBE0f26a7374", + "contractAddress": "0x42118cABBD6AD52AdAFF4BbAccCdEeBAC5DA24dE", "constructorArguments": [ - "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", - "0xcf90a2148b8fe67dab958b75cd358890c4b4a891", + "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", + "0xecbec0e3f1d12644168f1a0bceaf4142ee97b91b", "0x434f4e5354414e542d50524f4455435400000000000000000000000000000000" ], - "created": "2023-09-23T18:00:00.255Z" + "created": "2023-09-24T15:01:39.791Z" } }, "scroll_alpha": { diff --git a/scripts/deployment-process.txt b/scripts/deployment-process.txt new file mode 100644 index 00000000..3853fd1f --- /dev/null +++ b/scripts/deployment-process.txt @@ -0,0 +1,29 @@ +1. set values for production + - volatility tiers + - pool types + +2. copy 'limitPoolFactory' and 'limitPoolManager' from limit deployment + +3. set booleans for first deployment + private deployRouter = false + private deployTokens = false + private deployPools = true + private deployContracts = true + private deployPoolsharkLimitSource = true + private deployUniswapV3Source = false + +4. run first deployment + +5. verify contracts + - remove coverPool from scripts\autogen\contract-deployments-keys.ts + - 2nd verification run for Ticks + - 3rd verification run for Positions + - manually verify proxies on Arbiscan + * coverPool + * coverPoolToken + +6. add contracts on Tenderly + +7. increase observations on Limit Pools + +8. mint first position(s) From 1b41d3562b11eb0bd183f625810a113a04e09456 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 10:03:39 -0600 Subject: [PATCH 13/26] deploy and mint cover position --- scripts/autogen/contract-deployments.json | 8 ++++---- scripts/deployment-process.txt | 8 ++++++++ tasks/deploy/utils/mintPosition.ts | 4 ++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index d7ca3cbe..38bcfba3 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -150,12 +150,12 @@ }, "poolRouter": { "contractName": "PoolsharkRouter", - "contractAddress": "0x4aefd9449f4d827c4e5343a719ed082e68a1e145", + "contractAddress": "0x991743beef1a9f890adc1c289dea0aa1d498d86a", "constructorArguments": [ - "0x8b9303c8ad68229440f2856d4e8a3b7507b08b20", - "0xe36E4b8A8CCCA7a6580f8A7d4F18A2DB27EEf35c" + "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", + "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198" ], - "created": "2023-09-23T23:15:36.059Z" + "created": "2023-09-24T16:01:11.026Z" }, "positionERC1155": { "contractName": "PositionERC1155", diff --git a/scripts/deployment-process.txt b/scripts/deployment-process.txt index 3853fd1f..329b77f0 100644 --- a/scripts/deployment-process.txt +++ b/scripts/deployment-process.txt @@ -3,6 +3,7 @@ - pool types 2. copy 'limitPoolFactory' and 'limitPoolManager' from limit deployment + - paste into scripts\autogen\contract-deployments.json 3. set booleans for first deployment private deployRouter = false @@ -22,6 +23,13 @@ * coverPool * coverPoolToken +6. deploy poolRouter on Limit + - deploy + - verify contract + +7. copy 'poolRouter' from limit deployment + - paste into scripts\autogen\contract-deployments.json + 6. add contracts on Tenderly 7. increase observations on Limit Pools diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index 78006184..31d10a89 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -43,8 +43,8 @@ export class MintPosition { await validateMint({ signer: hre.props.alice, recipient: hre.props.alice.address, - lower: '71000', //1211 - upper: '70000', //1096 + lower: '70000', //1096 + upper: '71000', //1211 amount: token1Amount, zeroForOne: true, balanceInDecrease: token1Amount, From 88653b4f266db60d32f0405aae8f5291fada64fa Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 10:32:48 -0600 Subject: [PATCH 14/26] save position addreses --- tasks/deploy/utils/mintPosition.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index 31d10a89..346fd2d2 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -38,11 +38,13 @@ export class MintPosition { await getLatestTick(true) // await getPrice(true) - // 0x34e800D1456d87A5F62B774AD98cea54a3A40048 + // 0x65f5B282E024e3d6CaAD112e848dEc3317dB0902 // 0x1DcF623EDf118E4B21b4C5Dc263bb735E170F9B8 + // 0x9dA9409D17DeA285B078af06206941C049F692Dc + // 0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E await validateMint({ signer: hre.props.alice, - recipient: hre.props.alice.address, + recipient: '0x9dA9409D17DeA285B078af06206941C049F692Dc', lower: '70000', //1096 upper: '71000', //1211 amount: token1Amount, From 5b0102e0f45fb053289f1b37b538b1d04c5be63a Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 24 Sep 2023 12:14:31 -0600 Subject: [PATCH 15/26] track sample updates from twap source --- contracts/base/events/CoverPoolEvents.sol | 6 ---- contracts/base/events/TwapSourceEvents.sol | 11 +++++++ .../sources/PoolsharkLimitSource.sol | 11 +++---- subgraph/abis/TwapSource.json | 33 +++++++++++++++++++ subgraph/schema.graphql | 12 ++++++- subgraph/src/mappings/coverpoolmanager.ts | 28 +++++++++++----- subgraph/src/mappings/twapsource.ts | 24 ++++++++++++++ subgraph/src/mappings/utils/loads.ts | 22 ++++++++++++- subgraph/subgraph.yaml | 21 ++++++++++++ 9 files changed, 144 insertions(+), 24 deletions(-) create mode 100644 contracts/base/events/TwapSourceEvents.sol create mode 100644 subgraph/abis/TwapSource.json create mode 100644 subgraph/src/mappings/twapsource.ts diff --git a/contracts/base/events/CoverPoolEvents.sol b/contracts/base/events/CoverPoolEvents.sol index c8c40f01..8e01ff49 100644 --- a/contracts/base/events/CoverPoolEvents.sol +++ b/contracts/base/events/CoverPoolEvents.sol @@ -57,12 +57,6 @@ abstract contract CoverPoolEvents { uint160 pool1Price ); - event SampleCountInitialized ( - uint16 sampleCount, - uint16 sampleCountMax, - uint16 sampleCountRequired - ); - event Sync( uint160 pool0Price, uint160 pool1Price, diff --git a/contracts/base/events/TwapSourceEvents.sol b/contracts/base/events/TwapSourceEvents.sol new file mode 100644 index 00000000..11eab712 --- /dev/null +++ b/contracts/base/events/TwapSourceEvents.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity 0.8.13; + +abstract contract TwapSourceEvents { + event SampleCountInitialized ( + address indexed coverPool, + uint16 sampleCount, + uint16 sampleCountMax, + uint16 sampleCountRequired + ); +} diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 33ee1fa8..34a242c9 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -4,11 +4,12 @@ pragma solidity 0.8.13; import '../../interfaces/external/poolshark/limit/ILimitPoolManager.sol'; import '../../interfaces/external/poolshark/limit/ILimitPoolFactory.sol'; import '../../interfaces/external/poolshark/limit/ILimitPool.sol'; +import '../../base/events/TwapSourceEvents.sol'; import '../../interfaces/structs/CoverPoolStructs.sol'; import '../../interfaces/modules/sources/ITwapSource.sol'; import '../math/ConstantProduct.sol'; -contract PoolsharkLimitSource is ITwapSource { +contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { error WaitUntilBelowMaxTick(); error WaitUntilAboveMinTick(); @@ -18,12 +19,6 @@ contract PoolsharkLimitSource is ITwapSource { address public immutable limitPoolManager; uint16 public constant oneSecond = 1000; - event SampleCountInitialized ( - uint16 sampleCount, - uint16 sampleCountMax, - uint16 sampleCountRequired - ); - constructor( address _limitPoolFactory, address _limitPoolManager, @@ -51,6 +46,7 @@ contract PoolsharkLimitSource is ITwapSource { if (sampleCountMax < blockCount) { _increaseSampleCount(constants.inputPool, blockCount); emit SampleCountInitialized ( + msg.sender, sampleCount, sampleCountMax, blockCount @@ -60,6 +56,7 @@ contract PoolsharkLimitSource is ITwapSource { return (0, 0); } emit SampleCountInitialized ( + msg.sender, sampleCount, sampleCountMax, blockCount diff --git a/subgraph/abis/TwapSource.json b/subgraph/abis/TwapSource.json new file mode 100644 index 00000000..663c544f --- /dev/null +++ b/subgraph/abis/TwapSource.json @@ -0,0 +1,33 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "coverPool", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "sampleCount", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "sampleCountMax", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "sampleCountRequired", + "type": "uint16" + } + ], + "name": "SampleCountInitialized", + "type": "event" + } +] \ No newline at end of file diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index a0a8b019..283fe4f4 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -1,6 +1,7 @@ type CoverPoolFactory @entity { # poolAddress id: ID! + manager: CoverPoolManager! poolCount: BigInt! txnCount: BigInt! volumeUsdTotal: BigDecimal! @@ -20,7 +21,7 @@ type CoverPoolManager @entity { id: ID! owner: Bytes! feeTo: Bytes! - # factory: CoverPoolFactory! + factory: CoverPoolFactory! volatilityTiers: [VolatilityTier!]! } @@ -38,6 +39,10 @@ type VolatilityTier @entity { createdAtBlockNumber: BigInt! } +type TwapSource @entity { + id: ID! +} + type Token @entity { # token address id: ID! @@ -76,6 +81,11 @@ type CoverPool @entity { volatilityTier: VolatilityTier! genesisTime: BigInt! + # sample status + sampleCount: BigInt! + sampleCountMax: BigInt! + sampleCountRequired: BigInt! + liquidity: BigInt! liquidityGlobal: BigInt! latestTick: BigInt! diff --git a/subgraph/src/mappings/coverpoolmanager.ts b/subgraph/src/mappings/coverpoolmanager.ts index daf7c996..df5e4fcb 100644 --- a/subgraph/src/mappings/coverpoolmanager.ts +++ b/subgraph/src/mappings/coverpoolmanager.ts @@ -1,8 +1,19 @@ -import { safeLoadManager, safeLoadCoverPoolFactory, safeLoadVolatilityTier } from './utils/loads' +import { safeLoadManager, safeLoadCoverPoolFactory, safeLoadVolatilityTier, safeLoadTwapSource } from './utils/loads' import { BigInt, log } from '@graphprotocol/graph-ts' import { FACTORY_ADDRESS } from '../constants/constants' -import { FactoryChanged, FeeToTransfer, OwnerTransfer, ProtocolFeesCollected } from '../../generated/CoverPoolManager/CoverPoolManager' +import { FactoryChanged, FeeToTransfer, OwnerTransfer, PoolTypeEnabled, ProtocolFeesCollected } from '../../generated/CoverPoolManager/CoverPoolManager' import { VolatilityTierEnabled } from '../../generated/CoverPoolManager/CoverPoolManager' +import { TwapSourceTemplate } from '../../generated/templates' + +export function handlePoolTypeEnabled(event: PoolTypeEnabled): void { + let twapSourceAddressParam = event.params.sourceAddress + let loadTwapSource = safeLoadTwapSource(twapSourceAddressParam.toHex()) + if (!loadTwapSource.exists) { + TwapSourceTemplate.create(twapSourceAddressParam) + } + let twapSource = loadTwapSource.entity + twapSource.save() +} export function handleVolatilityTierEnabled(event: VolatilityTierEnabled): void { let feeTierParam = BigInt.fromI32(event.params.feeTier) @@ -38,11 +49,11 @@ export function handleFactoryChanged(event: FactoryChanged): void { let manager = loadManager.entity let factory = loadRangePoolFactory.entity - // manager.factory = factory.id - // factory.owner = manager.id + manager.factory = factory.id + factory.manager = manager.id - // manager.save() - // factory.save() + manager.save() + factory.save() } export function handleProtocolFeesCollected(event: ProtocolFeesCollected): void { @@ -74,12 +85,11 @@ export function handleOwnerTransfer(event: OwnerTransfer): void { if(!loadManager.exists) { manager.feeTo = newOwnerParam - // manager.factory = FACTORY_ADDRESS + manager.factory = FACTORY_ADDRESS.toLowerCase() } if(!loadFactory.exists) { - //factory.owner = manager.id + factory.manager = manager.id } - manager.owner = newOwnerParam manager.save() diff --git a/subgraph/src/mappings/twapsource.ts b/subgraph/src/mappings/twapsource.ts new file mode 100644 index 00000000..bed80964 --- /dev/null +++ b/subgraph/src/mappings/twapsource.ts @@ -0,0 +1,24 @@ +import { SampleCountInitialized } from "../../generated/templates/TwapSourceTemplate/TwapSource" +import { safeLoadCoverPool } from "./utils/loads" +import { BigInt } from '@graphprotocol/graph-ts' + +export function handleSampleCountInitialized(event: SampleCountInitialized): void { + let coverPoolParam = event.params.coverPool.toHex() + let sampleCountParam = event.params.sampleCount + let sampleCountMaxParam = event.params.sampleCountMax + let sampleCountRequiredParam = event.params.sampleCountRequired + + let loadPool = safeLoadCoverPool(coverPoolParam) + + if (!loadPool.exists) { + //error + } + + let pool = loadPool.entity + + pool.sampleCount = BigInt.fromI32(sampleCountParam) + pool.sampleCountMax = BigInt.fromI32(sampleCountMaxParam) + pool.sampleCountRequired = BigInt.fromI32(sampleCountRequiredParam) + + pool.save() +} \ No newline at end of file diff --git a/subgraph/src/mappings/utils/loads.ts b/subgraph/src/mappings/utils/loads.ts index 0548bb6e..b16e7f36 100644 --- a/subgraph/src/mappings/utils/loads.ts +++ b/subgraph/src/mappings/utils/loads.ts @@ -9,6 +9,7 @@ import { } from './helpers' import { bigDecimalExponated, safeDiv } from './math' import { getEthPriceInUSD } from './price' +import { TwapSource } from '../../../generated/schema' class LoadBasePriceRet { entity: BasePrice @@ -31,7 +32,6 @@ export function safeLoadBasePrice(name: string): LoadBasePriceRet { exists: exists, } } - class LoadTokenRet { entity: Token exists: boolean @@ -142,6 +142,26 @@ export function safeLoadManager(address: string): LoadManagerRet { } } +class LoadTwapSourceRet { + entity: TwapSource + exists: boolean +} +export function safeLoadTwapSource(address: string): LoadTwapSourceRet { + let exists = true + + let twapSourceEntity = TwapSource.load(address) + + if (!twapSourceEntity) { + twapSourceEntity = new TwapSource(address) + exists = false + } + + return { + entity: twapSourceEntity, + exists: exists, + } +} + class LoadVolatilityTierRet { entity: VolatilityTier exists: boolean diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 8b3bba15..c20590ac 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -52,6 +52,8 @@ dataSources: - name: CoverPoolManager file: ./abis/CoverPoolManager.json eventHandlers: + - event: PoolTypeEnabled(bytes32,address,address,address) + handler: handlePoolTypeEnabled - event: VolatilityTierEnabled(bytes32,uint16,int16,uint16,uint128,uint16,uint16,uint16,uint16,int16,bool) handler: handleVolatilityTierEnabled - event: FeeToTransfer(indexed address,indexed address) @@ -108,6 +110,25 @@ templates: handler: handleStashDeltasAccumulated - event: StashDeltasCleared(int24,bool) handler: handleStashDeltasCleared + # TwapSource events + - kind: ethereum/contract + name: TwapSourceTemplate + network: arbitrum-goerli + source: + abi: TwapSource + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + file: ./src/mappings/twapsource.ts + entities: + - TwapSource + abis: + - name: TwapSource + file: ./abis/TwapSource.json + eventHandlers: + - event: SampleCountInitialized(indexed address,uint16,uint16,uint16) + handler: handleSampleCountInitialized # ERC-1155 events - kind: ethereum/contract name: PositionERC1155Template From de30244d1994264ee0663132dbc5bb6530559237 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Mon, 25 Sep 2023 06:26:04 -0600 Subject: [PATCH 16/26] updated subgraph --- contracts/CoverPoolFactory.sol | 1 + .../sources/PoolsharkLimitSource.sol | 30 +++---- .../libraries/sources/UniswapV3Source.sol | 11 +-- scripts/autogen/contract-deployments-keys.ts | 2 +- scripts/autogen/contract-deployments.json | 80 +++++++++---------- scripts/deployment-process.txt | 26 +++--- scripts/util/deployAssist.ts | 2 +- subgraph/abis/PoolsharkRouter.json | 27 +++++++ subgraph/package.json | 2 +- subgraph/schema.graphql | 7 ++ subgraph/src/constants/constants.ts | 4 +- subgraph/src/mappings/coverpoolrouter.ts | 18 +++++ subgraph/src/mappings/twapsource.ts | 1 + subgraph/src/mappings/utils/loads.ts | 21 ++++- subgraph/subgraph.yaml | 28 ++++++- tasks/deploy/utils/mintPosition.ts | 10 +-- 16 files changed, 180 insertions(+), 90 deletions(-) create mode 100644 subgraph/abis/PoolsharkRouter.json create mode 100644 subgraph/src/mappings/coverpoolrouter.ts diff --git a/contracts/CoverPoolFactory.sol b/contracts/CoverPoolFactory.sol index fe846113..9b6a03ea 100644 --- a/contracts/CoverPoolFactory.sol +++ b/contracts/CoverPoolFactory.sol @@ -120,6 +120,7 @@ contract CoverPoolFactory is data: encodeCover(constants) }); + // intialize twap source ICoverPool(pool).initialize(); poolToken = constants.poolToken; diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 34a242c9..92da0555 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -43,24 +43,19 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { uint16 sampleCountMax ) = _getSampleCount(constants.inputPool); - if (sampleCountMax < blockCount) { - _increaseSampleCount(constants.inputPool, blockCount); - emit SampleCountInitialized ( - msg.sender, - sampleCount, - sampleCountMax, - blockCount - ); - return (0, 0); - } else if (sampleCount < blockCount) { - return (0, 0); - } emit SampleCountInitialized ( msg.sender, sampleCount, sampleCountMax, blockCount ); + + if (sampleCountMax < blockCount) { + _increaseSampleCount(constants.inputPool, blockCount); + return (0, 0); + } else if (sampleCount < blockCount) { + return (0, 0); + } // ready to initialize initializable = 1; int24[4] memory averageTicks = _calculateAverageTicks(constants); @@ -148,18 +143,17 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { function _getSampleCount( address pool ) internal view returns ( - uint16, - uint16 + uint16 sampleCount, + uint16 sampleCountMax ) { ( ILimitPool.RangePoolState memory poolState, ,,,,, ) = ILimitPool(pool).globalState(); - return ( - poolState.samples.count, - poolState.samples.countMax - ); + + sampleCount = poolState.samples.count; + sampleCountMax = poolState.samples.countMax; } function _increaseSampleCount(address pool, uint32 blockCount) internal { diff --git a/contracts/libraries/sources/UniswapV3Source.sol b/contracts/libraries/sources/UniswapV3Source.sol index d8f426ec..13d94367 100644 --- a/contracts/libraries/sources/UniswapV3Source.sol +++ b/contracts/libraries/sources/UniswapV3Source.sol @@ -3,23 +3,18 @@ pragma solidity 0.8.13; import '../../interfaces/external/uniswap/v3/IUniswapV3Factory.sol'; import '../../interfaces/external/uniswap/v3/IUniswapV3Pool.sol'; +import '../../base/events/TwapSourceEvents.sol'; import '../../interfaces/structs/CoverPoolStructs.sol'; import '../../interfaces/modules/sources/ITwapSource.sol'; import '../math/ConstantProduct.sol'; -contract UniswapV3Source is ITwapSource { +contract UniswapV3Source is ITwapSource, TwapSourceEvents { error WaitUntilBelowMaxTick(); error WaitUntilAboveMinTick(); address public immutable uniV3Factory; uint16 public constant oneSecond = 1000; - event SampleCountInitialized ( - uint16 sampleCount, - uint16 sampleCountMax, - uint16 sampleCountRequired - ); - constructor( address _uniV3Factory ) { @@ -42,6 +37,7 @@ contract UniswapV3Source is ITwapSource { if (cardinalityNext < blockCount) { _increaseV3Observations(constants.inputPool, blockCount); emit SampleCountInitialized( + msg.sender, cardinality, cardinalityNext, blockCount @@ -51,6 +47,7 @@ contract UniswapV3Source is ITwapSource { return (0, 0); } emit SampleCountInitialized( + msg.sender, cardinality, cardinalityNext, blockCount diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index 2ff7525a..82b6ea69 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -3,6 +3,6 @@ import { ContractDeploymentsKey } from "../util/files/contractDeploymentsJson"; export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ { networkName: 'arb_goerli', - objectName: 'positionsLib' + objectName: 'claimsLib' }, ]; \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index 38bcfba3..6156d365 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -50,89 +50,89 @@ }, "tickMapLib": { "contractName": "TickMap", - "contractAddress": "0xcE78D14Cd8bCD5eDCA5dA986CFBbF0122ff7729e", + "contractAddress": "0xf4bc5e94e732df58958a592993e8c25a6d0002a9", "constructorArguments": [], - "created": "2023-09-24T15:01:41.370Z" + "created": "2023-09-25T01:59:31.395Z" }, "epochMapLib": { "contractName": "EpochMap", - "contractAddress": "0x99eD522ac9506946a2997DCff2fcF516063A1463", + "contractAddress": "0xd10d0570aab6618bbda6ac54ea9f2ddfcd68ebcc", "constructorArguments": [], - "created": "2023-09-24T15:01:42.831Z" + "created": "2023-09-25T01:59:32.821Z" }, "deltasLib": { "contractName": "Deltas", - "contractAddress": "0x3626A7a9A01655b8794778432368010F8376e604", + "contractAddress": "0x4d7889cc4d60642c8b7c91c8cb4efab9c04842d5", "constructorArguments": [], - "created": "2023-09-24T15:01:44.599Z" + "created": "2023-09-25T01:59:34.545Z" }, "epochsLib": { "contractName": "Epochs", - "contractAddress": "0x5a11e1a5632Db03EFE569427c55304476d7e5f1C", + "contractAddress": "0xdad0d046b6166fea7f6e3613c8b6653b00872f75", "constructorArguments": [], - "created": "2023-09-24T15:01:47.158Z" + "created": "2023-09-25T01:59:37.359Z" }, "ticksLib": { "contractName": "Ticks", - "contractAddress": "0xDC3De1601BcE3E3D19a5af0C0Ed96467389023D2", + "contractAddress": "0xdb0ad73c36c337f47e22737eae4cc6f936ddcb3f", "constructorArguments": [], - "created": "2023-09-24T15:01:48.635Z" + "created": "2023-09-25T01:59:38.867Z" }, "claimsLib": { "contractName": "Claims", - "contractAddress": "0x860841514d314bcc54837cFd0292850fCf5c291e", + "contractAddress": "0x2c55dfa58eb98f892a8954f712baffbf5a8bc208", "constructorArguments": [], - "created": "2023-09-24T15:01:50.517Z" + "created": "2023-09-25T01:59:40.606Z" }, "positionsLib": { "contractName": "Positions", - "contractAddress": "0xF8881c880dfF2078442bA4cADb6E8b2FA082Ed4F", + "contractAddress": "0x42ff3191dd5ffabc297c86974a49c0db8ae985b7", "constructorArguments": [], - "created": "2023-09-24T15:01:52.611Z" + "created": "2023-09-25T01:59:42.738Z" }, "coverPoolManager": { "contractName": "CoverPoolManager", - "contractAddress": "0x904BDA322fDc790621653F4608E42c07C9bEe5f4", + "contractAddress": "0xf76088f4c5ad2a138f68870449f019e0e93e1510", "constructorArguments": [], - "created": "2023-09-24T15:01:54.257Z" + "created": "2023-09-25T01:59:44.380Z" }, "mintCall": { "contractName": "MintCall", - "contractAddress": "0x372513AfD0f0FF0090462e83FdD56Ef58Fa8C6CF", + "contractAddress": "0x97534089c388cb5c477ec49030f659ca9e7517e0", "constructorArguments": [], - "created": "2023-09-24T15:02:00.032Z" + "created": "2023-09-25T01:59:50.324Z" }, "burnCall": { "contractName": "BurnCall", - "contractAddress": "0x46eA97E4DcCa69678eA4c2bFC50e484A01A40727", + "contractAddress": "0x7625ae1f998f6cff8d7ad9e31806c9dfbb9d6617", "constructorArguments": [], - "created": "2023-09-24T15:02:01.689Z" + "created": "2023-09-25T01:59:52.205Z" }, "swapCall": { "contractName": "SwapCall", - "contractAddress": "0xF28F7316e204F272D5Bdb8BB254a3E4fd4c6BF84", + "contractAddress": "0x6e11352c5cfd4b2ed214aed9ccbcdcc8a3d42365", "constructorArguments": [], - "created": "2023-09-24T15:02:03.413Z" + "created": "2023-09-25T01:59:53.856Z" }, "quoteCall": { "contractName": "QuoteCall", - "contractAddress": "0xa1855E8d3C70cd6EC84426E4eF6D771a7Ef60a51", + "contractAddress": "0x18666efa258ac3305e53b6cac779617a71941613", "constructorArguments": [], - "created": "2023-09-24T15:02:05.279Z" + "created": "2023-09-25T01:59:55.987Z" }, "coverPoolFactory": { "contractName": "CoverPoolFactory", - "contractAddress": "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198", + "contractAddress": "0x4b0288914ea8ab81da888e74f93da0062212ddcc", "constructorArguments": [ - "0x904BDA322fDc790621653F4608E42c07C9bEe5f4" + "0xF76088F4C5Ad2a138f68870449f019e0E93E1510" ], - "created": "2023-09-24T15:01:56.097Z" + "created": "2023-09-25T01:59:46.159Z" }, "coverPool": { "contractName": "CoverPool", - "contractAddress": "0x67497852a7b84Ede0140dD761B15B26042608d25", + "contractAddress": "0x8d23572c0326b9242da4428ddfdffcc1975c705f", "constructorArguments": [], - "created": "2023-09-24T15:02:22.012Z" + "created": "2023-09-25T02:00:12.324Z" }, "token20Batcher": { "contractName": "Token20Batcher", @@ -142,28 +142,28 @@ }, "coverPoolImpl": { "contractName": "CoverPool", - "contractAddress": "0x0b1DCF6e2Fb9962ED8C5712F4491d09964191180", + "contractAddress": "0xebae6ac9aeaa46b321b7541e044ec10f4225c57c", "constructorArguments": [ - "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198" + "0x4B0288914Ea8aB81DA888e74F93DA0062212ddcC" ], - "created": "2023-09-24T15:02:07.252Z" + "created": "2023-09-25T01:59:57.763Z" }, "poolRouter": { "contractName": "PoolsharkRouter", - "contractAddress": "0x991743beef1a9f890adc1c289dea0aa1d498d86a", + "contractAddress": "0xdb11885eac2a8944438322349925ac0de3159392", "constructorArguments": [ "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", - "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198" + "0x4b0288914ea8ab81da888e74f93da0062212ddcc" ], - "created": "2023-09-24T16:01:11.026Z" + "created": "2023-09-25T03:03:32.166Z" }, "positionERC1155": { "contractName": "PositionERC1155", - "contractAddress": "0x69F1Ed2E0d742e0DD963dd35269756Ebd4FDde72", + "contractAddress": "0x2e05790dd1cd5689d2d4a9c9690121efb5ddeae6", "constructorArguments": [ - "0xc9Dc6657e02349445c0FF45EBaCd3B2534d7b198" + "0x4B0288914Ea8aB81DA888e74F93DA0062212ddcC" ], - "created": "2023-09-24T15:02:09.295Z" + "created": "2023-09-25T01:59:59.551Z" }, "limitPoolManager": { "contractName": "LimitPoolManager", @@ -181,13 +181,13 @@ }, "poolsharkLimitSource": { "contractName": "PoolsharkLimitSource", - "contractAddress": "0x42118cABBD6AD52AdAFF4BbAccCdEeBAC5DA24dE", + "contractAddress": "0xf0afe01f61148fe94f69823cd9b7a664ec4c4835", "constructorArguments": [ "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", "0xecbec0e3f1d12644168f1a0bceaf4142ee97b91b", "0x434f4e5354414e542d50524f4455435400000000000000000000000000000000" ], - "created": "2023-09-24T15:01:39.791Z" + "created": "2023-09-25T01:59:29.677Z" } }, "scroll_alpha": { diff --git a/scripts/deployment-process.txt b/scripts/deployment-process.txt index 329b77f0..f7d42568 100644 --- a/scripts/deployment-process.txt +++ b/scripts/deployment-process.txt @@ -1,11 +1,13 @@ -1. set values for production +1. yarn clean; yarn compile + +2. set values for production - volatility tiers - pool types -2. copy 'limitPoolFactory' and 'limitPoolManager' from limit deployment +3. copy 'limitPoolFactory' and 'limitPoolManager' from limit deployment - paste into scripts\autogen\contract-deployments.json -3. set booleans for first deployment +4. set booleans for first deployment private deployRouter = false private deployTokens = false private deployPools = true @@ -13,9 +15,9 @@ private deployPoolsharkLimitSource = true private deployUniswapV3Source = false -4. run first deployment +5. run first deployment -5. verify contracts +6. verify contracts - remove coverPool from scripts\autogen\contract-deployments-keys.ts - 2nd verification run for Ticks - 3rd verification run for Positions @@ -23,15 +25,19 @@ * coverPool * coverPoolToken -6. deploy poolRouter on Limit +7. deploy poolRouter on Limit - deploy - verify contract -7. copy 'poolRouter' from limit deployment +8. copy 'poolRouter' from limit deployment - paste into scripts\autogen\contract-deployments.json -6. add contracts on Tenderly +9. add contracts on Tenderly + +10. increase observations on Limit Pools -7. increase observations on Limit Pools +11. mint first position(s) -8. mint first position(s) +12. Subgraph setup +- subgraph.yaml => factory, manager, router addresses, startBlock +- constants.ts => FACTORY_ADDRESS down to => STABLE_IS_TOKEN_0 diff --git a/scripts/util/deployAssist.ts b/scripts/util/deployAssist.ts index 30f96927..647549dd 100644 --- a/scripts/util/deployAssist.ts +++ b/scripts/util/deployAssist.ts @@ -119,7 +119,7 @@ export class DeployAssist { network, contractName, objectName, - contract.address, + contract.address.toLocaleLowerCase(), constructorArguments ) await this.contractDeploymentsKeys.addContractDeploymentKey({ diff --git a/subgraph/abis/PoolsharkRouter.json b/subgraph/abis/PoolsharkRouter.json new file mode 100644 index 00000000..e1b4e1e5 --- /dev/null +++ b/subgraph/abis/PoolsharkRouter.json @@ -0,0 +1,27 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "router", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "limitPoolFactory", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "coverPoolFactory", + "type": "address" + } + ], + "name": "RouterDeployed", + "type": "event" + } + ] \ No newline at end of file diff --git a/subgraph/package.json b/subgraph/package.json index 4c69c471..960438b6 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -18,7 +18,7 @@ "build": "graph build", "deploy": "graph deploy --product hosted-service alphak3y/poolshark-cover", "deploy-sats": "graph deploy cover-arbitrumGoerli --version-label v0.0.4 --node https://app.satsuma.xyz/api/subgraphs/deploy --deploy-key 7NoUUXPcOGfBX --ipfs https://ipfs.satsuma.xyz", - "deploy-chainstack": "graph deploy --version-label v0.1.2 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", + "deploy-chainstack": "graph deploy --version-label v0.2.1 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", "deploy-op-test": "graph deploy --product hosted-service alphak3y/poolshark-cover-op-goerli", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020", "test": "graph codegen; graph test -v 0.2.0" diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 283fe4f4..73345dca 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -17,6 +17,13 @@ type BasePrice @entity { USD: BigDecimal! } +type PoolRouter @entity { + id: ID! + + limitPoolFactory: Bytes! + coverPoolFactory: Bytes! +} + type CoverPoolManager @entity { id: ID! owner: Bytes! diff --git a/subgraph/src/constants/constants.ts b/subgraph/src/constants/constants.ts index 21e6bc9e..a518713d 100644 --- a/subgraph/src/constants/constants.ts +++ b/subgraph/src/constants/constants.ts @@ -1,7 +1,7 @@ /* eslint-disable */ import { BigInt, BigDecimal, Address } from '@graphprotocol/graph-ts' import { CoverPoolFactory as FactoryContract } from '../../generated/CoverPoolFactory/CoverPoolFactory' -export let FACTORY_ADDRESS = '0x479c2df7ed63ea26146ac2092c55047c3928a5a6' +export let FACTORY_ADDRESS = '0x4b0288914ea8ab81da888e74f93da0062212ddcc' export let WETH_ADDRESS = '0x0bfaaafa6e8fb009cd4e2bd3693f2eec2d18b053' // tokens where USD value is safe to use for globals @@ -16,7 +16,7 @@ export let STABLE_COINS: string[] = [ ] // used for safe eth pricing -export const STABLE_POOL_ADDRESS = '0xa91eb93a6be6e49dbf7af22f7c04c8b219f0cc93' +export const STABLE_POOL_ADDRESS = '0x8d23572c0326b9242da4428ddfdffcc1975c705f' // determines which token to use for eth<-> rate, true means stable is token0 in pool above export const STABLE_IS_TOKEN_0 = false diff --git a/subgraph/src/mappings/coverpoolrouter.ts b/subgraph/src/mappings/coverpoolrouter.ts new file mode 100644 index 00000000..3b0d0076 --- /dev/null +++ b/subgraph/src/mappings/coverpoolrouter.ts @@ -0,0 +1,18 @@ +import { RouterDeployed } from "../../generated/PoolsharkRouter/PoolsharkRouter"; +import { safeLoadPoolRouter } from "./utils/loads"; + +export function handleRouterDeployed(event: RouterDeployed): void { + let routerParam = event.params.router + let limitPoolFactoryParam = event.params.limitPoolFactory + let coverPoolFactoryParam = event.params.coverPoolFactory + + let loadPoolRouter = safeLoadPoolRouter(routerParam.toHex()) + + let poolRouter = loadPoolRouter.entity + + if (!loadPoolRouter.exists) { + poolRouter.limitPoolFactory = limitPoolFactoryParam + poolRouter.coverPoolFactory = coverPoolFactoryParam + } + poolRouter.save() +} \ No newline at end of file diff --git a/subgraph/src/mappings/twapsource.ts b/subgraph/src/mappings/twapsource.ts index bed80964..7547b0b2 100644 --- a/subgraph/src/mappings/twapsource.ts +++ b/subgraph/src/mappings/twapsource.ts @@ -1,3 +1,4 @@ + import { SampleCountInitialized } from "../../generated/templates/TwapSourceTemplate/TwapSource" import { safeLoadCoverPool } from "./utils/loads" import { BigInt } from '@graphprotocol/graph-ts' diff --git a/subgraph/src/mappings/utils/loads.ts b/subgraph/src/mappings/utils/loads.ts index b16e7f36..fe77fe30 100644 --- a/subgraph/src/mappings/utils/loads.ts +++ b/subgraph/src/mappings/utils/loads.ts @@ -1,5 +1,5 @@ import { Address, BigDecimal, BigInt, Bytes, log } from '@graphprotocol/graph-ts' -import { BasePrice, BurnLog, CoverPool, CoverPoolFactory, CoverPoolManager, MintLog, Position, Tick, TickDeltas, Token, VolatilityTier } from '../../../generated/schema' +import { BasePrice, BurnLog, CoverPool, CoverPoolFactory, CoverPoolManager, MintLog, PoolRouter, Position, Tick, TickDeltas, Token, VolatilityTier } from '../../../generated/schema' import { ONE_BD, ONE_BI } from '../../constants/constants' import { fetchTokenSymbol, @@ -32,6 +32,25 @@ export function safeLoadBasePrice(name: string): LoadBasePriceRet { exists: exists, } } + +class LoadPoolRouterRet { + entity: PoolRouter + exists: boolean +} +export function safeLoadPoolRouter(routerAddress: string): LoadPoolRouterRet { + let exists = true + let poolRouterEntity = PoolRouter.load(routerAddress) + + if (!poolRouterEntity) { + poolRouterEntity = new PoolRouter(routerAddress) + exists = false + } + + return { + entity: poolRouterEntity, + exists: exists, + } +} class LoadTokenRet { entity: Token exists: boolean diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index c20590ac..5d1687f1 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -8,9 +8,9 @@ dataSources: name: CoverPoolFactory network: arbitrum-goerli source: - address: '0x479C2Df7eD63ea26146Ac2092C55047C3928A5A6' + address: '0x4b0288914ea8ab81da888e74f93da0062212ddcc' abi: CoverPoolFactory - startBlock: 41521100 + startBlock: 43471400 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -37,9 +37,9 @@ dataSources: name: CoverPoolManager network: arbitrum-goerli source: - address: '0x74db8d63FD2e6FAeA61a7a53bFB5Ab319d17f220' + address: '0xf76088f4c5ad2a138f68870449f019e0e93e1510' abi: CoverPoolManager - startBlock: 41521100 + startBlock: 43471400 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -64,6 +64,26 @@ dataSources: handler: handleProtocolFeesCollected - event: FactoryChanged(indexed address,indexed address) handler: handleFactoryChanged + - kind: ethereum/contract + name: PoolsharkRouter + network: arbitrum-goerli + source: + address: '0xdb11885eac2a8944438322349925ac0de3159392' + abi: PoolsharkRouter + startBlock: 43471400 + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + file: ./src/mappings/coverpoolrouter.ts + entities: + - PoolsharkRouter + abis: + - name: PoolsharkRouter + file: ./abis/PoolsharkRouter.json + eventHandlers: + - event: RouterDeployed(address,address,address) + handler: handleRouterDeployed templates: # Cover Pool Events - kind: ethereum/contract diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index 346fd2d2..064a1a3e 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -38,13 +38,13 @@ export class MintPosition { await getLatestTick(true) // await getPrice(true) - // 0x65f5B282E024e3d6CaAD112e848dEc3317dB0902 - // 0x1DcF623EDf118E4B21b4C5Dc263bb735E170F9B8 - // 0x9dA9409D17DeA285B078af06206941C049F692Dc - // 0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E + // 0x65f5B282E024e3d6CaAD112e848dEc3317dB0902 + // 0x1DcF623EDf118E4B21b4C5Dc263bb735E170F9B8 + // 0x9dA9409D17DeA285B078af06206941C049F692Dc + // 0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E await validateMint({ signer: hre.props.alice, - recipient: '0x9dA9409D17DeA285B078af06206941C049F692Dc', + recipient: '0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E', lower: '70000', //1096 upper: '71000', //1211 amount: token1Amount, From d3c9754376a97ac966d94c7c7fa80fd14a2b2b1b Mon Sep 17 00:00:00 2001 From: alphak3y Date: Wed, 27 Sep 2023 12:53:18 -0600 Subject: [PATCH 17/26] utf-8 string for poolType --- scripts/autogen/contract-deployments.json | 2 +- subgraph/package.json | 2 +- subgraph/src/mappings/coverpoolfactory.ts | 2 +- subgraph/src/mappings/coverpoolmanager.ts | 2 +- tasks/deploy/utils/mintPosition.ts | 4 ++-- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index 6156d365..ac64186d 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -142,7 +142,7 @@ }, "coverPoolImpl": { "contractName": "CoverPool", - "contractAddress": "0xebae6ac9aeaa46b321b7541e044ec10f4225c57c", + "contractAddress": "0x021d33056507e041b8e799530af4088123d334a1", "constructorArguments": [ "0x4B0288914Ea8aB81DA888e74F93DA0062212ddcC" ], diff --git a/subgraph/package.json b/subgraph/package.json index 960438b6..cf84d85f 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -18,7 +18,7 @@ "build": "graph build", "deploy": "graph deploy --product hosted-service alphak3y/poolshark-cover", "deploy-sats": "graph deploy cover-arbitrumGoerli --version-label v0.0.4 --node https://app.satsuma.xyz/api/subgraphs/deploy --deploy-key 7NoUUXPcOGfBX --ipfs https://ipfs.satsuma.xyz", - "deploy-chainstack": "graph deploy --version-label v0.2.1 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", + "deploy-chainstack": "graph deploy --node https://api.graph-eu.p2pify.com/f71ac9a325709eaaf5cea415ae068f76/deploy --ipfs https://api.graph-eu.p2pify.com/f71ac9a325709eaaf5cea415ae068f76/ipfs testing-cover", "deploy-op-test": "graph deploy --product hosted-service alphak3y/poolshark-cover-op-goerli", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020", "test": "graph codegen; graph test -v 0.2.0" diff --git a/subgraph/src/mappings/coverpoolfactory.ts b/subgraph/src/mappings/coverpoolfactory.ts index eafa3101..879bc0f6 100644 --- a/subgraph/src/mappings/coverpoolfactory.ts +++ b/subgraph/src/mappings/coverpoolfactory.ts @@ -15,7 +15,7 @@ export function handlePoolCreated(event: PoolCreated): void { let feeTierParam = BigInt.fromI32(event.params.fee) let tickSpreadParam = BigInt.fromI32(event.params.tickSpread) let twapLengthParam = BigInt.fromI32(event.params.twapLength) - let poolTypeParam = event.params.poolType.toHex() + let poolTypeParam = event.params.poolType.toString() let poolAddressParam = event.params.pool.toHex() // load from store diff --git a/subgraph/src/mappings/coverpoolmanager.ts b/subgraph/src/mappings/coverpoolmanager.ts index df5e4fcb..b6d2af59 100644 --- a/subgraph/src/mappings/coverpoolmanager.ts +++ b/subgraph/src/mappings/coverpoolmanager.ts @@ -20,7 +20,7 @@ export function handleVolatilityTierEnabled(event: VolatilityTierEnabled): void let tickSpreadParam = BigInt.fromI32(event.params.tickSpread) let twapLengthParam = BigInt.fromI32(event.params.twapLength) let auctionLengthParam = BigInt.fromI32(event.params.auctionLength) - let poolTypeParam = event.params.poolType.toHex() + let poolTypeParam = event.params.poolType.toString() let loadManager = safeLoadManager(event.address.toHex()) let loadVolatilityTier = safeLoadVolatilityTier(poolTypeParam, feeTierParam, tickSpreadParam, twapLengthParam) diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index 064a1a3e..0587599b 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -45,8 +45,8 @@ export class MintPosition { await validateMint({ signer: hre.props.alice, recipient: '0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E', - lower: '70000', //1096 - upper: '71000', //1211 + lower: '73400', //1096 + upper: '73600', //1211 amount: token1Amount, zeroForOne: true, balanceInDecrease: token1Amount, From fb28297de5d78680b7a7b2dbdb15fb1406b848b2 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Wed, 27 Sep 2023 12:55:36 -0600 Subject: [PATCH 18/26] deploy subgraph command --- subgraph/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/subgraph/package.json b/subgraph/package.json index cf84d85f..3dc02f32 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -18,7 +18,7 @@ "build": "graph build", "deploy": "graph deploy --product hosted-service alphak3y/poolshark-cover", "deploy-sats": "graph deploy cover-arbitrumGoerli --version-label v0.0.4 --node https://app.satsuma.xyz/api/subgraphs/deploy --deploy-key 7NoUUXPcOGfBX --ipfs https://ipfs.satsuma.xyz", - "deploy-chainstack": "graph deploy --node https://api.graph-eu.p2pify.com/f71ac9a325709eaaf5cea415ae068f76/deploy --ipfs https://api.graph-eu.p2pify.com/f71ac9a325709eaaf5cea415ae068f76/ipfs testing-cover", + "deploy-chainstack": "graph deploy --version-label v0.2.2 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", "deploy-op-test": "graph deploy --product hosted-service alphak3y/poolshark-cover-op-goerli", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020", "test": "graph codegen; graph test -v 0.2.0" From 56e680536e6f13388a124ccee59bedb3046b63e7 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Thu, 28 Sep 2023 17:18:48 -0600 Subject: [PATCH 19/26] epochLast0 and epochLast1 --- subgraph/schema.graphql | 3 ++- subgraph/src/mappings/coverpool.ts | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 73345dca..2431e635 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -192,7 +192,8 @@ type Tick @entity { index: BigInt! price0: BigDecimal! price1: BigDecimal! - epochLast: BigInt! + epochLast0: BigInt! + epochLast1: BigInt! } type TickDeltas @entity { diff --git a/subgraph/src/mappings/coverpool.ts b/subgraph/src/mappings/coverpool.ts index 7991f2fe..53badeac 100644 --- a/subgraph/src/mappings/coverpool.ts +++ b/subgraph/src/mappings/coverpool.ts @@ -649,7 +649,8 @@ export function handleFinalDeltasAccumulated(event: FinalDeltasAccumulated): voi let accumTickDeltas = loadAccumTickDeltas.entity pool.liquidityGlobal = pool.liquidityGlobal.minus(accumTickDeltas.liquidityMinus) - accumTick.epochLast = auctionEpochParam + if (isPool0Param) accumTick.epochLast0 = auctionEpochParam + else accumTick.epochLast1 = auctionEpochParam accumTickDeltas.liquidityMinus = BIGINT_ZERO accumTickDeltas.amountInDelta = accumTickDeltas.amountInDelta.plus(amountInDeltaParam) accumTickDeltas.amountOutDelta = accumTickDeltas.amountOutDelta.plus(amountOutDeltaParam) @@ -679,7 +680,8 @@ export function handleStashDeltasAccumulated(event: StashDeltasAccumulated): voi let stashTick = loadStashTick.entity let stashTickDeltas = loadStashTickDeltas.entity - stashTick.epochLast = auctionEpochParam + if (isPool0Param) stashTick.epochLast0 = auctionEpochParam + else stashTick.epochLast1 = auctionEpochParam stashTickDeltas.amountInDelta = stashTickDeltas.amountInDelta.plus(amountInDeltaParam) stashTickDeltas.amountOutDelta = stashTickDeltas.amountOutDelta.plus(amountOutDeltaParam) stashTickDeltas.amountInDeltaMaxStashed = stashTickDeltas.amountInDeltaMaxStashed.plus(amountInDeltaMaxStashedParam) From 2c0021bc75628d4d47083546737460201affed82 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sat, 30 Sep 2023 11:45:04 -0600 Subject: [PATCH 20/26] update multiquote call --- contracts/utils/PoolsharkRouter.sol | 138 ++++++++++++++++------------ 1 file changed, 79 insertions(+), 59 deletions(-) diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index a0bc823b..c9467b36 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -18,8 +18,8 @@ contract PoolsharkRouter is PoolsharkStructs, ILimitPoolMintCallback, ILimitPoolSwapCallback, - ICoverPoolMintCallback, - ICoverPoolSwapCallback + ICoverPoolSwapCallback, + ICoverPoolMintCallback { using SafeCast for uint256; using SafeCast for int256; @@ -99,8 +99,8 @@ contract PoolsharkRouter is } } - /// @inheritdoc ICoverPoolMintCallback - function coverPoolMintCallback( + /// @inheritdoc ICoverPoolSwapCallback + function coverPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data @@ -111,8 +111,8 @@ contract PoolsharkRouter is canonicalCoverPoolsOnly(constants); // decode original sender - MintCallbackData memory _data = abi.decode(data, (MintCallbackData)); - + SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); + // transfer from swap caller if (amount0Delta < 0) { SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); @@ -121,8 +121,8 @@ contract PoolsharkRouter is } } - /// @inheritdoc ICoverPoolSwapCallback - function coverPoolSwapCallback( + /// @inheritdoc ICoverPoolMintCallback + function coverPoolMintCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data @@ -133,8 +133,8 @@ contract PoolsharkRouter is canonicalCoverPoolsOnly(constants); // decode original sender - SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); - + MintCallbackData memory _data = abi.decode(data, (MintCallbackData)); + // transfer from swap caller if (amount0Delta < 0) { SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); @@ -200,8 +200,7 @@ contract PoolsharkRouter is if (i > 0) { if (params[i].zeroForOne != params[0].zeroForOne) require (false, 'ZeroForOneParamMismatch()'); if (params[i].exactIn != params[0].exactIn) require(false, 'ExactInParamMismatch()'); - if (params[i].amount != params[0].amount) require(false, 'AmountParamMisMatch()'); - /// @dev - priceLimit values are allowed to be different + /// @dev - amount and priceLimit values are allowed to be different } unchecked { ++i; @@ -267,20 +266,6 @@ contract PoolsharkRouter is } } - function multiCall( - address[] memory pools, - SwapParams[] memory params - ) external { - if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); - for (uint i = 0; i < pools.length;) { - params[i].callbackData = abi.encode(SwapCallbackData({sender: msg.sender})); - ICoverPool(pools[i]).swap(params[i]); - unchecked { - ++i; - } - } - } - function createLimitPoolAndMint( ILimitPoolFactory.LimitPoolParams memory params, MintRangeParams[] memory mintRangeParams, @@ -356,53 +341,88 @@ contract PoolsharkRouter is } } + struct SortQuoteResultsLocals { + QuoteResults[] sortedResults; + QuoteResults[] prunedResults; + bool[] sortedFlags; + uint256 emptyResults; + int256 sortAmount; + uint256 sortIndex; + uint256 prunedIndex; + } + function sortQuoteResults( QuoteParams[] memory params, QuoteResults[] memory results ) internal pure returns ( - QuoteResults[] memory sortedResults + QuoteResults[] memory ) { - sortedResults = new QuoteResults[](results.length); - for (uint sorted = 0; sorted < results.length;) { - // if exactIn, sort by most output - // if exactOut, sort by least input - int256 sortAmount = params[0].exactIn ? int256(0) : type(int256).max; - uint256 sortIndex = type(uint256).max; - for (uint index = 0; index < (results.length - sorted);) { - // check if result already sorted - if (results[index].priceAfter > 0) { - if (params[0].exactIn) { - if (results[index].amountOut >= sortAmount) { - sortIndex = index; - sortAmount = results[index].amountOut; - } - } else { - if (results[index].amountIn <= sortAmount) { - sortIndex = index; - sortAmount = results[index].amountIn; - } + SortQuoteResultsLocals memory locals; + locals.sortedResults = new QuoteResults[](results.length); + locals.sortedFlags = new bool[](results.length); + locals.emptyResults = 0; + for (uint sorted = 0; sorted < results.length;) { + // if exactIn, sort by most output + // if exactOut, sort by least input + locals.sortAmount = params[0].exactIn ? int256(0) : type(int256).max; + locals.sortIndex = type(uint256).max; + for (uint index = 0; index < results.length;) { + // check if result already sorted + if (!locals.sortedFlags[index]) { + if (params[0].exactIn) { + if (results[index].amountOut >= locals.sortAmount) { + locals.sortIndex = index; + locals.sortAmount = results[index].amountOut; + } + } else { + if (results[index].amountIn <= locals.sortAmount) { + locals.sortIndex = index; + locals.sortAmount = results[index].amountIn; } } - if (sortIndex != type(uint256).max) { - // add the sorted result - sortedResults[sorted].pool = results[sortIndex].pool; - sortedResults[sorted].amountIn = results[sortIndex].amountIn; - sortedResults[sorted].amountOut = results[sortIndex].amountOut; - sortedResults[sorted].priceAfter = results[sortIndex].priceAfter; - - // indicate this result was already sorted - results[sortIndex].priceAfter = 0; - } - // continue finding nth element + } + // continue finding nth element + unchecked { + ++index; + } + } + if (locals.sortIndex != type(uint256).max) { + // add the sorted result + locals.sortedResults[sorted].pool = results[locals.sortIndex].pool; + locals.sortedResults[sorted].amountIn = results[locals.sortIndex].amountIn; + locals.sortedResults[sorted].amountOut = results[locals.sortIndex].amountOut; + locals.sortedResults[sorted].priceAfter = results[locals.sortIndex].priceAfter; + + // indicate this result was already sorted + locals.sortedFlags[locals.sortIndex] = true; + } else { + ++locals.emptyResults; + } + // find next sorted element + unchecked { + ++sorted; + } + } + // if any results were empty, prune them + if (locals.emptyResults > 0) { + locals.prunedResults = new QuoteResults[](results.length - locals.emptyResults); + locals.prunedIndex = 0; + for (uint sorted = 0; sorted < results.length;) { + // empty results are omitted + if (locals.sortedResults[sorted].pool != address(0)) { + locals.prunedResults[locals.prunedIndex] = locals.sortedResults[sorted]; unchecked { - ++index; + ++locals.prunedIndex; } } - // find next sorted element unchecked { ++sorted; } } + } else { + locals.prunedResults = locals.sortedResults; + } + return locals.prunedResults; } function canonicalLimitPoolsOnly( From 055c0025945862624182309aac8137a07a23b267 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sat, 30 Sep 2023 12:06:03 -0600 Subject: [PATCH 21/26] avoid stack too deep for encodeCover --- contracts/CoverPool.sol | 8 +++-- contracts/CoverPoolFactory.sol | 8 +++-- contracts/utils/PoolsharkRouter.sol | 45 ++++++++++++++++------------- contracts/utils/PositionERC1155.sol | 8 +++-- 4 files changed, 40 insertions(+), 29 deletions(-) diff --git a/contracts/CoverPool.sol b/contracts/CoverPool.sol index e6da11d3..98bb4dff 100644 --- a/contracts/CoverPool.sol +++ b/contracts/CoverPool.sol @@ -320,7 +320,9 @@ contract CoverPool is constants.poolToken, constants.inputPool, constants.bounds.min, - constants.bounds.max, + constants.bounds.max + ); + bytes memory value2 = abi.encodePacked( constants.minAmountPerAuction, constants.genesisTime, constants.minPositionWidth, @@ -328,13 +330,13 @@ contract CoverPool is constants.twapLength, constants.auctionLength ); - bytes memory value2 = abi.encodePacked( + bytes memory value3 = abi.encodePacked( constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced ); - return abi.encodePacked(value1, value2); + return abi.encodePacked(value1, value2, value3); } function _onlyOwner() private view { diff --git a/contracts/CoverPoolFactory.sol b/contracts/CoverPoolFactory.sol index 9b6a03ea..8995f72f 100644 --- a/contracts/CoverPoolFactory.sol +++ b/contracts/CoverPoolFactory.sol @@ -189,7 +189,9 @@ contract CoverPoolFactory is constants.poolToken, constants.inputPool, constants.bounds.min, - constants.bounds.max, + constants.bounds.max + ); + bytes memory value2 = abi.encodePacked( constants.minAmountPerAuction, constants.genesisTime, constants.minPositionWidth, @@ -197,12 +199,12 @@ contract CoverPoolFactory is constants.twapLength, constants.auctionLength ); - bytes memory value2 = abi.encodePacked( + bytes memory value3 = abi.encodePacked( constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced ); - return abi.encodePacked(value1, value2); + return abi.encodePacked(value1, value2, value3); } } diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index c9467b36..584d295a 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -54,8 +54,8 @@ contract PoolsharkRouter is ); } - /// @inheritdoc ILimitPoolMintCallback - function limitPoolMintCallback( + /// @inheritdoc ILimitPoolSwapCallback + function limitPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data @@ -66,7 +66,7 @@ contract PoolsharkRouter is canonicalLimitPoolsOnly(constants); // decode original sender - MintCallbackData memory _data = abi.decode(data, (MintCallbackData)); + SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); // transfer from swap caller if (amount0Delta < 0) { @@ -77,16 +77,16 @@ contract PoolsharkRouter is } } - /// @inheritdoc ILimitPoolSwapCallback - function limitPoolSwapCallback( + /// @inheritdoc ICoverPoolSwapCallback + function coverPoolSwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { - PoolsharkStructs.LimitImmutables memory constants = ILimitPool(msg.sender).immutables(); + PoolsharkStructs.CoverImmutables memory constants = ICoverPool(msg.sender).immutables(); - // validate sender is a canonical limit pool - canonicalLimitPoolsOnly(constants); + // validate sender is a canonical cover pool + canonicalCoverPoolsOnly(constants); // decode original sender SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); @@ -94,29 +94,31 @@ contract PoolsharkRouter is // transfer from swap caller if (amount0Delta < 0) { SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); - } else { + } + if (amount1Delta < 0) { SafeTransfers.transferInto(constants.token1, _data.sender, uint256(-amount1Delta)); } } - /// @inheritdoc ICoverPoolSwapCallback - function coverPoolSwapCallback( + /// @inheritdoc ILimitPoolMintCallback + function limitPoolMintCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external override { - PoolsharkStructs.CoverImmutables memory constants = ICoverPool(msg.sender).immutables(); + PoolsharkStructs.LimitImmutables memory constants = ILimitPool(msg.sender).immutables(); - // validate sender is a canonical cover pool - canonicalCoverPoolsOnly(constants); + // validate sender is a canonical limit pool + canonicalLimitPoolsOnly(constants); // decode original sender - SwapCallbackData memory _data = abi.decode(data, (SwapCallbackData)); + MintCallbackData memory _data = abi.decode(data, (MintCallbackData)); // transfer from swap caller if (amount0Delta < 0) { SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); - } else { + } + if (amount1Delta < 0) { SafeTransfers.transferInto(constants.token1, _data.sender, uint256(-amount1Delta)); } } @@ -138,7 +140,8 @@ contract PoolsharkRouter is // transfer from swap caller if (amount0Delta < 0) { SafeTransfers.transferInto(constants.token0, _data.sender, uint256(-amount0Delta)); - } else { + } + if (amount1Delta < 0) { SafeTransfers.transferInto(constants.token1, _data.sender, uint256(-amount1Delta)); } } @@ -500,7 +503,9 @@ contract PoolsharkRouter is constants.poolToken, constants.inputPool, constants.bounds.min, - constants.bounds.max, + constants.bounds.max + ); + bytes memory value2 = abi.encodePacked( constants.minAmountPerAuction, constants.genesisTime, constants.minPositionWidth, @@ -508,12 +513,12 @@ contract PoolsharkRouter is constants.twapLength, constants.auctionLength ); - bytes memory value2 = abi.encodePacked( + bytes memory value3 = abi.encodePacked( constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced ); - return abi.encodePacked(value1, value2); + return abi.encodePacked(value1, value2, value3); } } \ No newline at end of file diff --git a/contracts/utils/PositionERC1155.sol b/contracts/utils/PositionERC1155.sol index 2afedbee..990aa07c 100644 --- a/contracts/utils/PositionERC1155.sol +++ b/contracts/utils/PositionERC1155.sol @@ -323,7 +323,9 @@ contract PositionERC1155 is constants.poolToken, constants.inputPool, constants.bounds.min, - constants.bounds.max, + constants.bounds.max + ); + bytes memory value2 = abi.encodePacked( constants.minAmountPerAuction, constants.genesisTime, constants.minPositionWidth, @@ -331,12 +333,12 @@ contract PositionERC1155 is constants.twapLength, constants.auctionLength ); - bytes memory value2 = abi.encodePacked( + bytes memory value3 = abi.encodePacked( constants.sampleInterval, constants.token0Decimals, constants.token1Decimals, constants.minAmountLowerPriced ); - return abi.encodePacked(value1, value2); + return abi.encodePacked(value1, value2, value3); } } \ No newline at end of file From 44c685d917d218a7ac83a9a211e425b3f057f7db Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 1 Oct 2023 07:25:07 -0600 Subject: [PATCH 22/26] add syncLatestTick contract call --- contracts/CoverPool.sol | 7 +++++++ contracts/interfaces/cover/ICoverPool.sol | 5 +++++ contracts/libraries/Epochs.sol | 9 +++++++++ contracts/utils/PoolsharkRouter.sol | 14 ++++++++++++++ subgraph/abis/LimitSamples.json | 21 +++++++++++++++++++++ subgraph/schema.graphql | 20 +++++++++++++++++++- subgraph/src/mappings/coverpoolfactory.ts | 13 +++++++++---- subgraph/src/mappings/limit/samples.ts | 23 +++++++++++++++++++++++ subgraph/src/mappings/utils/loads.ts | 22 ++++++++++++++++++++-- subgraph/subgraph.yaml | 19 +++++++++++++++++++ 10 files changed, 146 insertions(+), 7 deletions(-) create mode 100644 subgraph/abis/LimitSamples.json create mode 100644 subgraph/src/mappings/limit/samples.ts diff --git a/contracts/CoverPool.sol b/contracts/CoverPool.sol index 98bb4dff..f22d795a 100644 --- a/contracts/CoverPool.sol +++ b/contracts/CoverPool.sol @@ -281,6 +281,13 @@ contract CoverPool is ); } + function syncLatestTick() external view returns (int24) { + return Epochs.syncLatestTick( + globalState, + immutables() + ); + } + function priceBounds( int16 tickSpacing ) external pure returns (uint160, uint160) { diff --git a/contracts/interfaces/cover/ICoverPool.sol b/contracts/interfaces/cover/ICoverPool.sol index bd03524d..d8711c37 100644 --- a/contracts/interfaces/cover/ICoverPool.sol +++ b/contracts/interfaces/cover/ICoverPool.sol @@ -116,6 +116,11 @@ interface ICoverPool is CoverPoolStructs { CoverImmutables memory constants ); + function syncLatestTick( + ) external view returns ( + int24 newLatestTick + ); + function priceBounds( int16 tickSpacing ) external pure returns ( diff --git a/contracts/libraries/Epochs.sol b/contracts/libraries/Epochs.sol index 247af5db..8606beab 100644 --- a/contracts/libraries/Epochs.sol +++ b/contracts/libraries/Epochs.sol @@ -144,6 +144,15 @@ library Epochs { return (state, cache.syncFees, pool0, pool1); } + function syncLatestTick( + CoverPoolStructs.GlobalState memory state, + PoolsharkStructs.CoverImmutables memory constants + ) external view returns ( + int24 newLatestTick + ) { + (newLatestTick,) = _syncTick(state, constants); + } + function syncLatest( mapping(int24 => CoverPoolStructs.Tick) storage ticks, CoverPoolStructs.TickMap storage tickMap, diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index 584d295a..6b010a93 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -521,4 +521,18 @@ contract PoolsharkRouter is ); return abi.encodePacked(value1, value2, value3); } + + function multiCall( + address[] memory pools, + SwapParams[] memory params + ) external { + if (pools.length != params.length) require(false, 'InputArrayLengthsMismatch()'); + for (uint i = 0; i < pools.length;) { + params[i].callbackData = abi.encode(SwapCallbackData({sender: msg.sender})); + ICoverPool(pools[i]).swap(params[i]); + unchecked { + ++i; + } + } + } } \ No newline at end of file diff --git a/subgraph/abis/LimitSamples.json b/subgraph/abis/LimitSamples.json new file mode 100644 index 00000000..308c7b67 --- /dev/null +++ b/subgraph/abis/LimitSamples.json @@ -0,0 +1,21 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "int56", + "name": "tickSecondsAccum", + "type": "int56" + }, + { + "indexed": false, + "internalType": "uint160", + "name": "secondsPerLiquidityAccum", + "type": "uint160" + } + ], + "name": "SampleRecorded", + "type": "event" + } +] \ No newline at end of file diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 2431e635..db4bcfc2 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -93,9 +93,10 @@ type CoverPool @entity { sampleCountMax: BigInt! sampleCountRequired: BigInt! + newLatestTick: BigInt! + latestTick: BigInt! liquidity: BigInt! liquidityGlobal: BigInt! - latestTick: BigInt! auctionEpoch: BigInt! auctionStart: BigInt! @@ -130,6 +131,23 @@ type CoverPool @entity { updatedAtBlockNumber: BigInt! } +type LimitPool @entity { + # poolAddress + id: ID! + + coverPool: CoverPool! + + samples: [Sample!]! + samplesRecorded: BigInt! +} + +type Sample @entity { + # poolAddress + sample number + id: ID! + tickSecondsAccum: BigInt! + blockTimestamp: BigInt! +} + type Position @entity { # poolAddress + owner + lower + upper id: ID! diff --git a/subgraph/src/mappings/coverpoolfactory.ts b/subgraph/src/mappings/coverpoolfactory.ts index 879bc0f6..f035708f 100644 --- a/subgraph/src/mappings/coverpoolfactory.ts +++ b/subgraph/src/mappings/coverpoolfactory.ts @@ -1,6 +1,6 @@ import { log } from '@graphprotocol/graph-ts' import { PoolCreated } from '../../generated/CoverPoolFactory/CoverPoolFactory' -import { CoverPoolTemplate } from '../../generated/templates' +import { CoverPoolTemplate, LimitSamplesTemplate } from '../../generated/templates' import { fetchTokenSymbol, fetchTokenName, @@ -16,11 +16,12 @@ export function handlePoolCreated(event: PoolCreated): void { let tickSpreadParam = BigInt.fromI32(event.params.tickSpread) let twapLengthParam = BigInt.fromI32(event.params.twapLength) let poolTypeParam = event.params.poolType.toString() - let poolAddressParam = event.params.pool.toHex() + let poolAddressParam = event.params.pool + let inputPoolParam = event.params.inputPool // load from store let loadVolatilityTier = safeLoadVolatilityTier(poolTypeParam, feeTierParam, tickSpreadParam, twapLengthParam) - let loadCoverPool = safeLoadCoverPool(poolAddressParam) + let loadCoverPool = safeLoadCoverPool(poolAddressParam.toHex()) let loadCoverPoolFactory = safeLoadCoverPoolFactory(FACTORY_ADDRESS.toLowerCase()) let loadToken0 = safeLoadToken(event.params.token0.toHexString()) let loadToken1 = safeLoadToken(event.params.token1.toHexString()) @@ -75,5 +76,9 @@ export function handlePoolCreated(event: PoolCreated): void { token1.save() // create the tracked contract based on the template - CoverPoolTemplate.create(event.params.pool) + CoverPoolTemplate.create(poolAddressParam) + + if (poolTypeParam == 'PSHARK-CPROD') { + LimitSamplesTemplate.create(inputPoolParam) + } } diff --git a/subgraph/src/mappings/limit/samples.ts b/subgraph/src/mappings/limit/samples.ts new file mode 100644 index 00000000..96675e04 --- /dev/null +++ b/subgraph/src/mappings/limit/samples.ts @@ -0,0 +1,23 @@ +import { SampleRecorded } from "../../../generated/templates/LimitSamplesTemplate/LimitSamples"; +import { ONE_BI } from "../../constants/constants"; +import { safeLoadCoverPool, safeLoadLimitPool } from "../utils/loads"; + +export function handleSampleRecorded(event: SampleRecorded): void { + // load params + let poolAddress = event.address + + // load entities + let loadLimitPool = safeLoadLimitPool(poolAddress.toHex()) + let limitPool = loadLimitPool.entity + + let loadCoverPool = safeLoadCoverPool(limitPool.coverPool) + let coverPool = loadCoverPool.entity + + // increment sample count + limitPool.samplesRecorded = limitPool.samplesRecorded.plus(ONE_BI) + if (limitPool.samplesRecorded.le(coverPool.sampleCountMax)) + coverPool.sampleCount = limitPool.samplesRecorded + + limitPool.save() + coverPool.save() +} \ No newline at end of file diff --git a/subgraph/src/mappings/utils/loads.ts b/subgraph/src/mappings/utils/loads.ts index fe77fe30..2d34783c 100644 --- a/subgraph/src/mappings/utils/loads.ts +++ b/subgraph/src/mappings/utils/loads.ts @@ -1,5 +1,5 @@ import { Address, BigDecimal, BigInt, Bytes, log } from '@graphprotocol/graph-ts' -import { BasePrice, BurnLog, CoverPool, CoverPoolFactory, CoverPoolManager, MintLog, PoolRouter, Position, Tick, TickDeltas, Token, VolatilityTier } from '../../../generated/schema' +import { BasePrice, BurnLog, CoverPool, CoverPoolFactory, CoverPoolManager, LimitPool, MintLog, PoolRouter, Position, Tick, TickDeltas, Token, VolatilityTier } from '../../../generated/schema' import { ONE_BD, ONE_BI } from '../../constants/constants' import { fetchTokenSymbol, @@ -227,7 +227,6 @@ export function safeLoadTick(address: string, index: BigInt): LoadTickRet { tickEntity = new Tick(tickId) tickEntity.pool = address tickEntity.index = index - tickEntity.epochLast = ONE_BI // 1.0001^tick is token1/token0. tickEntity.price0 = bigDecimalExponated(BigDecimal.fromString('1.0001'), BigInt.fromI32(tickEntity.index.toI32())) tickEntity.price1 = safeDiv(ONE_BD, tickEntity.price0) @@ -287,6 +286,25 @@ export function safeLoadCoverPoolFactory(factoryAddress: string): LoadCoverPoolF } } +class LoadLimitPoolRet { + entity: LimitPool + exists: boolean +} +export function safeLoadLimitPool(poolAddress: string): LoadLimitPoolRet { + let exists = true + let limitPoolEntity = LimitPool.load(poolAddress) + + if (!limitPoolEntity) { + limitPoolEntity = new LimitPool(poolAddress) + exists = false + } + + return { + entity: limitPoolEntity, + exists: exists, + } +} + class LoadCoverPoolRet { entity: CoverPool exists: boolean diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 5d1687f1..9c337ce9 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -149,6 +149,25 @@ templates: eventHandlers: - event: SampleCountInitialized(indexed address,uint16,uint16,uint16) handler: handleSampleCountInitialized + # InputPool events + - kind: ethereum/contract + name: LimitSamplesTemplate + network: arbitrum-goerli + source: + abi: LimitSamples + mapping: + kind: ethereum/events + apiVersion: 0.0.6 + language: wasm/assemblyscript + file: ./src/mappings/limit/samples.ts + entities: + - CoverPool + abis: + - name: LimitSamples + file: ./abis/LimitSamples.json + eventHandlers: + - event: SampleRecorded(int56,uint160) + handler: handleSampleRecorded # ERC-1155 events - kind: ethereum/contract name: PositionERC1155Template From 44d9806a16762c8a5d0bfb12ca74ab5f28d347fb Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 1 Oct 2023 18:17:39 -0600 Subject: [PATCH 23/26] latest subgraph build --- scripts/autogen/contract-deployments-keys.ts | 60 ++++++++++++++++ scripts/autogen/contract-deployments.json | 74 ++++++++++---------- subgraph/package.json | 1 + subgraph/src/constants/constants.ts | 4 +- subgraph/subgraph.yaml | 12 ++-- test/utils/setup/initialSetup.ts | 2 +- 6 files changed, 107 insertions(+), 46 deletions(-) diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index 82b6ea69..aedd40b2 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -1,8 +1,68 @@ import { ContractDeploymentsKey } from "../util/files/contractDeploymentsJson"; export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ + { + networkName: 'arb_goerli', + objectName: 'poolsharkLimitSource' + }, + { + networkName: 'arb_goerli', + objectName: 'tickMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochMapLib' + }, + { + networkName: 'arb_goerli', + objectName: 'deltasLib' + }, + { + networkName: 'arb_goerli', + objectName: 'epochsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'ticksLib' + }, { networkName: 'arb_goerli', objectName: 'claimsLib' }, + { + networkName: 'arb_goerli', + objectName: 'positionsLib' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolManager' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolFactory' + }, + { + networkName: 'arb_goerli', + objectName: 'mintCall' + }, + { + networkName: 'arb_goerli', + objectName: 'burnCall' + }, + { + networkName: 'arb_goerli', + objectName: 'swapCall' + }, + { + networkName: 'arb_goerli', + objectName: 'quoteCall' + }, + { + networkName: 'arb_goerli', + objectName: 'coverPoolImpl' + }, + { + networkName: 'arb_goerli', + objectName: 'positionERC1155' + }, ]; \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index ac64186d..53fadbe1 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -50,89 +50,89 @@ }, "tickMapLib": { "contractName": "TickMap", - "contractAddress": "0xf4bc5e94e732df58958a592993e8c25a6d0002a9", + "contractAddress": "0x29eb755472102856ab9a9babf4d04273404d61df", "constructorArguments": [], - "created": "2023-09-25T01:59:31.395Z" + "created": "2023-10-01T13:30:26.735Z" }, "epochMapLib": { "contractName": "EpochMap", - "contractAddress": "0xd10d0570aab6618bbda6ac54ea9f2ddfcd68ebcc", + "contractAddress": "0x8f6b91faddf9521dc83c2913473908593bc6d452", "constructorArguments": [], - "created": "2023-09-25T01:59:32.821Z" + "created": "2023-10-01T13:30:28.186Z" }, "deltasLib": { "contractName": "Deltas", - "contractAddress": "0x4d7889cc4d60642c8b7c91c8cb4efab9c04842d5", + "contractAddress": "0xa37d00a363d8da87406ee369240d201ee2c87b3d", "constructorArguments": [], - "created": "2023-09-25T01:59:34.545Z" + "created": "2023-10-01T13:30:29.949Z" }, "epochsLib": { "contractName": "Epochs", - "contractAddress": "0xdad0d046b6166fea7f6e3613c8b6653b00872f75", + "contractAddress": "0x9fbd9d061bfdf53e87bb473ad95dede2a5f9ea04", "constructorArguments": [], - "created": "2023-09-25T01:59:37.359Z" + "created": "2023-10-01T13:30:32.280Z" }, "ticksLib": { "contractName": "Ticks", - "contractAddress": "0xdb0ad73c36c337f47e22737eae4cc6f936ddcb3f", + "contractAddress": "0x082af851f92e6de9941852aab625e37fd52bd873", "constructorArguments": [], - "created": "2023-09-25T01:59:38.867Z" + "created": "2023-10-01T13:30:33.917Z" }, "claimsLib": { "contractName": "Claims", - "contractAddress": "0x2c55dfa58eb98f892a8954f712baffbf5a8bc208", + "contractAddress": "0x89b1398d0d785e2e684be921294ba9d06f39218c", "constructorArguments": [], - "created": "2023-09-25T01:59:40.606Z" + "created": "2023-10-01T13:30:35.698Z" }, "positionsLib": { "contractName": "Positions", - "contractAddress": "0x42ff3191dd5ffabc297c86974a49c0db8ae985b7", + "contractAddress": "0xcd71412992644c8018b2f0ed10ce75c278c1b951", "constructorArguments": [], - "created": "2023-09-25T01:59:42.738Z" + "created": "2023-10-01T13:30:37.726Z" }, "coverPoolManager": { "contractName": "CoverPoolManager", - "contractAddress": "0xf76088f4c5ad2a138f68870449f019e0e93e1510", + "contractAddress": "0x7877a681d1290d80ed0272a920b9a5cee8fd2fac", "constructorArguments": [], - "created": "2023-09-25T01:59:44.380Z" + "created": "2023-10-01T13:30:39.432Z" }, "mintCall": { "contractName": "MintCall", - "contractAddress": "0x97534089c388cb5c477ec49030f659ca9e7517e0", + "contractAddress": "0xe5cb0e6371e1885aeec5c2b9f7c730aff0f7a079", "constructorArguments": [], - "created": "2023-09-25T01:59:50.324Z" + "created": "2023-10-01T13:30:45.602Z" }, "burnCall": { "contractName": "BurnCall", - "contractAddress": "0x7625ae1f998f6cff8d7ad9e31806c9dfbb9d6617", + "contractAddress": "0x9d497a02179343b384fe74e91f3473aa20ce04bf", "constructorArguments": [], - "created": "2023-09-25T01:59:52.205Z" + "created": "2023-10-01T13:30:47.331Z" }, "swapCall": { "contractName": "SwapCall", - "contractAddress": "0x6e11352c5cfd4b2ed214aed9ccbcdcc8a3d42365", + "contractAddress": "0xa657df94d3fb7ae53f01198cc4b49f75247df51e", "constructorArguments": [], - "created": "2023-09-25T01:59:53.856Z" + "created": "2023-10-01T13:30:49.010Z" }, "quoteCall": { "contractName": "QuoteCall", - "contractAddress": "0x18666efa258ac3305e53b6cac779617a71941613", + "contractAddress": "0x8a30afb4a1147073e328c9cf7375f457d18252d6", "constructorArguments": [], - "created": "2023-09-25T01:59:55.987Z" + "created": "2023-10-01T13:30:50.965Z" }, "coverPoolFactory": { "contractName": "CoverPoolFactory", - "contractAddress": "0x4b0288914ea8ab81da888e74f93da0062212ddcc", + "contractAddress": "0xf8f75a39663e97d36da4be2882608513512f4cf0", "constructorArguments": [ - "0xF76088F4C5Ad2a138f68870449f019e0E93E1510" + "0x7877A681D1290d80ed0272A920b9a5CeE8Fd2fAC" ], - "created": "2023-09-25T01:59:46.159Z" + "created": "2023-10-01T13:30:41.488Z" }, "coverPool": { "contractName": "CoverPool", - "contractAddress": "0x8d23572c0326b9242da4428ddfdffcc1975c705f", + "contractAddress": "0xaaa678556b92c93e81e15107bb43df9980f4255d", "constructorArguments": [], - "created": "2023-09-25T02:00:12.324Z" + "created": "2023-10-01T13:31:08.679Z" }, "token20Batcher": { "contractName": "Token20Batcher", @@ -142,11 +142,11 @@ }, "coverPoolImpl": { "contractName": "CoverPool", - "contractAddress": "0x021d33056507e041b8e799530af4088123d334a1", + "contractAddress": "0x1ab0396417172520cae0df81dc098b70d6c08004", "constructorArguments": [ - "0x4B0288914Ea8aB81DA888e74F93DA0062212ddcC" + "0xf8F75A39663E97D36dA4bE2882608513512f4cf0" ], - "created": "2023-09-25T01:59:57.763Z" + "created": "2023-10-01T13:30:52.774Z" }, "poolRouter": { "contractName": "PoolsharkRouter", @@ -159,11 +159,11 @@ }, "positionERC1155": { "contractName": "PositionERC1155", - "contractAddress": "0x2e05790dd1cd5689d2d4a9c9690121efb5ddeae6", + "contractAddress": "0x604f24b0f2e7b4f38502d82b69d67155002ddd78", "constructorArguments": [ - "0x4B0288914Ea8aB81DA888e74F93DA0062212ddcC" + "0xf8F75A39663E97D36dA4bE2882608513512f4cf0" ], - "created": "2023-09-25T01:59:59.551Z" + "created": "2023-10-01T13:30:54.448Z" }, "limitPoolManager": { "contractName": "LimitPoolManager", @@ -181,13 +181,13 @@ }, "poolsharkLimitSource": { "contractName": "PoolsharkLimitSource", - "contractAddress": "0xf0afe01f61148fe94f69823cd9b7a664ec4c4835", + "contractAddress": "0x59c43d42bd13541f2b4cb6f963e790e5b8ac9af5", "constructorArguments": [ "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", "0xecbec0e3f1d12644168f1a0bceaf4142ee97b91b", "0x434f4e5354414e542d50524f4455435400000000000000000000000000000000" ], - "created": "2023-09-25T01:59:29.677Z" + "created": "2023-10-01T13:30:25.130Z" } }, "scroll_alpha": { diff --git a/subgraph/package.json b/subgraph/package.json index 3dc02f32..f326d91f 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -18,6 +18,7 @@ "build": "graph build", "deploy": "graph deploy --product hosted-service alphak3y/poolshark-cover", "deploy-sats": "graph deploy cover-arbitrumGoerli --version-label v0.0.4 --node https://app.satsuma.xyz/api/subgraphs/deploy --deploy-key 7NoUUXPcOGfBX --ipfs https://ipfs.satsuma.xyz", + "deploy-staging": "graph deploy --version-label v0.0.1 --node https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/deploy --ipfs https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/ipfs staging-cover-arbitrumGoerli", "deploy-chainstack": "graph deploy --version-label v0.2.2 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", "deploy-op-test": "graph deploy --product hosted-service alphak3y/poolshark-cover-op-goerli", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020", diff --git a/subgraph/src/constants/constants.ts b/subgraph/src/constants/constants.ts index a518713d..abd6ceea 100644 --- a/subgraph/src/constants/constants.ts +++ b/subgraph/src/constants/constants.ts @@ -1,7 +1,7 @@ /* eslint-disable */ import { BigInt, BigDecimal, Address } from '@graphprotocol/graph-ts' import { CoverPoolFactory as FactoryContract } from '../../generated/CoverPoolFactory/CoverPoolFactory' -export let FACTORY_ADDRESS = '0x4b0288914ea8ab81da888e74f93da0062212ddcc' +export let FACTORY_ADDRESS = '0xf8f75a39663e97d36da4be2882608513512f4cf0' export let WETH_ADDRESS = '0x0bfaaafa6e8fb009cd4e2bd3693f2eec2d18b053' // tokens where USD value is safe to use for globals @@ -16,7 +16,7 @@ export let STABLE_COINS: string[] = [ ] // used for safe eth pricing -export const STABLE_POOL_ADDRESS = '0x8d23572c0326b9242da4428ddfdffcc1975c705f' +export const STABLE_POOL_ADDRESS = '0xaaa678556b92c93e81e15107bb43df9980f4255d' // determines which token to use for eth<-> rate, true means stable is token0 in pool above export const STABLE_IS_TOKEN_0 = false diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 9c337ce9..8d11838c 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -8,9 +8,9 @@ dataSources: name: CoverPoolFactory network: arbitrum-goerli source: - address: '0x4b0288914ea8ab81da888e74f93da0062212ddcc' + address: '0xf8f75a39663e97d36da4be2882608513512f4cf0' abi: CoverPoolFactory - startBlock: 43471400 + startBlock: 44921100 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -37,9 +37,9 @@ dataSources: name: CoverPoolManager network: arbitrum-goerli source: - address: '0xf76088f4c5ad2a138f68870449f019e0e93e1510' + address: '0x7877a681d1290d80ed0272a920b9a5cee8fd2fac' abi: CoverPoolManager - startBlock: 43471400 + startBlock: 44921100 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -68,9 +68,9 @@ dataSources: name: PoolsharkRouter network: arbitrum-goerli source: - address: '0xdb11885eac2a8944438322349925ac0de3159392' + address: '0xbe033a8649376bf3ac06cae9439c2612b582532c' abi: PoolsharkRouter - startBlock: 43471400 + startBlock: 44996083 mapping: kind: ethereum/events apiVersion: 0.0.6 diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index 8ffaf806..d3ccc335 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -514,7 +514,7 @@ export class InitialSetup { console.log('vol tier 3') const volTier3: VolatilityTier = { minAmountPerAuction: BN_ZERO, - auctionLength: 5 , + auctionLength: 5, sampleInterval: 1000, syncFee: 0, fillFee: 0, From f2f9f102ba35334b9ddaff1f72752cbe76437de9 Mon Sep 17 00:00:00 2001 From: alphak3y Date: Mon, 2 Oct 2023 13:31:09 -0600 Subject: [PATCH 24/26] subgraph modifications for syncLatestTick call --- subgraph/package.json | 2 +- subgraph/schema.graphql | 3 --- subgraph/src/mappings/coverpoolfactory.ts | 18 ++++++++++++------ subgraph/src/mappings/limit/samples.ts | 9 +++------ tasks/deploy/utils/mintPosition.ts | 2 +- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/subgraph/package.json b/subgraph/package.json index f326d91f..9dca6a44 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -18,7 +18,7 @@ "build": "graph build", "deploy": "graph deploy --product hosted-service alphak3y/poolshark-cover", "deploy-sats": "graph deploy cover-arbitrumGoerli --version-label v0.0.4 --node https://app.satsuma.xyz/api/subgraphs/deploy --deploy-key 7NoUUXPcOGfBX --ipfs https://ipfs.satsuma.xyz", - "deploy-staging": "graph deploy --version-label v0.0.1 --node https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/deploy --ipfs https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/ipfs staging-cover-arbitrumGoerli", + "deploy-staging": "graph deploy --version-label v0.0.2 --node https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/deploy --ipfs https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/ipfs staging-cover-arbitrumGoerli", "deploy-chainstack": "graph deploy --version-label v0.2.2 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", "deploy-op-test": "graph deploy --product hosted-service alphak3y/poolshark-cover-op-goerli", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020", diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index db4bcfc2..52386a59 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -136,9 +136,6 @@ type LimitPool @entity { id: ID! coverPool: CoverPool! - - samples: [Sample!]! - samplesRecorded: BigInt! } type Sample @entity { diff --git a/subgraph/src/mappings/coverpoolfactory.ts b/subgraph/src/mappings/coverpoolfactory.ts index f035708f..c74c66a2 100644 --- a/subgraph/src/mappings/coverpoolfactory.ts +++ b/subgraph/src/mappings/coverpoolfactory.ts @@ -6,7 +6,7 @@ import { fetchTokenName, fetchTokenDecimals, } from './utils/helpers' -import { safeLoadCoverPool, safeLoadCoverPoolFactory, safeLoadToken, safeLoadVolatilityTier } from './utils/loads' +import { safeLoadCoverPool, safeLoadCoverPoolFactory, safeLoadLimitPool, safeLoadToken, safeLoadVolatilityTier } from './utils/loads' import { BigInt } from '@graphprotocol/graph-ts' import { FACTORY_ADDRESS, ONE_BI } from '../constants/constants' @@ -70,15 +70,21 @@ export function handlePoolCreated(event: PoolCreated): void { factory.poolCount = factory.poolCount.plus(ONE_BI) factory.txnCount = factory.txnCount.plus(ONE_BI) - pool.save() - factory.save() - token0.save() - token1.save() - // create the tracked contract based on the template CoverPoolTemplate.create(poolAddressParam) if (poolTypeParam == 'PSHARK-CPROD') { + let loadLimitPool = safeLoadLimitPool(inputPoolParam.toHex()) + let limitPool = loadLimitPool.entity + if (!loadLimitPool.exists) { + limitPool.coverPool = poolAddressParam.toHex() + limitPool.save() + } LimitSamplesTemplate.create(inputPoolParam) } + + pool.save() + factory.save() + token0.save() + token1.save() } diff --git a/subgraph/src/mappings/limit/samples.ts b/subgraph/src/mappings/limit/samples.ts index 96675e04..0d66cfad 100644 --- a/subgraph/src/mappings/limit/samples.ts +++ b/subgraph/src/mappings/limit/samples.ts @@ -13,11 +13,8 @@ export function handleSampleRecorded(event: SampleRecorded): void { let loadCoverPool = safeLoadCoverPool(limitPool.coverPool) let coverPool = loadCoverPool.entity - // increment sample count - limitPool.samplesRecorded = limitPool.samplesRecorded.plus(ONE_BI) - if (limitPool.samplesRecorded.le(coverPool.sampleCountMax)) + if (limitPool.samplesRecorded.le(coverPool.sampleCountMax)) { coverPool.sampleCount = limitPool.samplesRecorded - - limitPool.save() - coverPool.save() + coverPool.save() + } } \ No newline at end of file diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index 0587599b..cddbcc2f 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -44,7 +44,7 @@ export class MintPosition { // 0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E await validateMint({ signer: hre.props.alice, - recipient: '0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E', + recipient: '0x65f5B282E024e3d6CaAD112e848dEc3317dB0902', lower: '73400', //1096 upper: '73600', //1211 amount: token1Amount, From c11f97fd675e382361e0e088b24e1855923260dc Mon Sep 17 00:00:00 2001 From: alphak3y Date: Fri, 3 Nov 2023 11:33:53 -0600 Subject: [PATCH 25/26] add synclatesttick to factory --- contracts/CoverPool.sol | 5 +- contracts/CoverPoolFactory.sol | 107 ++++++++++++++--- contracts/base/events/CoverPoolEvents.sol | 2 +- .../base/events/CoverPoolFactoryEvents.sol | 4 +- .../base/events/CoverPoolManagerEvents.sol | 5 +- contracts/interfaces/cover/ICoverPool.sol | 5 + .../interfaces/cover/ICoverPoolFactory.sol | 2 +- .../interfaces/cover/ICoverPoolManager.sol | 4 +- .../external/poolshark/limit/ILimitPool.sol | 55 --------- .../poolshark/limit/ILimitPoolFactory.sol | 16 --- contracts/interfaces/limit/ILimitPool.sol | 40 ++++++- .../interfaces/limit/ILimitPoolFactory.sol | 4 +- .../limit/ILimitPoolManager.sol | 4 +- .../modules/sources/ITwapSource.sol | 14 +++ .../interfaces/structs/PoolsharkStructs.sol | 37 +++++- .../sources/PoolsharkLimitSource.sol | 76 +++++++++--- .../libraries/sources/UniswapV3Source.sol | 51 +++++++- contracts/libraries/utils/SafeCast.sol | 7 ++ contracts/test/LimitPoolFactoryMock.sol | 12 +- contracts/test/LimitPoolMock.sol | 8 +- contracts/utils/CoverPoolErrors.sol | 4 +- contracts/utils/CoverPoolManager.sol | 65 ++++++----- contracts/utils/PoolsharkRouter.sol | 44 +++++-- hardhat.config.ts | 2 +- scripts/autogen/contract-deployments-keys.ts | 58 +--------- scripts/autogen/contract-deployments.json | 92 +++++++-------- subgraph/abis/CoverPoolFactory.json | 12 +- subgraph/abis/CoverPoolManager.json | 16 ++- subgraph/package.json | 2 +- subgraph/schema.graphql | 3 +- subgraph/src/mappings/coverpoolfactory.ts | 6 +- subgraph/src/mappings/coverpoolmanager.ts | 6 +- subgraph/subgraph.yaml | 18 +-- tasks/deploy/utils/mintPosition.ts | 15 +++ tasks/deploy/utils/mintTokens.ts | 52 +-------- test/utils/contracts/coverpool.ts | 2 +- test/utils/setup/initialSetup.ts | 109 ++++++++++++++---- 37 files changed, 591 insertions(+), 373 deletions(-) delete mode 100644 contracts/interfaces/external/poolshark/limit/ILimitPool.sol delete mode 100644 contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol rename contracts/interfaces/{external/poolshark => }/limit/ILimitPoolManager.sol (89%) diff --git a/contracts/CoverPool.sol b/contracts/CoverPool.sol index f22d795a..deec64cf 100644 --- a/contracts/CoverPool.sol +++ b/contracts/CoverPool.sol @@ -49,7 +49,6 @@ contract CoverPool is function initialize() external - factoryOnly { Ticks.initialize( tickMap, @@ -288,6 +287,10 @@ contract CoverPool is ); } + function syncGlobalState() external view returns (GlobalState memory) { + return globalState; + } + function priceBounds( int16 tickSpacing ) external pure returns (uint160, uint160) { diff --git a/contracts/CoverPoolFactory.sol b/contracts/CoverPoolFactory.sol index 8995f72f..9f2abde3 100644 --- a/contracts/CoverPoolFactory.sol +++ b/contracts/CoverPoolFactory.sol @@ -32,7 +32,7 @@ contract CoverPoolFactory is ) { // validate token pair if (params.tokenIn == params.tokenOut || params.tokenIn == address(0) || params.tokenOut == address(0)) { - revert InvalidTokenAddress(); + require(false, "InvalidTokenAddress()"); } CoverImmutables memory constants; constants.owner = owner; @@ -46,7 +46,7 @@ contract CoverPoolFactory is uint8 token1Decimals = ERC20(constants.token1).decimals(); if (token0Decimals > 18 || token1Decimals > 18 || token0Decimals < 6 || token1Decimals < 6) { - revert InvalidTokenDecimals(); + require(false, "InvalidTokenDecimals()"); } constants.token0Decimals = token0Decimals; constants.token1Decimals = token1Decimals; @@ -55,24 +55,26 @@ contract CoverPoolFactory is // get twap source { ( - address poolImpl, - address tokenImpl, - address twapSource - ) = ICoverPoolManager(owner).poolTypes(params.poolType); - if (poolImpl == address(0) || twapSource == address(0)) revert PoolTypeNotFound(); - constants.poolImpl = poolImpl; - constants.poolToken = tokenImpl; - constants.source = ITwapSource(twapSource); + address _poolImpl, + address _tokenImpl, + address _twapSource + ) = ICoverPoolManager(owner).poolTypes(params.poolTypeId); + if (_poolImpl == address(0) || _twapSource == address(0)) + require(false, "PoolTypeNotFound()"); + constants.poolImpl = _poolImpl; + constants.poolToken = _tokenImpl; + constants.source = ITwapSource(_twapSource); } // get volatility tier config { VolatilityTier memory config = ICoverPoolManager(owner).volatilityTiers( - params.poolType, + params.poolTypeId, params.feeTier, params.tickSpread, params.twapLength ); - if (config.auctionLength == 0) revert VolatilityTierNotSupported(); + if (config.auctionLength == 0) + require(false, "VolatilityTierNotSupported()"); constants.minAmountPerAuction = config.minAmountPerAuction; constants.auctionLength = config.auctionLength; constants.sampleInterval = config.sampleInterval; @@ -82,10 +84,11 @@ contract CoverPoolFactory is // record genesis time constants.tickSpread = params.tickSpread; constants.twapLength = params.twapLength; - constants.genesisTime = uint32(block.timestamp); + constants.genesisTime = uint32(block.timestamp); // get reference pool constants.inputPool = ITwapSource(constants.source).getPool(constants.token0, constants.token1, params.feeTier); - + if (constants.inputPool == address(0)) + require (false, "InputPoolDoesNotExist()"); // generate key for pool bytes32 key = keccak256( abi.encode( @@ -132,10 +135,10 @@ contract CoverPoolFactory is constants.inputPool, constants.token0, constants.token1, - params.poolType, params.feeTier, params.tickSpread, - params.twapLength + params.twapLength, + params.poolTypeId ); } @@ -153,7 +156,7 @@ contract CoverPoolFactory is address poolImpl, address tokenImpl, address source - ) = ICoverPoolManager(owner).poolTypes(params.poolType); + ) = ICoverPoolManager(owner).poolTypes(params.poolTypeId); address inputPool = ITwapSource(source).getPool(token0, token1, params.feeTier); // generate key for pool @@ -178,6 +181,76 @@ contract CoverPoolFactory is ); } + function syncLatestTick( + CoverPoolParams memory params + ) external view returns ( + int24 latestTick, + bool inputPoolExists, + bool twapReady + ) { + if (params.tokenIn == params.tokenOut || + params.tokenIn == address(0) || + params.tokenOut == address(0)) { + return (0, false, false); + } + CoverImmutables memory constants; + // set lexographical token address ordering + constants.token0 = params.tokenIn < params.tokenOut ? params.tokenIn : params.tokenOut; + constants.token1 = params.tokenIn < params.tokenOut ? params.tokenOut : params.tokenIn; + // get twap source + { + ( + ,, + address _twapSource + ) = ICoverPoolManager(owner).poolTypes(params.poolTypeId); + if (_twapSource == address(0)) + return (0, false, false); + constants.source = ITwapSource(constants.source); + } + constants.inputPool = ITwapSource(constants.source).getPool(constants.token0, constants.token1, params.feeTier); + + if (constants.inputPool == address(0)) + return (0, false, false); + + inputPoolExists = true; + + // generate key for pool + bytes32 key = keccak256(abi.encode( + constants.token0, + constants.token1, + constants.source, + constants.inputPool, + params.tickSpread, + params.twapLength + )); + + // validate erc20 decimals + { + uint8 token0Decimals = ERC20(constants.token0).decimals(); + uint8 token1Decimals = ERC20(constants.token1).decimals(); + if (token0Decimals > 18 || token1Decimals > 18 + || token0Decimals < 6 || token1Decimals < 6) { + return (0, true, false); + } + } + // get volatility tier config + { + VolatilityTier memory config = ICoverPoolManager(owner).volatilityTiers( + params.poolTypeId, + params.feeTier, + params.tickSpread, + params.twapLength + ); + if (config.auctionLength == 0) + return (0, true, false); + constants.sampleInterval = config.sampleInterval; + } + constants.tickSpread = params.tickSpread; + constants.twapLength = params.twapLength; + + (latestTick, twapReady) = ITwapSource(constants.source).syncLatestTick(constants, coverPools[key]); + } + function encodeCover( CoverImmutables memory constants ) private pure returns (bytes memory) { diff --git a/contracts/base/events/CoverPoolEvents.sol b/contracts/base/events/CoverPoolEvents.sol index 8e01ff49..045c2f0c 100644 --- a/contracts/base/events/CoverPoolEvents.sol +++ b/contracts/base/events/CoverPoolEvents.sol @@ -2,7 +2,7 @@ pragma solidity 0.8.13; abstract contract CoverPoolEvents { - event Mint( + event Mint( address indexed to, int24 lower, int24 upper, diff --git a/contracts/base/events/CoverPoolFactoryEvents.sol b/contracts/base/events/CoverPoolFactoryEvents.sol index 9c4087f9..d25b442a 100644 --- a/contracts/base/events/CoverPoolFactoryEvents.sol +++ b/contracts/base/events/CoverPoolFactoryEvents.sol @@ -7,9 +7,9 @@ abstract contract CoverPoolFactoryEvents { address indexed inputPool, address token0, address token1, - bytes32 indexed poolType, uint16 fee, int16 tickSpread, - uint16 twapLength + uint16 twapLength, + uint8 indexed poolTypeId ); } diff --git a/contracts/base/events/CoverPoolManagerEvents.sol b/contracts/base/events/CoverPoolManagerEvents.sol index 92011d01..fe0f91e9 100644 --- a/contracts/base/events/CoverPoolManagerEvents.sol +++ b/contracts/base/events/CoverPoolManagerEvents.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.13; abstract contract CoverPoolManagerEvents { event FactoryChanged(address indexed previousFactory, address indexed newFactory); event VolatilityTierEnabled( - bytes32 poolType, + uint8 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength, @@ -17,7 +17,8 @@ abstract contract CoverPoolManagerEvents { bool minLowerPriced ); event PoolTypeEnabled( - bytes32 poolType, + uint8 poolTypeId, + bytes32 poolTypeName, address implAddress, address sourceAddress, address factoryAddress diff --git a/contracts/interfaces/cover/ICoverPool.sol b/contracts/interfaces/cover/ICoverPool.sol index d8711c37..27fb8430 100644 --- a/contracts/interfaces/cover/ICoverPool.sol +++ b/contracts/interfaces/cover/ICoverPool.sol @@ -127,4 +127,9 @@ interface ICoverPool is CoverPoolStructs { uint160 minPrice, uint160 maxPrice ); + + function syncGlobalState( + ) external view returns ( + GlobalState memory state + ); } diff --git a/contracts/interfaces/cover/ICoverPoolFactory.sol b/contracts/interfaces/cover/ICoverPoolFactory.sol index b9412b71..cf927542 100644 --- a/contracts/interfaces/cover/ICoverPoolFactory.sol +++ b/contracts/interfaces/cover/ICoverPoolFactory.sol @@ -6,12 +6,12 @@ import '../../base/storage/CoverPoolFactoryStorage.sol'; abstract contract ICoverPoolFactory is CoverPoolFactoryStorage { struct CoverPoolParams { - bytes32 poolType; address tokenIn; address tokenOut; uint16 feeTier; int16 tickSpread; uint16 twapLength; + uint8 poolTypeId; } /** diff --git a/contracts/interfaces/cover/ICoverPoolManager.sol b/contracts/interfaces/cover/ICoverPoolManager.sol index bb57accf..a2503f92 100644 --- a/contracts/interfaces/cover/ICoverPoolManager.sol +++ b/contracts/interfaces/cover/ICoverPoolManager.sol @@ -8,14 +8,14 @@ interface ICoverPoolManager is CoverPoolStructs { function owner() external view returns (address); function feeTo() external view returns (address); function poolTypes( - bytes32 poolType + uint8 poolTypeId ) external view returns ( address poolImpl, address tokenImpl, address twapImpl ); function volatilityTiers( - bytes32 implName, + uint8 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPool.sol b/contracts/interfaces/external/poolshark/limit/ILimitPool.sol deleted file mode 100644 index f4045835..00000000 --- a/contracts/interfaces/external/poolshark/limit/ILimitPool.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity 0.8.13; - -interface ILimitPool { - struct RangePoolState { - SampleState samples; - uint200 feeGrowthGlobal0; - uint200 feeGrowthGlobal1; - uint160 secondsPerLiquidityAccum; - uint160 price; /// @dev Starting price current - uint128 liquidity; /// @dev Liquidity currently active - int56 tickSecondsAccum; - int24 tickAtPrice; - uint16 protocolSwapFee0; - uint16 protocolSwapFee1; - } - - struct SampleState { - uint16 index; - uint16 count; - uint16 countMax; - } - - struct LimitPoolState { - uint160 price; /// @dev Starting price current - uint128 liquidity; /// @dev Liquidity currently active - uint128 protocolFees; - uint16 protocolFillFee; - int24 tickAtPrice; - } - - function sample( - uint32[] memory secondsAgo - ) external view returns ( - int56[] memory tickSecondsAccum, - uint160[] memory secondsPerLiquidityAccum, - uint160 averagePrice, - uint128 averageLiquidity, - int24 averageTick - ); - - function increaseSampleCount( - uint16 newSampleCountMax - ) external; - - function globalState() external view returns ( - RangePoolState memory pool, - LimitPoolState memory pool0, - LimitPoolState memory pool1, - uint128 liquidityGlobal, - uint32 positionIdNext, - uint32 epoch, - uint8 unlocked - ); -} diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol b/contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol deleted file mode 100644 index 86f2a2b6..00000000 --- a/contracts/interfaces/external/poolshark/limit/ILimitPoolFactory.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: BUSL-1.1 -pragma solidity 0.8.13; - -import '../../../structs/PoolsharkStructs.sol'; - -abstract contract ILimitPoolFactory is PoolsharkStructs { - function getLimitPool( - bytes32 poolType, - address tokenIn, - address tokenOut, - uint16 swapFee - ) external view virtual returns ( - address pool, - address poolToken - ); -} diff --git a/contracts/interfaces/limit/ILimitPool.sol b/contracts/interfaces/limit/ILimitPool.sol index 03429ed3..54cb05a7 100644 --- a/contracts/interfaces/limit/ILimitPool.sol +++ b/contracts/interfaces/limit/ILimitPool.sol @@ -16,6 +16,20 @@ interface ILimitPool is PoolsharkStructs { BurnLimitParams memory params ) external; + function snapshotLimit( + SnapshotLimitParams memory params + ) external view returns( + uint128, + uint128 + ); + + function fees( + FeesParams memory params + ) external returns ( + uint128 token0Fees, + uint128 token1Fees + ); + function immutables( ) external view returns( LimitImmutables memory @@ -27,4 +41,28 @@ interface ILimitPool is PoolsharkStructs { uint160 minPrice, uint160 maxPrice ); -} + + function sample( + uint32[] memory secondsAgo + ) external view returns ( + int56[] memory tickSecondsAccum, + uint160[] memory secondsPerLiquidityAccum, + uint160 averagePrice, + uint128 averageLiquidity, + int24 averageTick + ); + + function increaseSampleCount( + uint16 newSampleCountMax + ) external; + + function globalState() external view returns ( + RangePoolState memory pool, + LimitPoolState memory pool0, + LimitPoolState memory pool1, + uint128 liquidityGlobal, + uint32 positionIdNext, + uint32 epoch, + uint8 unlocked + ); +} \ No newline at end of file diff --git a/contracts/interfaces/limit/ILimitPoolFactory.sol b/contracts/interfaces/limit/ILimitPoolFactory.sol index d8302452..90313306 100644 --- a/contracts/interfaces/limit/ILimitPoolFactory.sol +++ b/contracts/interfaces/limit/ILimitPoolFactory.sol @@ -12,10 +12,10 @@ abstract contract ILimitPoolFactory is PoolsharkStructs { ); function getLimitPool( - bytes32 poolType, address tokenIn, address tokenOut, - uint16 swapFee + uint16 swapFee, + uint8 poolTypeId ) external view virtual returns ( address pool, address poolToken diff --git a/contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol b/contracts/interfaces/limit/ILimitPoolManager.sol similarity index 89% rename from contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol rename to contracts/interfaces/limit/ILimitPoolManager.sol index cc616f33..5bb61838 100644 --- a/contracts/interfaces/external/poolshark/limit/ILimitPoolManager.sol +++ b/contracts/interfaces/limit/ILimitPoolManager.sol @@ -5,8 +5,8 @@ pragma solidity 0.8.13; interface ILimitPoolManager { function owner() external view returns (address); function feeTo() external view returns (address); - function implementations( - bytes32 poolType + function poolTypes( + uint8 poolType ) external view returns ( address poolImpl, address tokenImpl diff --git a/contracts/interfaces/modules/sources/ITwapSource.sol b/contracts/interfaces/modules/sources/ITwapSource.sol index fe9a7738..9cc72992 100644 --- a/contracts/interfaces/modules/sources/ITwapSource.sol +++ b/contracts/interfaces/modules/sources/ITwapSource.sol @@ -18,6 +18,20 @@ interface ITwapSource { int24 averageTick ); + function calculateAverageTicks( + PoolsharkStructs.CoverImmutables memory constants + ) external view returns ( + int24[4] memory averageTicks + ); + + function syncLatestTick( + PoolsharkStructs.CoverImmutables memory constants, + address coverPool + ) external view returns ( + int24 latestTick, + bool twapReady + ); + function getPool( address tokenA, address tokenB, diff --git a/contracts/interfaces/structs/PoolsharkStructs.sol b/contracts/interfaces/structs/PoolsharkStructs.sol index f4d1d2bd..2d528dd1 100644 --- a/contracts/interfaces/structs/PoolsharkStructs.sol +++ b/contracts/interfaces/structs/PoolsharkStructs.sol @@ -51,11 +51,11 @@ interface PoolsharkStructs { } struct LimitPoolParams { - bytes32 poolType; address tokenIn; address tokenOut; uint160 startPrice; uint16 swapFee; + uint8 poolTypeId; } struct MintLimitParams { @@ -101,6 +101,41 @@ interface PoolsharkStructs { bool zeroForOne; } + struct FeesParams { + uint16 protocolSwapFee0; + uint16 protocolSwapFee1; + uint16 protocolFillFee0; + uint16 protocolFillFee1; + uint8 setFeesFlags; + } + + struct LimitPoolState { + uint160 price; /// @dev Starting price current + uint128 liquidity; /// @dev Liquidity currently active + uint128 protocolFees; + uint16 protocolFillFee; + int24 tickAtPrice; + } + + struct RangePoolState { + SampleState samples; + uint200 feeGrowthGlobal0; + uint200 feeGrowthGlobal1; + uint160 secondsPerLiquidityAccum; + uint160 price; /// @dev Starting price current + uint128 liquidity; /// @dev Liquidity currently active + int56 tickSecondsAccum; + int24 tickAtPrice; + uint16 protocolSwapFee0; + uint16 protocolSwapFee1; + } + + struct SampleState { + uint16 index; + uint16 count; + uint16 countMax; + } + /** * @custom:struct MintCoverParams */ diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 92da0555..8bc81191 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.13; -import '../../interfaces/external/poolshark/limit/ILimitPoolManager.sol'; -import '../../interfaces/external/poolshark/limit/ILimitPoolFactory.sol'; -import '../../interfaces/external/poolshark/limit/ILimitPool.sol'; +import '../../interfaces/limit/ILimitPoolManager.sol'; +import '../../interfaces/limit/ILimitPoolFactory.sol'; +import '../../interfaces/limit/ILimitPool.sol'; import '../../base/events/TwapSourceEvents.sol'; +import '../../interfaces/cover/ICoverPool.sol'; import '../../interfaces/structs/CoverPoolStructs.sol'; import '../../interfaces/modules/sources/ITwapSource.sol'; import '../math/ConstantProduct.sol'; @@ -14,7 +15,7 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { error WaitUntilAboveMinTick(); // poolType on limitPoolFactory - bytes32 public immutable poolType; + uint8 public immutable poolType; address public immutable limitPoolFactory; address public immutable limitPoolManager; uint16 public constant oneSecond = 1000; @@ -22,7 +23,7 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { constructor( address _limitPoolFactory, address _limitPoolManager, - bytes32 _poolType + uint8 _poolType ) { limitPoolFactory = _limitPoolFactory; limitPoolManager = _limitPoolManager; @@ -36,8 +37,8 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { int24 startingTick ) { - // get the number of blocks covered by the twapLength - uint16 blockCount = uint16(constants.twapLength) * oneSecond / constants.sampleInterval; + // get the number of samples covered by the twapLength + uint16 samplesRequired = uint16(constants.twapLength) * oneSecond / constants.sampleInterval; ( uint16 sampleCount, uint16 sampleCountMax @@ -47,18 +48,18 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { msg.sender, sampleCount, sampleCountMax, - blockCount + samplesRequired ); - if (sampleCountMax < blockCount) { - _increaseSampleCount(constants.inputPool, blockCount); + if (sampleCountMax < samplesRequired) { + _increaseSampleCount(constants.inputPool, samplesRequired); return (0, 0); - } else if (sampleCount < blockCount) { + } else if (sampleCount < samplesRequired) { return (0, 0); } // ready to initialize initializable = 1; - int24[4] memory averageTicks = _calculateAverageTicks(constants); + int24[4] memory averageTicks = calculateAverageTicks(constants); // take the average of the 4 samples as a starting tick startingTick = (averageTicks[0] + averageTicks[1] + averageTicks[2] + averageTicks[3]) / 4; } @@ -83,7 +84,7 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { ) external view returns( address pool ) { - (pool,) = ILimitPoolFactory(limitPoolFactory).getLimitPool(poolType, token0, token1, feeTier); + (pool,) = ILimitPoolFactory(limitPoolFactory).getLimitPool(token0, token1, feeTier, poolType); } function calculateAverageTick( @@ -93,7 +94,7 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { int24 averageTick ) { - int24[4] memory averageTicks = _calculateAverageTicks(constants); + int24[4] memory averageTicks = calculateAverageTicks(constants); int24 minTickVariance = ConstantProduct.maxTick(constants.tickSpread) * 2; for (uint i; i < 4; i++) { int24 absTickVariance = latestTick - averageTicks[i] >= 0 ? latestTick - averageTicks[i] @@ -106,9 +107,9 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { } } - function _calculateAverageTicks( + function calculateAverageTicks( PoolsharkStructs.CoverImmutables memory constants - ) internal view returns ( + ) public view returns ( int24[4] memory averageTicks ) { @@ -140,6 +141,49 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { } } + function syncLatestTick( + PoolsharkStructs.CoverImmutables memory constants, + address coverPool + ) external view returns ( + int24 latestTick, + bool twapReady + ) { + if (constants.inputPool == address(0)) + return (0, false); + ( + uint16 sampleCount, + uint16 sampleCountMax + ) = _getSampleCount(constants.inputPool); + + // check twap readiness + uint16 samplesRequired = uint16(constants.twapLength) * + oneSecond / constants.sampleInterval; + if (sampleCountMax < samplesRequired) { + return (0, false); + } else if (sampleCount < samplesRequired) { + return (0, false); + } + // ready to initialize + twapReady = true; + + // if pool exists check unlocked state + uint8 unlockedState = 0; + if (coverPool != address(0)) { + CoverPoolStructs.GlobalState memory state = ICoverPool(coverPool).syncGlobalState(); + unlockedState = state.unlocked; + } + if (unlockedState == 0) { + // pool uninitialized + int24[4] memory averageTicks = calculateAverageTicks(constants); + // take the average of the 4 samples as a starting tick + latestTick = (averageTicks[0] + averageTicks[1] + averageTicks[2] + averageTicks[3]) / 4; + latestTick = (latestTick / int24(constants.tickSpread)) * int24(constants.tickSpread); + } else { + // pool initialized + latestTick = ICoverPool(coverPool).syncLatestTick(); + } + } + function _getSampleCount( address pool ) internal view returns ( diff --git a/contracts/libraries/sources/UniswapV3Source.sol b/contracts/libraries/sources/UniswapV3Source.sol index 13d94367..626829ef 100644 --- a/contracts/libraries/sources/UniswapV3Source.sol +++ b/contracts/libraries/sources/UniswapV3Source.sol @@ -4,6 +4,7 @@ pragma solidity 0.8.13; import '../../interfaces/external/uniswap/v3/IUniswapV3Factory.sol'; import '../../interfaces/external/uniswap/v3/IUniswapV3Pool.sol'; import '../../base/events/TwapSourceEvents.sol'; +import '../../interfaces/cover/ICoverPool.sol'; import '../../interfaces/structs/CoverPoolStructs.sol'; import '../../interfaces/modules/sources/ITwapSource.sol'; import '../math/ConstantProduct.sol'; @@ -54,7 +55,7 @@ contract UniswapV3Source is ITwapSource, TwapSourceEvents { ); // ready to initialize if we get here initializable = 1; - int24[4] memory averageTicks = _calculateAverageTicks(constants); + int24[4] memory averageTicks = calculateAverageTicks(constants); // take the average of the 4 samples as a starting tick startingTick = (averageTicks[0] + averageTicks[1] + averageTicks[2] + averageTicks[3]) / 4; } @@ -89,7 +90,7 @@ contract UniswapV3Source is ITwapSource, TwapSourceEvents { int24 averageTick ) { - int24[4] memory averageTicks = _calculateAverageTicks(constants); + int24[4] memory averageTicks = calculateAverageTicks(constants); int24 minTickVariance = ConstantProduct.maxTick(constants.tickSpread) * 2; for (uint i; i < 4; i++) { int24 absTickVariance = latestTick - averageTicks[i] >= 0 ? latestTick - averageTicks[i] @@ -102,9 +103,9 @@ contract UniswapV3Source is ITwapSource, TwapSourceEvents { } } - function _calculateAverageTicks( + function calculateAverageTicks( PoolsharkStructs.CoverImmutables memory constants - ) internal view returns ( + ) public view returns ( int24[4] memory averageTicks ) { @@ -136,6 +137,48 @@ contract UniswapV3Source is ITwapSource, TwapSourceEvents { } } + function syncLatestTick( + PoolsharkStructs.CoverImmutables memory constants, + address coverPool + ) external view returns ( + int24 latestTick, + bool twapReady + ) { + if (constants.inputPool == address(0)) + return (0, false); + + uint16 samplesRequired = uint16(constants.twapLength) * oneSecond / constants.sampleInterval; + ( + uint16 sampleCount, + uint16 sampleCountMax + ) = _getObservationsCardinality(constants.inputPool); + + if (sampleCountMax < samplesRequired) { + return (0, false); + } else if (sampleCount < samplesRequired) { + return (0, false); + } + // ready to initialize + twapReady = true; + + // if pool exists check unlocked state + uint8 unlockedState = 0; + if (coverPool != address(0)) { + CoverPoolStructs.GlobalState memory state = ICoverPool(coverPool).syncGlobalState(); + unlockedState = state.unlocked; + } + if (unlockedState == 0) { + // pool uninitialized + int24[4] memory averageTicks = calculateAverageTicks(constants); + // take the average of the 4 samples as a starting tick + latestTick = (averageTicks[0] + averageTicks[1] + averageTicks[2] + averageTicks[3]) / 4; + latestTick = (latestTick / int24(constants.tickSpread)) * int24(constants.tickSpread); + } else { + // pool initialized + latestTick = ICoverPool(coverPool).syncLatestTick(); + } + } + function _getObservationsCardinality( address pool ) internal view returns ( diff --git a/contracts/libraries/utils/SafeCast.sol b/contracts/libraries/utils/SafeCast.sol index 89192bd3..b049ca54 100644 --- a/contracts/libraries/utils/SafeCast.sol +++ b/contracts/libraries/utils/SafeCast.sol @@ -63,4 +63,11 @@ library SafeCast { if(y < 0) require(false, 'Int256ToUint256:Underflow()'); z = uint256(y); } + + /// @notice Cast a uint256 to a uint8, revert on overflow + /// @param y The uint256 to be downcasted + /// @return z The downcasted integer, now type uint128 + function toUint8(uint256 y) internal pure returns (uint8 z) { + if((z = uint8(y)) != y) require(false, 'Uint256ToUint8:Overflow()'); + } } \ No newline at end of file diff --git a/contracts/test/LimitPoolFactoryMock.sol b/contracts/test/LimitPoolFactoryMock.sol index ae10118c..abf57a9b 100644 --- a/contracts/test/LimitPoolFactoryMock.sol +++ b/contracts/test/LimitPoolFactoryMock.sol @@ -1,10 +1,10 @@ //SPDX-License-Identifier: Unlicense pragma solidity 0.8.13; -import '../interfaces/external/poolshark/limit/ILimitPoolFactory.sol'; +import '../interfaces/limit/ILimitPoolFactory.sol'; import './LimitPoolMock.sol'; -contract LimitPoolFactoryMock is ILimitPoolFactory { +contract LimitPoolFactoryMock { address mockPool; address mockPool2; address owner; @@ -30,14 +30,14 @@ contract LimitPoolFactoryMock is ILimitPoolFactory { } function getLimitPool( - bytes32 poolType, address tokenIn, address tokenOut, - uint16 feeTier - ) external view override returns (address pool, address poolToken) { + uint16 feeTier, + uint8 poolTypeId + ) external view returns (address pool, address poolToken) { address token0 = tokenIn < tokenOut ? tokenIn : tokenOut; address token1 = tokenIn < tokenOut ? tokenOut : tokenIn; - poolType; + poolTypeId; poolToken; pool = limitPools[token0][token1][feeTier]; diff --git a/contracts/test/LimitPoolMock.sol b/contracts/test/LimitPoolMock.sol index 14e1e02a..dd937c94 100644 --- a/contracts/test/LimitPoolMock.sol +++ b/contracts/test/LimitPoolMock.sol @@ -1,10 +1,10 @@ //SPDX-License-Identifier: Unlicense pragma solidity 0.8.13; -import '../interfaces/external/poolshark/limit/ILimitPool.sol'; +import '../interfaces/limit/ILimitPool.sol'; import './UniswapV3PoolMock.sol'; -contract LimitPoolMock is ILimitPool { +contract LimitPoolMock is PoolsharkStructs { address internal admin; address public token0; address public token1; @@ -41,7 +41,7 @@ contract LimitPoolMock is ILimitPool { function globalState() external - view override + view returns ( RangePoolState memory pool, LimitPoolState memory pool0, @@ -67,7 +67,7 @@ contract LimitPoolMock is ILimitPool { function sample( uint32[] calldata secondsAgos - ) external view override returns ( + ) external view returns ( int56[] memory tickSecondsAccum, uint160[] memory secondsPerLiquidityAccum, uint160 averagePrice, diff --git a/contracts/utils/CoverPoolErrors.sol b/contracts/utils/CoverPoolErrors.sol index e8841488..b557e957 100644 --- a/contracts/utils/CoverPoolErrors.sol +++ b/contracts/utils/CoverPoolErrors.sol @@ -45,9 +45,7 @@ abstract contract CoverPoolFactoryErrors { error VolatilityTierNotSupported(); error InvalidTickSpread(); error PoolTypeNotFound(); - error CurveMathNotFound(); - error TickSpreadNotMultipleOfTickSpacing(); - error TickSpreadNotAtLeastDoubleTickSpread(); + error InputPoolDoesNotExist(); } abstract contract CoverTransferErrors { diff --git a/contracts/utils/CoverPoolManager.sol b/contracts/utils/CoverPoolManager.sol index 945f9919..c16d7b32 100644 --- a/contracts/utils/CoverPoolManager.sol +++ b/contracts/utils/CoverPoolManager.sol @@ -2,6 +2,7 @@ pragma solidity 0.8.13; +import '../libraries/utils/SafeCast.sol'; import '../interfaces/cover/ICoverPool.sol'; import '../interfaces/cover/ICoverPoolFactory.sol'; import '../interfaces/cover/ICoverPoolManager.sol'; @@ -17,11 +18,14 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { uint16 public constant MAX_PROTOCOL_FEE = 1e4; /// @dev - max protocol fee of 1% uint16 public constant oneSecond = 1000; // poolType => impl address - mapping(bytes32 => address) internal _poolTypes; - mapping(bytes32 => address) internal _poolTokens; - mapping(bytes32 => address) internal _twapSources; + bytes32[] _poolTypeNames; + mapping(uint256 => address) internal _poolTypes; + mapping(uint256 => address) internal _poolTokens; + mapping(uint256 => address) internal _twapSources; // sourceName => feeTier => tickSpread => twapLength => VolatilityTier - mapping(bytes32 => mapping(uint16 => mapping(int16 => mapping(uint16 => VolatilityTier)))) internal _volatilityTiers; + mapping(uint256 => mapping(uint16 => mapping(int16 => mapping(uint16 => VolatilityTier)))) internal _volatilityTiers; + + using SafeCast for uint256; constructor() { owner = msg.sender; @@ -78,35 +82,36 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } function enablePoolType( - bytes32 poolType, - address poolImpl, - address tokenImpl, - address twapImpl + address poolImpl_, + address tokenImpl_, + address twapImpl_, + bytes32 poolTypeName_ ) external onlyOwner { + uint8 poolTypeId_ = _poolTypeNames.length.toUint8(); // valid poolType name - if(poolType == bytes32("")) + if(poolTypeName_ == bytes32("")) require (false, 'PoolTypeNameInvalid()'); // invalid impl address - if(poolImpl == address(0) || twapImpl == address(0) || tokenImpl == address(0)) + if(poolImpl_ == address(0) || twapImpl_ == address(0) || tokenImpl_ == address(0)) require (false, 'TwapSourceAddressZero()'); // pool type already exists - if(_twapSources[poolType] != address(0) || _poolTypes[poolType] != address(0)) + if(_twapSources[poolTypeId_] != address(0) || _poolTypes[poolTypeId_] != address(0)) require (false, 'PoolTypeAlreadyExists()'); - - _poolTypes[poolType] = poolImpl; - _poolTokens[poolType] = tokenImpl; - _twapSources[poolType] = twapImpl; - emit PoolTypeEnabled(poolType, poolImpl, twapImpl, ITwapSource(twapImpl).factory()); + _poolTypes[poolTypeId_] = poolImpl_; + _poolTokens[poolTypeId_] = tokenImpl_; + _twapSources[poolTypeId_] = twapImpl_; + _poolTypeNames.push(poolTypeName_); + emit PoolTypeEnabled(poolTypeId_, poolTypeName_, poolImpl_, twapImpl_, ITwapSource(twapImpl_).factory()); } function enableVolatilityTier( - bytes32 poolType, + uint8 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength, VolatilityTier memory volTier ) external onlyOwner { - if (_volatilityTiers[poolType][feeTier][tickSpread][twapLength].auctionLength != 0) { + if (_volatilityTiers[poolTypeId][feeTier][tickSpread][twapLength].auctionLength != 0) { require (false, 'VolatilityTierAlreadyEnabled()'); } else if (volTier.auctionLength == 0 || volTier.minPositionWidth <= 0) { require (false, 'VolatilityTierCannotBeZero()'); @@ -115,7 +120,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } else if (volTier.syncFee > 10000 || volTier.fillFee > 10000) { require (false, 'ProtocolFeeCeilingExceeded()'); } - address sourceAddress = _twapSources[poolType]; + address sourceAddress = _twapSources[poolTypeId]; { // check fee tier exists if (sourceAddress == address(0)) require (false, 'TwapSourceNotFound()'); @@ -132,10 +137,10 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } } // twapLength * sampleInterval should never overflow uint16 - _volatilityTiers[poolType][feeTier][tickSpread][twapLength] = volTier; + _volatilityTiers[poolTypeId][feeTier][tickSpread][twapLength] = volTier; emit VolatilityTierEnabled( - poolType, + poolTypeId, feeTier, tickSpread, twapLength, @@ -150,7 +155,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } function modifyVolatilityTierFees( - bytes32 implName, + uint8 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength, @@ -160,8 +165,8 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { if (syncFee > 10000 || fillFee > 10000) { require (false, 'ProtocolFeeCeilingExceeded()'); } - _volatilityTiers[implName][feeTier][tickSpread][twapLength].syncFee = syncFee; - _volatilityTiers[implName][feeTier][tickSpread][twapLength].fillFee = fillFee; + _volatilityTiers[poolTypeId][feeTier][tickSpread][twapLength].syncFee = syncFee; + _volatilityTiers[poolTypeId][feeTier][tickSpread][twapLength].fillFee = fillFee; } function setFactory( @@ -214,28 +219,28 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } function poolTypes( - bytes32 poolType + uint8 poolTypeId ) external view returns ( address poolImpl, address tokenImpl, address twapImpl ) { return ( - _poolTypes[poolType], - _poolTokens[poolType], - _twapSources[poolType] + _poolTypes[poolTypeId], + _poolTokens[poolTypeId], + _twapSources[poolTypeId] ); } function volatilityTiers( - bytes32 implName, + uint8 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength ) external view returns ( VolatilityTier memory config ) { - config = _volatilityTiers[implName][feeTier][tickSpread][twapLength]; + config = _volatilityTiers[poolTypeId][feeTier][tickSpread][twapLength]; } /** diff --git a/contracts/utils/PoolsharkRouter.sol b/contracts/utils/PoolsharkRouter.sol index 6b010a93..34ca713a 100644 --- a/contracts/utils/PoolsharkRouter.sol +++ b/contracts/utils/PoolsharkRouter.sol @@ -269,6 +269,24 @@ contract PoolsharkRouter is } } + function multiSnapshotLimit( + address[] memory pools, + SnapshotLimitParams[] memory params + ) external view returns( + uint128[] memory amountIns, + uint128[] memory amountOuts + ) { + amountIns = new uint128[](pools.length); + amountOuts = new uint128[](pools.length); + for (uint i = 0; i < pools.length;) { + if (pools[i] == address(0)) require(false, "InvalidPoolAddress()"); + (amountIns[i], amountOuts[i]) = ILimitPool(pools[i]).snapshotLimit(params[i]); + unchecked { + ++i; + } + } + } + function createLimitPoolAndMint( ILimitPoolFactory.LimitPoolParams memory params, MintRangeParams[] memory mintRangeParams, @@ -282,10 +300,10 @@ contract PoolsharkRouter is pool, poolToken ) = ILimitPoolFactory(limitPoolFactory).getLimitPool( - params.poolType, params.tokenIn, params.tokenOut, - params.swapFee + params.swapFee, + params.poolTypeId ); // create if pool doesn't exist if (pool == address(0)) { @@ -298,14 +316,22 @@ contract PoolsharkRouter is } // mint initial range positions for (uint i = 0; i < mintRangeParams.length;) { - IRangePool(pool).mintRange(mintRangeParams[i]); + mintRangeParams[i].positionId = 0; + mintRangeParams[i].callbackData = abi.encode(MintCallbackData({sender: msg.sender})); + try IRangePool(pool).mintRange(mintRangeParams[i]){ + } catch { + } unchecked { ++i; } } // mint initial limit positions for (uint i = 0; i < mintLimitParams.length;) { - ILimitPool(pool).mintLimit(mintLimitParams[i]); + mintLimitParams[i].positionId = 0; + mintLimitParams[i].callbackData = abi.encode(MintCallbackData({sender: msg.sender})); + try ILimitPool(pool).mintLimit(mintLimitParams[i]) { + } catch { + } unchecked { ++i; } @@ -337,7 +363,11 @@ contract PoolsharkRouter is } // mint initial cover positions for (uint i = 0; i < mintCoverParams.length;) { - ICoverPool(pool).mint(mintCoverParams[i]); + mintCoverParams[i].positionId = 0; + mintCoverParams[i].callbackData = abi.encode(MintCallbackData({sender: msg.sender})); + try ICoverPool(pool).mint(mintCoverParams[i]){ + } catch { + } unchecked { ++i; } @@ -373,12 +403,12 @@ contract PoolsharkRouter is // check if result already sorted if (!locals.sortedFlags[index]) { if (params[0].exactIn) { - if (results[index].amountOut >= locals.sortAmount) { + if (results[index].amountOut > 0 && results[index].amountOut >= locals.sortAmount) { locals.sortIndex = index; locals.sortAmount = results[index].amountOut; } } else { - if (results[index].amountIn <= locals.sortAmount) { + if (results[index].amountIn > 0 && results[index].amountIn <= locals.sortAmount) { locals.sortIndex = index; locals.sortAmount = results[index].amountIn; } diff --git a/hardhat.config.ts b/hardhat.config.ts index c494043e..ae96119a 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -35,7 +35,7 @@ const config: HardhatUserConfig = { }, arb_goerli: { chainId: 421613, - gasPrice: 100000000000, + gasPrice: 1_000_000_000, url: process.env.ARBITRUM_GOERLI_URL || '', accounts: process.env.PRIVATE_KEY !== undefined ? [process.env.PRIVATE_KEY] : [], timeout: 60000, diff --git a/scripts/autogen/contract-deployments-keys.ts b/scripts/autogen/contract-deployments-keys.ts index aedd40b2..ffab0baa 100644 --- a/scripts/autogen/contract-deployments-keys.ts +++ b/scripts/autogen/contract-deployments-keys.ts @@ -1,68 +1,12 @@ import { ContractDeploymentsKey } from "../util/files/contractDeploymentsJson"; export const CONTRACT_DEPLOYMENT_KEYS: ContractDeploymentsKey[] = [ - { - networkName: 'arb_goerli', - objectName: 'poolsharkLimitSource' - }, - { - networkName: 'arb_goerli', - objectName: 'tickMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochMapLib' - }, - { - networkName: 'arb_goerli', - objectName: 'deltasLib' - }, - { - networkName: 'arb_goerli', - objectName: 'epochsLib' - }, { networkName: 'arb_goerli', objectName: 'ticksLib' }, - { - networkName: 'arb_goerli', - objectName: 'claimsLib' - }, { networkName: 'arb_goerli', objectName: 'positionsLib' }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolManager' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolFactory' - }, - { - networkName: 'arb_goerli', - objectName: 'mintCall' - }, - { - networkName: 'arb_goerli', - objectName: 'burnCall' - }, - { - networkName: 'arb_goerli', - objectName: 'swapCall' - }, - { - networkName: 'arb_goerli', - objectName: 'quoteCall' - }, - { - networkName: 'arb_goerli', - objectName: 'coverPoolImpl' - }, - { - networkName: 'arb_goerli', - objectName: 'positionERC1155' - }, -]; \ No newline at end of file +] \ No newline at end of file diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index 53fadbe1..fdf2c9a8 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -50,89 +50,89 @@ }, "tickMapLib": { "contractName": "TickMap", - "contractAddress": "0x29eb755472102856ab9a9babf4d04273404d61df", + "contractAddress": "0xe618ee633aa483b6b90d004e1e848791d4f7c986", "constructorArguments": [], - "created": "2023-10-01T13:30:26.735Z" + "created": "2023-11-02T22:43:32.357Z" }, "epochMapLib": { "contractName": "EpochMap", - "contractAddress": "0x8f6b91faddf9521dc83c2913473908593bc6d452", + "contractAddress": "0x1fe541c10a679bf02202bae7eda13d71a0180ec2", "constructorArguments": [], - "created": "2023-10-01T13:30:28.186Z" + "created": "2023-11-02T22:43:33.847Z" }, "deltasLib": { "contractName": "Deltas", - "contractAddress": "0xa37d00a363d8da87406ee369240d201ee2c87b3d", + "contractAddress": "0x0a080de5da6308e3db793f790033ad753453a2ca", "constructorArguments": [], - "created": "2023-10-01T13:30:29.949Z" + "created": "2023-11-02T22:43:35.604Z" }, "epochsLib": { "contractName": "Epochs", - "contractAddress": "0x9fbd9d061bfdf53e87bb473ad95dede2a5f9ea04", + "contractAddress": "0xa625e1aaa080d2f5dadd51a90948b270d2d8d3dd", "constructorArguments": [], - "created": "2023-10-01T13:30:32.280Z" + "created": "2023-11-02T22:43:38.035Z" }, "ticksLib": { "contractName": "Ticks", - "contractAddress": "0x082af851f92e6de9941852aab625e37fd52bd873", + "contractAddress": "0xb235cdf93884fc2078b5d929689c6c125fc7fb2c", "constructorArguments": [], - "created": "2023-10-01T13:30:33.917Z" + "created": "2023-11-02T22:43:39.850Z" }, "claimsLib": { "contractName": "Claims", - "contractAddress": "0x89b1398d0d785e2e684be921294ba9d06f39218c", + "contractAddress": "0x60b9965e3e86ab199c1c76914ae64f9dee241969", "constructorArguments": [], - "created": "2023-10-01T13:30:35.698Z" + "created": "2023-11-02T22:43:41.635Z" }, "positionsLib": { "contractName": "Positions", - "contractAddress": "0xcd71412992644c8018b2f0ed10ce75c278c1b951", + "contractAddress": "0x26e745ce8153d2d40339bead44b68eb77c29982e", "constructorArguments": [], - "created": "2023-10-01T13:30:37.726Z" + "created": "2023-11-02T22:43:43.624Z" }, "coverPoolManager": { "contractName": "CoverPoolManager", - "contractAddress": "0x7877a681d1290d80ed0272a920b9a5cee8fd2fac", + "contractAddress": "0x87131ccc50786e387cfebcaafa522073a8e43548", "constructorArguments": [], - "created": "2023-10-01T13:30:39.432Z" + "created": "2023-11-02T22:43:45.355Z" }, "mintCall": { "contractName": "MintCall", - "contractAddress": "0xe5cb0e6371e1885aeec5c2b9f7c730aff0f7a079", + "contractAddress": "0xe644bd89b10afac8ec8ac19f1872837f08fcbe19", "constructorArguments": [], - "created": "2023-10-01T13:30:45.602Z" + "created": "2023-11-02T22:43:51.505Z" }, "burnCall": { "contractName": "BurnCall", - "contractAddress": "0x9d497a02179343b384fe74e91f3473aa20ce04bf", + "contractAddress": "0xc86be213fa0f4e13d1a649937052f02a5a194dcb", "constructorArguments": [], - "created": "2023-10-01T13:30:47.331Z" + "created": "2023-11-02T22:43:53.248Z" }, "swapCall": { "contractName": "SwapCall", - "contractAddress": "0xa657df94d3fb7ae53f01198cc4b49f75247df51e", + "contractAddress": "0x188d2440b8eee2e230e92a1b65d39283e1c47666", "constructorArguments": [], - "created": "2023-10-01T13:30:49.010Z" + "created": "2023-11-02T22:43:54.912Z" }, "quoteCall": { "contractName": "QuoteCall", - "contractAddress": "0x8a30afb4a1147073e328c9cf7375f457d18252d6", + "contractAddress": "0x35ba9286f1ee7e518beafd4139dc67752b439da2", "constructorArguments": [], - "created": "2023-10-01T13:30:50.965Z" + "created": "2023-11-02T22:43:56.912Z" }, "coverPoolFactory": { "contractName": "CoverPoolFactory", - "contractAddress": "0xf8f75a39663e97d36da4be2882608513512f4cf0", + "contractAddress": "0xc4230d3f673a44bf125c94effd1a6cc44202e0b8", "constructorArguments": [ - "0x7877A681D1290d80ed0272A920b9a5CeE8Fd2fAC" + "0x87131cCc50786e387CfebCAafA522073a8E43548" ], - "created": "2023-10-01T13:30:41.488Z" + "created": "2023-11-02T22:43:47.451Z" }, "coverPool": { "contractName": "CoverPool", - "contractAddress": "0xaaa678556b92c93e81e15107bb43df9980f4255d", + "contractAddress": "0xaff9a4f0d8c2b17e898180f0a29ad76b9a4756c0", "constructorArguments": [], - "created": "2023-10-01T13:31:08.679Z" + "created": "2023-11-02T22:44:15.888Z" }, "token20Batcher": { "contractName": "Token20Batcher", @@ -142,38 +142,38 @@ }, "coverPoolImpl": { "contractName": "CoverPool", - "contractAddress": "0x1ab0396417172520cae0df81dc098b70d6c08004", + "contractAddress": "0x68cc0410a7a61061143879d4f79ba5714352c8cf", "constructorArguments": [ - "0xf8F75A39663E97D36dA4bE2882608513512f4cf0" + "0xC4230d3F673A44Bf125c94EFFD1A6Cc44202e0B8" ], - "created": "2023-10-01T13:30:52.774Z" + "created": "2023-11-02T22:43:59.040Z" }, "poolRouter": { "contractName": "PoolsharkRouter", - "contractAddress": "0xdb11885eac2a8944438322349925ac0de3159392", + "contractAddress": "0x6ccccc845849b76f3acb3affcca28a6035e41a20", "constructorArguments": [ - "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", - "0x4b0288914ea8ab81da888e74f93da0062212ddcc" + "0xd0219266568eae5c1eea960e3eacf1a1e149aab0", + "0xC4230d3F673A44Bf125c94EFFD1A6Cc44202e0B8" ], - "created": "2023-09-25T03:03:32.166Z" + "created": "2023-11-02T22:44:04.308Z" }, "positionERC1155": { "contractName": "PositionERC1155", - "contractAddress": "0x604f24b0f2e7b4f38502d82b69d67155002ddd78", + "contractAddress": "0x7744c90fca4c06bd19bf91850bc78c14da53479b", "constructorArguments": [ - "0xf8F75A39663E97D36dA4bE2882608513512f4cf0" + "0xC4230d3F673A44Bf125c94EFFD1A6Cc44202e0B8" ], - "created": "2023-10-01T13:30:54.448Z" + "created": "2023-11-02T22:44:00.878Z" }, "limitPoolManager": { "contractName": "LimitPoolManager", - "contractAddress": "0xecbec0e3f1d12644168f1a0bceaf4142ee97b91b", + "contractAddress": "0xcfe989b7d341ef9b766263a980adadd16d3d0ac9", "constructorArguments": [], "created": "2023-09-24T14:56:56.998Z" }, "limitPoolFactory": { "contractName": "LimitPoolFactory", - "contractAddress": "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", + "contractAddress": "0xd0219266568eae5c1eea960e3eacf1a1e149aab0", "constructorArguments": [ "0xEcBeC0E3F1d12644168F1a0bCeAf4142ee97B91B" ], @@ -181,13 +181,13 @@ }, "poolsharkLimitSource": { "contractName": "PoolsharkLimitSource", - "contractAddress": "0x59c43d42bd13541f2b4cb6f963e790e5b8ac9af5", + "contractAddress": "0x7411c07e51fcbdd5832ede04d54783af1ace3ca7", "constructorArguments": [ - "0xab21829ec97c5fb6fc5edee736235fa7ca1fbb0a", - "0xecbec0e3f1d12644168f1a0bceaf4142ee97b91b", - "0x434f4e5354414e542d50524f4455435400000000000000000000000000000000" + "0xd0219266568eae5c1eea960e3eacf1a1e149aab0", + "0xcfe989b7d341ef9b766263a980adadd16d3d0ac9", + 0 ], - "created": "2023-10-01T13:30:25.130Z" + "created": "2023-11-02T22:43:30.655Z" } }, "scroll_alpha": { diff --git a/subgraph/abis/CoverPoolFactory.json b/subgraph/abis/CoverPoolFactory.json index e0a70850..47cb70f9 100644 --- a/subgraph/abis/CoverPoolFactory.json +++ b/subgraph/abis/CoverPoolFactory.json @@ -26,12 +26,6 @@ "name": "token1", "type": "address" }, - { - "indexed": true, - "internalType": "bytes32", - "name": "poolType", - "type": "bytes32" - }, { "indexed": false, "internalType": "uint16", @@ -49,6 +43,12 @@ "internalType": "uint16", "name": "twapLength", "type": "uint16" + }, + { + "indexed": true, + "internalType": "uint8", + "name": "poolTypeId", + "type": "uint8" } ], "name": "PoolCreated", diff --git a/subgraph/abis/CoverPoolManager.json b/subgraph/abis/CoverPoolManager.json index f5ea9f3d..eeb90400 100644 --- a/subgraph/abis/CoverPoolManager.json +++ b/subgraph/abis/CoverPoolManager.json @@ -59,10 +59,16 @@ { "anonymous": false, "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "poolTypeId", + "type": "uint8" + }, { "indexed": false, "internalType": "bytes32", - "name": "poolType", + "name": "poolTypeName", "type": "bytes32" }, { @@ -160,9 +166,9 @@ "inputs": [ { "indexed": false, - "internalType": "bytes32", - "name": "poolType", - "type": "bytes32" + "internalType": "uint8", + "name": "poolTypeId", + "type": "uint8" }, { "indexed": false, @@ -197,7 +203,7 @@ { "indexed": false, "internalType": "uint16", - "name": "blockTime", + "name": "sampleInterval", "type": "uint16" }, { diff --git a/subgraph/package.json b/subgraph/package.json index 9dca6a44..5f17d591 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -19,7 +19,7 @@ "deploy": "graph deploy --product hosted-service alphak3y/poolshark-cover", "deploy-sats": "graph deploy cover-arbitrumGoerli --version-label v0.0.4 --node https://app.satsuma.xyz/api/subgraphs/deploy --deploy-key 7NoUUXPcOGfBX --ipfs https://ipfs.satsuma.xyz", "deploy-staging": "graph deploy --version-label v0.0.2 --node https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/deploy --ipfs https://api.graph-eu.p2pify.com/705e9b5127dea429966086e1021e19f6/ipfs staging-cover-arbitrumGoerli", - "deploy-chainstack": "graph deploy --version-label v0.2.2 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", + "deploy-chainstack": "graph deploy --version-label v0.2.4 --node https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/deploy --ipfs https://api.graph-eu.p2pify.com/643e8c5f0f9ff2b36bb9da6b94af7d5f/ipfs cover-arbitrumGoerli-beta2", "deploy-op-test": "graph deploy --product hosted-service alphak3y/poolshark-cover-op-goerli", "deploy-local": "graph deploy example --ipfs http://localhost:5001 --node http://127.0.0.1:8020", "test": "graph codegen; graph test -v 0.2.0" diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 52386a59..c48ac01a 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -35,7 +35,7 @@ type CoverPoolManager @entity { type VolatilityTier @entity { # fee amount + tick spread + twap length + auction length id: ID! - poolType: String! + poolTypeId: String! feeAmount: BigInt! tickSpread: BigInt! twapLength: BigInt! @@ -136,6 +136,7 @@ type LimitPool @entity { id: ID! coverPool: CoverPool! + samplesRecorded: BigInt! } type Sample @entity { diff --git a/subgraph/src/mappings/coverpoolfactory.ts b/subgraph/src/mappings/coverpoolfactory.ts index c74c66a2..b98d9078 100644 --- a/subgraph/src/mappings/coverpoolfactory.ts +++ b/subgraph/src/mappings/coverpoolfactory.ts @@ -15,12 +15,12 @@ export function handlePoolCreated(event: PoolCreated): void { let feeTierParam = BigInt.fromI32(event.params.fee) let tickSpreadParam = BigInt.fromI32(event.params.tickSpread) let twapLengthParam = BigInt.fromI32(event.params.twapLength) - let poolTypeParam = event.params.poolType.toString() + let poolTypeIdParam: string = event.params.poolTypeId.toString() let poolAddressParam = event.params.pool let inputPoolParam = event.params.inputPool // load from store - let loadVolatilityTier = safeLoadVolatilityTier(poolTypeParam, feeTierParam, tickSpreadParam, twapLengthParam) + let loadVolatilityTier = safeLoadVolatilityTier(poolTypeIdParam, feeTierParam, tickSpreadParam, twapLengthParam) let loadCoverPool = safeLoadCoverPool(poolAddressParam.toHex()) let loadCoverPoolFactory = safeLoadCoverPoolFactory(FACTORY_ADDRESS.toLowerCase()) let loadToken0 = safeLoadToken(event.params.token0.toHexString()) @@ -73,7 +73,7 @@ export function handlePoolCreated(event: PoolCreated): void { // create the tracked contract based on the template CoverPoolTemplate.create(poolAddressParam) - if (poolTypeParam == 'PSHARK-CPROD') { + if (poolTypeIdParam == '0') { let loadLimitPool = safeLoadLimitPool(inputPoolParam.toHex()) let limitPool = loadLimitPool.entity if (!loadLimitPool.exists) { diff --git a/subgraph/src/mappings/coverpoolmanager.ts b/subgraph/src/mappings/coverpoolmanager.ts index b6d2af59..be0cb9f7 100644 --- a/subgraph/src/mappings/coverpoolmanager.ts +++ b/subgraph/src/mappings/coverpoolmanager.ts @@ -20,15 +20,15 @@ export function handleVolatilityTierEnabled(event: VolatilityTierEnabled): void let tickSpreadParam = BigInt.fromI32(event.params.tickSpread) let twapLengthParam = BigInt.fromI32(event.params.twapLength) let auctionLengthParam = BigInt.fromI32(event.params.auctionLength) - let poolTypeParam = event.params.poolType.toString() + let poolTypeIdParam: string = event.params.poolTypeId.toString() let loadManager = safeLoadManager(event.address.toHex()) - let loadVolatilityTier = safeLoadVolatilityTier(poolTypeParam, feeTierParam, tickSpreadParam, twapLengthParam) + let loadVolatilityTier = safeLoadVolatilityTier(poolTypeIdParam, feeTierParam, tickSpreadParam, twapLengthParam) let manager = loadManager.entity let volatilityTier = loadVolatilityTier.entity - volatilityTier.poolType = poolTypeParam + volatilityTier.poolTypeId = poolTypeIdParam volatilityTier.feeAmount = feeTierParam volatilityTier.tickSpread = tickSpreadParam volatilityTier.twapLength = twapLengthParam diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 8d11838c..8a44e520 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -8,9 +8,9 @@ dataSources: name: CoverPoolFactory network: arbitrum-goerli source: - address: '0xf8f75a39663e97d36da4be2882608513512f4cf0' + address: '0xc4230d3f673a44bf125c94effd1a6cc44202e0b8' abi: CoverPoolFactory - startBlock: 44921100 + startBlock: 52612037 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -31,15 +31,15 @@ dataSources: - name: ERC20NameBytes file: ./abis/ERC20NameBytes.json eventHandlers: - - event: PoolCreated(address,indexed address,address,address,indexed bytes32,uint16,int16,uint16) + - event: PoolCreated(address,indexed address,address,address,uint16,int16,uint16,indexed uint8) handler: handlePoolCreated - kind: ethereum/contract name: CoverPoolManager network: arbitrum-goerli source: - address: '0x7877a681d1290d80ed0272a920b9a5cee8fd2fac' + address: '0x87131ccc50786e387cfebcaafa522073a8e43548' abi: CoverPoolManager - startBlock: 44921100 + startBlock: 52612031 mapping: kind: ethereum/events apiVersion: 0.0.6 @@ -52,9 +52,9 @@ dataSources: - name: CoverPoolManager file: ./abis/CoverPoolManager.json eventHandlers: - - event: PoolTypeEnabled(bytes32,address,address,address) + - event: PoolTypeEnabled(uint8,bytes32,address,address,address) handler: handlePoolTypeEnabled - - event: VolatilityTierEnabled(bytes32,uint16,int16,uint16,uint128,uint16,uint16,uint16,uint16,int16,bool) + - event: VolatilityTierEnabled(uint8,uint16,int16,uint16,uint128,uint16,uint16,uint16,uint16,int16,bool) handler: handleVolatilityTierEnabled - event: FeeToTransfer(indexed address,indexed address) handler: handleFeeToTransfer @@ -68,9 +68,9 @@ dataSources: name: PoolsharkRouter network: arbitrum-goerli source: - address: '0xbe033a8649376bf3ac06cae9439c2612b582532c' + address: '0x6ccccc845849b76f3acb3affcca28a6035e41a20' abi: PoolsharkRouter - startBlock: 44996083 + startBlock: 52612031 mapping: kind: ethereum/events apiVersion: 0.0.6 diff --git a/tasks/deploy/utils/mintPosition.ts b/tasks/deploy/utils/mintPosition.ts index cddbcc2f..0c9be0fc 100644 --- a/tasks/deploy/utils/mintPosition.ts +++ b/tasks/deploy/utils/mintPosition.ts @@ -42,6 +42,21 @@ export class MintPosition { // 0x1DcF623EDf118E4B21b4C5Dc263bb735E170F9B8 // 0x9dA9409D17DeA285B078af06206941C049F692Dc // 0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E + const txn = await hre.props.poolRouter.createCoverPoolAndMint( + { + poolType: ethers.utils.formatBytes32String("PSHARK-CPROD"), + tokenIn: '0x0bfaaafa6e8fb009cd4e2bd3693f2eec2d18b053', + tokenOut: '0xEbfF7a98149b4774c9743C5D1f382305Fe5422c9', + feeTier: "1000", + tickSpread: "20", + twapLength: "12" + }, + [] + , {gasLimit: 3_000_000}) + + await txn.wait(); + + return; await validateMint({ signer: hre.props.alice, recipient: '0x65f5B282E024e3d6CaAD112e848dEc3317dB0902', diff --git a/tasks/deploy/utils/mintTokens.ts b/tasks/deploy/utils/mintTokens.ts index ef08fb9b..6570ae41 100644 --- a/tasks/deploy/utils/mintTokens.ts +++ b/tasks/deploy/utils/mintTokens.ts @@ -26,56 +26,16 @@ export class MintTokens { hre.nonce = await getNonce(hre, hre.props.alice.address) console.log(this.nonce) await this.initialSetup.readCoverPoolSetup(this.nonce) - const token0Amount = ethers.utils.parseUnits('100', await hre.props.token0.decimals()) - const token1Amount = ethers.utils.parseUnits('100', await hre.props.token1.decimals()) + const token0Amount = ethers.utils.parseUnits('1000', 6) + // const token1Amount = ethers.utils.parseUnits('1000', await hre.props.token1.decimals()) // await mintSigners20(hre.props.token0, token0Amount.mul(10), [hre.props.alice], ['0xCa2A59A26dDfd56C69e3465DF66ee2986B4B0F4a']) // await mintSigners20(hre.props.token1, token0Amount.mul(10), [hre.props.alice], ['0xCa2A59A26dDfd56C69e3465DF66ee2986B4B0F4a']) + // '0xEbfF7a98149b4774c9743C5D1f382305Fe5422c9' await hre.props.token20Batcher.mintBatch( - [hre.props.token0.address, hre.props.token1.address], + ['0xEbfF7a98149b4774c9743C5D1f382305Fe5422c9'], [ - '0xE61aBAFe6AbD96809AD2505F521E7E02ceC41764', - '0x4DD72586fFe14a915ef757b0E9a0c4019932BcA2', - '0xF7128274D8Ec9D25694E34912beAB3d4B2F50130', - '0xaaea48d32fa9c930c4a64e343325f3784bbdea05', - '0xF8C44D4c2BC63AacA7E6EcFd7763effF71A3444C', - '0x46c754738F78454690C04c6F416858aEF8B46eeE', - '0xc05ED8F3adbC1007d9d8dEbc21a721Aa951FAD50', - '0x2b7403bdB196fa5fc0e4f779600A084bE0D8422E', - '0xB0a6C408d37AeC2A58a041919F895cb24d4088f1', - '0xc600a005F9a948F9D44B4B7937a3Dfc7182b238C', - '0x693542F61eBcE90a4F37f6491CC6B0e73F0a2fB3', - '0x5FBce71b1b74d0d8511dC708ceED3250a1aBDacA', - '0x03AC7CaA058026BaaA09a1285F2a9990892b64F0', - '0x7bEeba96a6EaBfbc9ceF5C8a5CF4E28fD4223fcF', - '0xdC1ab035004Fe9D88a308eBaf6417509accb37c2', - '0x1E66DfC2FC49Ba3A323812AeCEbcf50C7b2D64A9', - '0xEADa8ABE36f600da7100eEd8912B5796B9661deC', - '0xC0E36199a29043363A373a8f02b6cc8ab40389cb', - '0x07f8eA7a012fD8d7786567523afA4873993cbB05', - '0x2bd5D10d5994a19e5E911379753A7EbC50119D5B', - '0x6F6932C87Ddc4Ea4B6c9001A8C007344430F233a', - '0x268e0d7811A711Fc0f2735cBc62C1572D05bF70A', - '0x71799D107Df028d5A5D0a11a726969E7DF71B4AB', - '0x9b327BC6616fF854Ef9f78C477F368b929d9dF2D', - '0x06887698291516f0F1A8aa51C24cE9c4DF9ae0d6', - '0xA1a26c50382f10e112328D793f76B2D84Ba87D4A', - '0xCda329d290B6E7Cf8B9B1e4faAA48Da80B6Fa2F2', - '0x465d8F5dB6aBfdAE82FE95Af82CbeC538ec5337b', - '0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E', - '0x4ED5f34cf458f0E2a42a514E1B1b846637Bd242E', - '0xaE312276Ea1B35C68617441beddc0d0Fd13c1aF2', - '0x39e9259Aa9d1bf05f5E285BE7acA91Eefe694094', - '0x34e800D1456d87A5F62B774AD98cea54a3A40048', - '0x1DcF623EDf118E4B21b4C5Dc263bb735E170F9B8', - '0xF2bE526eE1242C0e9736CF0E03d834C71389A4c7', - '0x1b5e17110463b3a2da875bc68934EB5137A4f6f4', - '0x20A13F1e2638c9784a031F291943b2A87B3f12A6', - '0x69e8e23Eb2e61BC8449e02Ced7075186DAFBcFc1', - '0x5bcb86339f2B53CA52EdAdc4C692199a78f06E71', - '0xFb408FA20c6f6DA099a7492107bC3531911896e3', - '0x4fd787803dB60816F16B121cC7c5637263f1736f', - '0xB7b60698a41e2375A700a37A46fFCEE42c202c13', - ], token0Amount.mul(10), {gasLimit: 20000000}) + '0x0e1b285d86e581d02BB54050F4CC178193F91332' + ], token0Amount.mul(1), {gasLimit: 80_000_000}) //TODO: take in address parameter // const token0Balance = await hre.props.token0.balanceOf( diff --git a/test/utils/contracts/coverpool.ts b/test/utils/contracts/coverpool.ts index eed58fc8..063fdb9c 100644 --- a/test/utils/contracts/coverpool.ts +++ b/test/utils/contracts/coverpool.ts @@ -56,12 +56,12 @@ export interface PriceBounds { } export interface CoverPoolParams { - poolType: any // bytes tokenIn: string tokenOut: string feeTier: number tickSpread: number twapLength: number + poolTypeId: number } export interface Tick { diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index d3ccc335..1d6b7576 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -33,7 +33,7 @@ export class InitialSetup { private contractDeploymentsKeys: ContractDeploymentsKeys /// DEPLOY CONFIG - private deployRouter = false + private deployRouter = true private deployTokens = false private deployPools = true private deployContracts = true @@ -50,8 +50,75 @@ export class InitialSetup { const network = SUPPORTED_NETWORKS[hre.network.name.toUpperCase()] + // await this.deployAssist.deployContractWithRetry( + // network, + // //@ts-ignore + // PoolsharkRouter__factory, + // 'poolRouter', + // [ + // '0xd0219266568eae5c1eea960e3eacf1a1e149aab0', // limitPoolFactory + // '0x4FddF20f10BfBc722B013F154762395dA5ba477f' + // ] + // ) + + // return; + + // const limitPoolFactoryAddress = ( + // await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + // { + // networkName: hre.network.name, + // objectName: 'limitPoolFactory', + // }, + // 'initialSetup' + // ) + // ).contractAddress + + // const limitPoolManagerAddress = ( + // await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + // { + // networkName: hre.network.name, + // objectName: 'limitPoolManager', + // }, + // 'initialSetup' + // ) + // ).contractAddress + + // await this.deployAssist.deployContractWithRetry( + // network, + // // @ts-ignore + // PoolsharkLimitSource__factory, + // 'poolsharkLimitSource', + // [ + // limitPoolFactoryAddress, + // limitPoolManagerAddress, + // 0 + // ] + // ) + + // const coverPoolManagerAddress = ( + // await this.contractDeploymentsJson.readContractDeploymentsJsonFile( + // { + // networkName: hre.network.name, + // objectName: 'coverPoolManager', + // }, + // 'initialSetup' + // ) + // ).contractAddress + + // await this.deployAssist.deployContractWithRetry( + // network, + // // @ts-ignore + // CoverPoolFactory__factory, + // 'coverPoolFactory', + // [ + // coverPoolManagerAddress, + // hre.props.poolsharkLimitSource.address + // ] + // ) + + // return; + if (!this.deployTokens && hre.network.name != 'hardhat') { - const token0Address = ( await this.contractDeploymentsJson.readContractDeploymentsJsonFile( { @@ -195,7 +262,7 @@ export class InitialSetup { [ limitPoolFactoryAddress, limitPoolManagerAddress, - this.constantProductString + 0 ] ) } else if (this.deployUniswapV3Source) { @@ -309,7 +376,7 @@ export class InitialSetup { CoverPoolFactory__factory, 'coverPoolFactory', [ - hre.props.coverPoolManager.address + hre.props.coverPoolManager.address, ] ) @@ -401,14 +468,13 @@ export class InitialSetup { hre.nonce += 1; } else if (this.deployPoolsharkLimitSource) { const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( - this.poolsharkString, hre.props.coverPoolImpl.address, hre.props.positionERC1155.address, - hre.props.poolsharkLimitSource.address + hre.props.poolsharkLimitSource.address, + this.poolsharkString ) await enableImplTxn.wait(); hre.nonce += 1; - console.log('impl enabled') } } @@ -419,7 +485,7 @@ export class InitialSetup { PoolsharkRouter__factory, 'poolRouter', [ - '0xbd6d010bcecc7440a72889546411e0edbb333ea2', // limitPoolFactory + '0xd0219266568eae5c1eea960e3eacf1a1e149aab0', // limitPoolFactory hre.props.coverPoolFactory.address ] ) @@ -443,7 +509,7 @@ export class InitialSetup { } const enableVolTier1 = await hre.props.coverPoolManager.enableVolatilityTier( - this.poolsharkString, + 0, 1000, // feeTier 20, // tickSpread 12, // twapLength (seconds) = ~40 arbitrum blocks @@ -456,7 +522,7 @@ export class InitialSetup { // CREATE POOL 1 poolParams1 = { - poolType: this.poolsharkString, + poolTypeId: 0, tokenIn: hre.props.token0.address, tokenOut: hre.props.token1.address, feeTier: 1000, @@ -483,7 +549,7 @@ export class InitialSetup { } const enableVolTier2 = await hre.props.coverPoolManager.enableVolatilityTier( - this.poolsharkString, + 0, 3000, // feeTier 60, // tickSpread 12, // twapLength (seconds) = ~40 arbitrum blocks @@ -496,7 +562,7 @@ export class InitialSetup { // CREATE POOL 2 console.log('pool 2') const poolParams2: CoverPoolParams = { - poolType: this.poolsharkString, + poolTypeId: 0, tokenIn: hre.props.token0.address, tokenOut: hre.props.token1.address, feeTier: 3000, @@ -523,7 +589,7 @@ export class InitialSetup { } const enableVolTier3 = await hre.props.coverPoolManager.enableVolatilityTier( - this.poolsharkString, + 0, 10000, // feeTier 200, // tickSpread 12, // twapLength (seconds) = ~40 arbitrum blocks @@ -536,7 +602,7 @@ export class InitialSetup { // CREATE POOL 3 console.log('pool 3') const poolParams3: CoverPoolParams = { - poolType: this.poolsharkString, + poolTypeId: 0, tokenIn: hre.props.token0.address, tokenOut: hre.props.token1.address, feeTier: 10000, @@ -566,7 +632,7 @@ export class InitialSetup { } const enableVolTier1 = await hre.props.coverPoolManager.enableVolatilityTier( - this.uniV3String, + 0, 500, // feeTier 20, // tickSpread 5, // twapLength (seconds) @@ -577,20 +643,21 @@ export class InitialSetup { hre.nonce += 1; const poolParams1: CoverPoolParams = { - poolType: this.uniV3String, + poolTypeId: 0, tokenIn: hre.props.token0.address, tokenOut: hre.props.token1.address, feeTier: 500, tickSpread: 20, twapLength: 5 } - + console.log('about to create pool') // create first cover pool - let createPoolTxn = await hre.props.coverPoolFactory.createCoverPool( - poolParams1 + let createPoolTxn = await hre.props.poolRouter.createCoverPoolAndMint( + poolParams1, + [] ) await createPoolTxn.wait(); - + console.log('pool created') hre.nonce += 1; [coverPoolAddress, coverPoolTokenAddress] = await hre.props.coverPoolFactory.getCoverPool( @@ -693,7 +760,7 @@ export class InitialSetup { public async createCoverPool(): Promise { const poolParams: CoverPoolParams = { - poolType: this.uniV3String, + poolTypeId: 0, tokenIn: hre.props.token0.address, tokenOut: hre.props.token1.address, feeTier: 500, From 4763e3fe3c182094e7a9bc714dbb55c452fe01df Mon Sep 17 00:00:00 2001 From: alphak3y Date: Sun, 3 Dec 2023 20:09:06 -0700 Subject: [PATCH 26/26] uint16 poolTypeId --- .../base/events/CoverPoolFactoryEvents.sol | 2 +- .../base/events/CoverPoolManagerEvents.sol | 6 +- .../interfaces/cover/ICoverPoolFactory.sol | 2 +- .../interfaces/cover/ICoverPoolManager.sol | 4 +- .../interfaces/limit/ILimitPoolFactory.sol | 2 +- .../interfaces/limit/ILimitPoolManager.sol | 2 +- .../interfaces/structs/PoolsharkStructs.sol | 2 +- .../sources/PoolsharkLimitSource.sol | 4 +- contracts/libraries/utils/SafeCast.sol | 7 + contracts/utils/CoverPoolManager.sol | 14 +- scripts/autogen/contract-deployments.json | 18 +- tasks/deploy/utils/mintTokens.ts | 157 +++++++++++++++++- test/utils/setup/initialSetup.ts | 2 +- 13 files changed, 188 insertions(+), 34 deletions(-) diff --git a/contracts/base/events/CoverPoolFactoryEvents.sol b/contracts/base/events/CoverPoolFactoryEvents.sol index d25b442a..da6ec96c 100644 --- a/contracts/base/events/CoverPoolFactoryEvents.sol +++ b/contracts/base/events/CoverPoolFactoryEvents.sol @@ -10,6 +10,6 @@ abstract contract CoverPoolFactoryEvents { uint16 fee, int16 tickSpread, uint16 twapLength, - uint8 indexed poolTypeId + uint16 indexed poolTypeId ); } diff --git a/contracts/base/events/CoverPoolManagerEvents.sol b/contracts/base/events/CoverPoolManagerEvents.sol index fe0f91e9..5b9e1d9a 100644 --- a/contracts/base/events/CoverPoolManagerEvents.sol +++ b/contracts/base/events/CoverPoolManagerEvents.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.13; abstract contract CoverPoolManagerEvents { event FactoryChanged(address indexed previousFactory, address indexed newFactory); event VolatilityTierEnabled( - uint8 poolTypeId, + uint16 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength, @@ -17,11 +17,11 @@ abstract contract CoverPoolManagerEvents { bool minLowerPriced ); event PoolTypeEnabled( - uint8 poolTypeId, bytes32 poolTypeName, address implAddress, address sourceAddress, - address factoryAddress + address factoryAddress, + uint16 poolTypeId ); event FeeToTransfer(address indexed previousFeeTo, address indexed newFeeTo); event OwnerTransfer(address indexed previousOwner, address indexed newOwner); diff --git a/contracts/interfaces/cover/ICoverPoolFactory.sol b/contracts/interfaces/cover/ICoverPoolFactory.sol index cf927542..af40484d 100644 --- a/contracts/interfaces/cover/ICoverPoolFactory.sol +++ b/contracts/interfaces/cover/ICoverPoolFactory.sol @@ -11,7 +11,7 @@ abstract contract ICoverPoolFactory is CoverPoolFactoryStorage { uint16 feeTier; int16 tickSpread; uint16 twapLength; - uint8 poolTypeId; + uint16 poolTypeId; } /** diff --git a/contracts/interfaces/cover/ICoverPoolManager.sol b/contracts/interfaces/cover/ICoverPoolManager.sol index a2503f92..a896d4b1 100644 --- a/contracts/interfaces/cover/ICoverPoolManager.sol +++ b/contracts/interfaces/cover/ICoverPoolManager.sol @@ -8,14 +8,14 @@ interface ICoverPoolManager is CoverPoolStructs { function owner() external view returns (address); function feeTo() external view returns (address); function poolTypes( - uint8 poolTypeId + uint16 poolTypeId ) external view returns ( address poolImpl, address tokenImpl, address twapImpl ); function volatilityTiers( - uint8 poolTypeId, + uint16 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength diff --git a/contracts/interfaces/limit/ILimitPoolFactory.sol b/contracts/interfaces/limit/ILimitPoolFactory.sol index 90313306..679e6f3c 100644 --- a/contracts/interfaces/limit/ILimitPoolFactory.sol +++ b/contracts/interfaces/limit/ILimitPoolFactory.sol @@ -15,7 +15,7 @@ abstract contract ILimitPoolFactory is PoolsharkStructs { address tokenIn, address tokenOut, uint16 swapFee, - uint8 poolTypeId + uint16 poolTypeId ) external view virtual returns ( address pool, address poolToken diff --git a/contracts/interfaces/limit/ILimitPoolManager.sol b/contracts/interfaces/limit/ILimitPoolManager.sol index 5bb61838..7ca7f5b2 100644 --- a/contracts/interfaces/limit/ILimitPoolManager.sol +++ b/contracts/interfaces/limit/ILimitPoolManager.sol @@ -6,7 +6,7 @@ interface ILimitPoolManager { function owner() external view returns (address); function feeTo() external view returns (address); function poolTypes( - uint8 poolType + uint16 poolType ) external view returns ( address poolImpl, address tokenImpl diff --git a/contracts/interfaces/structs/PoolsharkStructs.sol b/contracts/interfaces/structs/PoolsharkStructs.sol index 2d528dd1..565e21f4 100644 --- a/contracts/interfaces/structs/PoolsharkStructs.sol +++ b/contracts/interfaces/structs/PoolsharkStructs.sol @@ -55,7 +55,7 @@ interface PoolsharkStructs { address tokenOut; uint160 startPrice; uint16 swapFee; - uint8 poolTypeId; + uint16 poolTypeId; } struct MintLimitParams { diff --git a/contracts/libraries/sources/PoolsharkLimitSource.sol b/contracts/libraries/sources/PoolsharkLimitSource.sol index 8bc81191..13620cf0 100644 --- a/contracts/libraries/sources/PoolsharkLimitSource.sol +++ b/contracts/libraries/sources/PoolsharkLimitSource.sol @@ -15,7 +15,7 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { error WaitUntilAboveMinTick(); // poolType on limitPoolFactory - uint8 public immutable poolType; + uint16 public immutable poolType; address public immutable limitPoolFactory; address public immutable limitPoolManager; uint16 public constant oneSecond = 1000; @@ -23,7 +23,7 @@ contract PoolsharkLimitSource is ITwapSource, TwapSourceEvents { constructor( address _limitPoolFactory, address _limitPoolManager, - uint8 _poolType + uint16 _poolType ) { limitPoolFactory = _limitPoolFactory; limitPoolManager = _limitPoolManager; diff --git a/contracts/libraries/utils/SafeCast.sol b/contracts/libraries/utils/SafeCast.sol index b049ca54..b86c6526 100644 --- a/contracts/libraries/utils/SafeCast.sol +++ b/contracts/libraries/utils/SafeCast.sol @@ -64,6 +64,13 @@ library SafeCast { z = uint256(y); } + /// @notice Cast a uint256 to a uint8, revert on overflow + /// @param y The uint256 to be downcasted + /// @return z The downcasted integer, now type uint128 + function toUint16(uint256 y) internal pure returns (uint16 z) { + if((z = uint16(y)) != y) require(false, 'Uint256ToUint16:Overflow()'); + } + /// @notice Cast a uint256 to a uint8, revert on overflow /// @param y The uint256 to be downcasted /// @return z The downcasted integer, now type uint128 diff --git a/contracts/utils/CoverPoolManager.sol b/contracts/utils/CoverPoolManager.sol index c16d7b32..6e1f1fd5 100644 --- a/contracts/utils/CoverPoolManager.sol +++ b/contracts/utils/CoverPoolManager.sol @@ -22,7 +22,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { mapping(uint256 => address) internal _poolTypes; mapping(uint256 => address) internal _poolTokens; mapping(uint256 => address) internal _twapSources; - // sourceName => feeTier => tickSpread => twapLength => VolatilityTier + // poolTypeId => feeTier => tickSpread => twapLength => VolatilityTier mapping(uint256 => mapping(uint16 => mapping(int16 => mapping(uint16 => VolatilityTier)))) internal _volatilityTiers; using SafeCast for uint256; @@ -87,7 +87,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { address twapImpl_, bytes32 poolTypeName_ ) external onlyOwner { - uint8 poolTypeId_ = _poolTypeNames.length.toUint8(); + uint16 poolTypeId_ = _poolTypeNames.length.toUint16(); // valid poolType name if(poolTypeName_ == bytes32("")) require (false, 'PoolTypeNameInvalid()'); @@ -101,11 +101,11 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { _poolTokens[poolTypeId_] = tokenImpl_; _twapSources[poolTypeId_] = twapImpl_; _poolTypeNames.push(poolTypeName_); - emit PoolTypeEnabled(poolTypeId_, poolTypeName_, poolImpl_, twapImpl_, ITwapSource(twapImpl_).factory()); + emit PoolTypeEnabled(poolTypeName_, poolImpl_, twapImpl_, ITwapSource(twapImpl_).factory(), poolTypeId_); } function enableVolatilityTier( - uint8 poolTypeId, + uint16 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength, @@ -155,7 +155,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } function modifyVolatilityTierFees( - uint8 poolTypeId, + uint16 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength, @@ -219,7 +219,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } function poolTypes( - uint8 poolTypeId + uint16 poolTypeId ) external view returns ( address poolImpl, address tokenImpl, @@ -233,7 +233,7 @@ contract CoverPoolManager is ICoverPoolManager, CoverPoolManagerEvents { } function volatilityTiers( - uint8 poolTypeId, + uint16 poolTypeId, uint16 feeTier, int16 tickSpread, uint16 twapLength diff --git a/scripts/autogen/contract-deployments.json b/scripts/autogen/contract-deployments.json index fdf2c9a8..6fb6e54c 100644 --- a/scripts/autogen/contract-deployments.json +++ b/scripts/autogen/contract-deployments.json @@ -2,23 +2,23 @@ "arb_goerli": { "token0": { "contractName": "Token20", - "contractAddress": "0x0BfaaAfa6e8fB009cD4e2Bd3693F2EEC2d18B053", + "contractAddress": "0xebff7a98149b4774c9743c5d1f382305fe5422c9", "constructorArguments": [ - "Wrapped Ether", - "WETH", - 18 + "USD Coin", + "USDC", + 6 ], - "created": "2023-08-23T15:56:24.715Z" + "created": "2023-08-23T15:56:24.723Z" }, "token1": { "contractName": "Token20", - "contractAddress": "0x19beE8e887a5db5cf20A841eb4DAACBCacF14B1b", + "contractAddress": "0xefb283ef3167ca2ee9d93b201af15e2af3f6e8c7", "constructorArguments": [ - "Dai Stablecoin", - "DAI", + "Wrapped Ether", + "WETH", 18 ], - "created": "2023-08-23T15:56:24.723Z" + "created": "2023-08-23T15:56:24.715Z" }, "uniswapV3FactoryMock": { "contractName": "UniswapV3FactoryMock", diff --git a/tasks/deploy/utils/mintTokens.ts b/tasks/deploy/utils/mintTokens.ts index 6570ae41..3c0ae4ed 100644 --- a/tasks/deploy/utils/mintTokens.ts +++ b/tasks/deploy/utils/mintTokens.ts @@ -29,13 +29,160 @@ export class MintTokens { const token0Amount = ethers.utils.parseUnits('1000', 6) // const token1Amount = ethers.utils.parseUnits('1000', await hre.props.token1.decimals()) // await mintSigners20(hre.props.token0, token0Amount.mul(10), [hre.props.alice], ['0xCa2A59A26dDfd56C69e3465DF66ee2986B4B0F4a']) - // await mintSigners20(hre.props.token1, token0Amount.mul(10), [hre.props.alice], ['0xCa2A59A26dDfd56C69e3465DF66ee2986B4B0F4a']) + // await mintSigners20(hre.props.token1, token0Amount.mul(1000), [hre.props.alice], ['0xBd5db4c7D55C086107f4e9D17c4c34395D1B1E1E']) // '0xEbfF7a98149b4774c9743C5D1f382305Fe5422c9' + // '0x0BfaaAfa6e8fB009cD4e2Bd3693F2EEC2d18B053' + // '0x19beE8e887a5db5cf20A841eb4DAACBCacF14B1b' await hre.props.token20Batcher.mintBatch( - ['0xEbfF7a98149b4774c9743C5D1f382305Fe5422c9'], - [ - '0x0e1b285d86e581d02BB54050F4CC178193F91332' - ], token0Amount.mul(1), {gasLimit: 80_000_000}) + ['0xEbfF7a98149b4774c9743C5D1f382305Fe5422c9',], + [ '0x6a88027bBFC1393f1Ed19fa2A9300C3953aC8b98',// + '0xDc3cCAF326C8ff29a3177805eE87fB0251914309', + '0x07f8eA7a012fD8d7786567523afA4873993cbB05', + '0xf89d78D330434e110b0B5C27b8308d225142Da03', + '0x9B837d0C951a34d565231bED1F9c20772f80e27A', + '0x043Be57cA9A428762C68C6A13cC1266512589E7D', + '0xf46bCfa955c7380E1A9748975428E04E624D1cC9', + '0x106E06bD8dF139ac4A105fC0d6277fb68b39FA3a', + '0x7b042c22A39c651Fb6e516928cD5F5179cD9d4DB', + '0x63440DE92C437967aA08EC0Dd51850FF7FD94aff', + '0xc689A1cf9Ca0D3db7713345D42BEb4B132d8aE32', + '0x8106C8c338B0D86a78Ae9011Ba717e8eaa3Ae9d4', + '0x6b2f58614a8d43829e210e17b1F504EFe0d2eD17', // + '0xa3f9bd4F103F600E5886eE80708372ECC646a036', + '0x44c614dE52a51E6eA0360906E55d717Fa8C5eB3E', + '0x671E83971F543fa4C3E533df4b55838c6aeb2c45', + '0x1846Fb3E55069d144715709dF1C5433E780f9053', + '0x547814d5c60c72ba8B55955bc8A046536FbD77eE', + '0x2e4f0e9240E9240a54d352e90F4CB614bB18C6f7', + '0x45d993393f7B3Fe781935e1155118C7f830d4415', + '0x0c1d5aa8930ff99d735bb5fc1265d3108d09729f', + '0x2eb6896CE4F45192140b5321F61D11E9eDA82F2B', + '0x8847EBaaf29A18396e49191602f8d8D141b98aa7', + '0x664Fae4E52981d3eb5f0E2BDa615A0E4B057F0DE', + '0x2bB4a1Dc852b02eE3a3446cA624aD343b6eEEaA6', + '0x64d196e9cc62ec70ca0379dfc38ccbff344dd38b', + '0x410360b9dCA14DF852Fe2818b57aD4e9d2b7Bc45', + '0x6fCD3561C603cc72b15357caF59C0e579f5C1B03', + '0xC48520Bdf117d951E495225B77EB38734Be96d94', + '0x24E1921f04D3c0AA707bcd588225ccFe1C53493d', + '0x8F76c82F572D97C7b7D773dB62E64b4f0b61B253', + '0x5125889AaB1Ab5dBDD399eFe7f5734e44Db07f56', + '0x860732d54034CdE25E9Dd579E7e36184F04f4548', + '0xe52bA6F91811439854b85CE79a9C65e8911c13aC', + '0xd435231Bed0D4DE8541D94Ec93e1E094Ae633b72', + '0x4dA792b5058F59162E1B619749a0Ce4E984D4841', + '0x547814d5c60c72ba8B55955bc8A046536FbD77eE', + '0xCa9ba74eE20917211ef646AC51ACcc287F27538b', + '0x9AE4F4a3efea60a1d73cb32476A8697E057473BB', + '0x33275f4B8de6571e7650305CbCfCbeeba5fcF4B5', + '0x71ac680233DFA6d8a10600D077Df9bE89e19aaC7', + '0xc63671075D54f73f47fb437528d8643b3D7701C4', + '0xA99DA68da256437215264005605E125973E793Ad', + '0x000f4432a40560bBFf1b581a8b7AdEd8dab80026', + '0x01d0C05F9a9b74CEBF8Fcf2BBfa2257A50708929', + '0x000F38c11De32dF3BFD065c37Eec99a00a42546f', + '0x4b3a832dB69d467819267C04cc632f7636C05Dcc', + '0x315fFf7C53D75737D5a9F5165beD76ca1f689c73', + '0x8bC0dbe3B09bCb20470763143352cB8Cb0238181', + '0x34d6C8F98846e773177519cB59C197caD17A12C9', + '0x148F4e63611be189601f1F1555d4C79e8cEBddC8', + '0x9A810B1cEaF50759693c288D5DB485938663A462', + '0xad2429c165eE3c9E282FF5c9E41045eBe2Aa9044', + '0x01F8B9484B95f9e118a5b0593E513bDba47Ad7Da', + '0x74F0bD24d03F8D444fCa820Fa022964a0eB56eb8', + '0x84533181eb327EbfCcFd2439e8C4966d7260be5b', + '0xAd50B95c9305488dC4444Deb39C6a102Df59D7AE', + '0xcd34746eAc14E60F666E3cEE9d7991D045bBf761', + '0x57FC1299a7FE49882E9593BA79a6E650c2e3F9D0', + '0x72E5d8D85Db805C275561D9FCE16C11002c676FE', + '0x72E5d8D85Db805C275561D9FCE16C11002c676FE', + '0x42a831A7279C8De5DEea822627E8991b904653a9', + '0xe08583e015f358ce59489DEba17B9774833C9F8E', + '0x287c07066A0430223a7a02D6695F067dF518Ba5e', + '0x07d095Ff9fCF13e086ab6D44309733E95DAa28c3', + '0xb9AAd7fb7D0854a4bD55Cca2c8c606fDA499f7B9', + '0x88c736cCee4cf398297a764f2fe2aAF7e6937D7b', + '0x8c952cc18969129A1C67297332A0B6558eB0bFEc', + '0x9eFEb581C020Fc746C1df51d8d2e829C03aA6674', + '0x1b4C396f3F25b86c33FFDe1E7F6afCAeBDD3ddF4', + '0x5881d9BfFf787C8655A9b7F3484aE1a6f7a966E8', + '0x5df12FaD79F630DC7c64D3BD2C00673F4ef36682', + '0x7b042c22A39c651Fb6e516928cD5F5179cD9d4DB', + '0xc689A1cf9Ca0D3db7713345D42BEb4B132d8aE32', + '0x720B451a9c21908DeDA19D92E55895847Bec043d', + '0x8c90e009A6567eA39fE1443Ae3aB03c0EB80Cc11', + '0x659835D141416Cb9c868Ae99486A58Ee214140cD', + '0xBe317BcadDFD00106977e17420427BC8D0101F05', + '0x10C292a9B4b0D085e71590B67F99408a38F3e40a', + '0x1DfE222F72B87Ca8bF2e1414c3B2F952B0F73B62', + '0x8522442BE81c98F18C63Ab6446f9De11481F4F92', + '0xc195F2726352165A1C628cd08833aaF837d76924', + '0x10D8614a4De958A5831F6b015604864E30252a30', + '0x943f12dF9afA19DB3b67888aBd9EaE4465eb7c8d', + '0xF23BE978a2Fa4d91D6E3A9E62120dD069cF1c733', + '0x6d3E6D2f1546dBF6E691b17Af425c6124D1Dc374', + '0x62f1511269AAc24e79BF6F5172ca661711C7dC23', + '0x8446DfE7f0c8d5Db618E8264cC6ed15b7a91c66b', + '0x465d8F5dB6aBfdAE82FE95Af82CbeC538ec5337b', + '0x7A8583Db42EF87E618a4879b18a58FA62E462bF4', + '0x69978da94A19E96C4DD44bc13b693CF83057B9a1', + '0xF40efeF7a98502B33c1BeE076c886795BAbcA02C', + '0xe1E281bC6a1B6b12B775d8b08A829c4ecCeD4B35', + '0x734ef1765588150677F26F4Ebb43d7d3326A9Eaa', + '0x503596528878b9603534c8a43363FE4ea5A89262', + '0xc4735b87dFb6c7cC3651677651E4bF139B27Cc59', + '0x8F90628fBF475dEd16a83071eDCD1D21B764017D', + '0x85B2Ca334f2E6dC60428ce663575aA96F81F7256', + '0x4692C5fE408879c96f0d94D1814c690434f550c0', + '0x573aDaD94A5d502E14A772488Dea8FBf30ECd47E', + '0x515b754d8b51E08F7a4BB0d804C047d63fa4FD27', + '0x8B2B8601124CDFa264558169473A2c12f2ddaa50', + '0x010fFce4B90d552Ec754B7B37DBA9bF49C1Ad3e9', + '0xAe14Daa3Ec60a5EC30c83ffC3f3f3d7553D7973D', + '0x478e78583A27972845971fA1bf1e43fBBF14d7F0', + '0x35CB5ABD6d3B8911291B06477a61691FaA407265', + '0xe8D79Ded7c683Edbe868aC5c7EC3016B9687Db02', + '0x2cFDFD87eF82ebAEB6603a1124de410ADf72bE65', + '0x28581D2854fBc981DBC9eA109105D73A70c527E7', + '0xAf61B0f9756163709A129F60c2192876365D13D5', + '0xd516ACf12120a0Aa34CA3D835F688dA9195BAbc3', + '0x0A01715CF0D6728e16f753F61d447eE580e35558', + '0xaE0BF45abf324f15E00bEe2D5b5D8e7612e50a32', + '0xa303Fe338F7E412d90ff27BA3FCe1903B0c885Bc', + '0x54372fd91473e0F6F8507A955CD45De9B9D740D5', + '0x0874827c91c24d337854fB3e8c701088Cd9881d3', + '0x6DDe50a4ABF87193C2aba53153Ef1734C5A192BA', + '0x33DdF6B07804ECf8BC378A4B197002F02078E7EB', + '0x7C058598da8998599CD5477B1646dE0Fc5839049', + '0x1049c923fF19FA5088d2466F942A1dAa79D03d85', + '0x1d75Ccf1E886a203c8f84e0A7b68475CF8bD2c6a', + '0xc92eF6b1426Be8fCB048831ab0555e1577a16E28', + '0xED5A42f58d5dBDE7e0cC122416A3540De6ccc6C3', + '0x8A8C879D39A74fCE0593714956bB7Ed048A5c1BF', + '0x0949C8d6aa7aD809ea08216f327ecF8a3C6B6518', + '0x8bC0dbe3B09bCb20470763143352cB8Cb0238181', + '0x8bC0dbe3B09bCb20470763143352cB8Cb0238181', + '0xa1e0699E73C1523a788bf2058Be68196c933D1E1', + '0x14d1a955e2467ee8D04d747EeD647c7966E6AC06', + '0x7C1c510878768Ab7A37dF92411Dee3244967F5c6', + '0xa8EB650d195B8c271d16Bdd80DFa0dC54A0FC27A', + '0x5320A72B8EEcDa26be1eE9E0245d39D53979D1a0', + '0x69cE139860Bb9162DC3356d48495Cbf90299F5EF', + '0x2d209040c031d4e2D4d9cb4D3aabf18F52260AB0', + '0x507bFAaEDB3394d0c5aeE8170ebce209057A6Cce', + '0x05Aff7939E8072ab2eA03306A099EFF2516aFe6F', + '0x4236c9f574057c6530067e1FDD9AC6c08c8287fd', + '0x1D97170895cf2a7788DF357e67071beA821b296C', + '0x59A337056D8f5FCbB900d8Ad3268002a11587F1d', + '0x004A014984904D48fE450db8dEB9289aC27F427D', + '0xABBb979bAe05506E018FAA1e7aa12582C00988A4', + '0x814101E949f2690Ee7c5BEc7e7817C1A72bf09c4', + '0xc13E2dB13C132c05895997a05A6b0474543961bE', + '0xF671a0945586c3bF398f5a0bF5Ade9436DC89B1f', + '0x9FBC318fb93821b36dE5b0344bA1E522a5d5D7Ba', + '0x416cE32e56bEA5Df1D5B1D81aA1761C7433bC6B7', + '0x6b2f58614a8d43829e210e17b1F504EFe0d2eD17', + '0xe08583e015f358ce59489DEba17B9774833C9F8E',], token0Amount.mul(1), {gasLimit: 80_000_000}) //TODO: take in address parameter // const token0Balance = await hre.props.token0.balanceOf( diff --git a/test/utils/setup/initialSetup.ts b/test/utils/setup/initialSetup.ts index 1d6b7576..e84e4770 100644 --- a/test/utils/setup/initialSetup.ts +++ b/test/utils/setup/initialSetup.ts @@ -468,7 +468,7 @@ export class InitialSetup { hre.nonce += 1; } else if (this.deployPoolsharkLimitSource) { const enableImplTxn = await hre.props.coverPoolManager.enablePoolType( - hre.props.coverPoolImpl.address, + hre.props.coverPoolImpl.addre6ss, hre.props.positionERC1155.address, hre.props.poolsharkLimitSource.address, this.poolsharkString