Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4ebc0bf
implement mint cover callback
alphak3y Sep 22, 2023
71f9148
refactor interfaces
alphak3y Sep 23, 2023
ced897c
update router
alphak3y Sep 23, 2023
8157d0a
update poolshark limit sampling; split deployment for local and testnet
alphak3y Sep 23, 2023
8487b7b
cleanup initial setup
alphak3y Sep 23, 2023
9cd474e
use poolshark limit for testnet
alphak3y Sep 23, 2023
cd97b07
arbitrum goerli deployment using poolshark source
alphak3y Sep 23, 2023
78c88ef
refactor initial twap source initialization sequence
alphak3y Sep 24, 2023
535a4d9
refactor uniswap v3 source to emit init event
alphak3y Sep 24, 2023
69d9607
cleanup manager checks
alphak3y Sep 24, 2023
93a439f
cleanup manager checks
alphak3y Sep 24, 2023
2a30ed8
deployment process text file; refactor sample length to count
alphak3y Sep 24, 2023
1b41d35
deploy and mint cover position
alphak3y Sep 24, 2023
88653b4
save position addreses
alphak3y Sep 24, 2023
5b0102e
track sample updates from twap source
alphak3y Sep 24, 2023
de30244
updated subgraph
alphak3y Sep 25, 2023
d3c9754
utf-8 string for poolType
alphak3y Sep 27, 2023
fb28297
deploy subgraph command
alphak3y Sep 27, 2023
56e6805
epochLast0 and epochLast1
alphak3y Sep 28, 2023
2c0021b
update multiquote call
alphak3y Sep 30, 2023
055c002
avoid stack too deep for encodeCover
alphak3y Sep 30, 2023
44c685d
add syncLatestTick contract call
alphak3y Oct 1, 2023
44d9806
latest subgraph build
alphak3y Oct 2, 2023
f2f9f10
subgraph modifications for syncLatestTick call
alphak3y Oct 2, 2023
c11f97f
add synclatesttick to factory
alphak3y Nov 3, 2023
4763e3f
uint16 poolTypeId
alphak3y Dec 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 42 additions & 8 deletions contracts/CoverPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ contract CoverPool is
_;
}

modifier factoryOnly() {
_onlyFactory();
_;
}

modifier canoncialOnly() {
_onlyCanoncialClones();
_;
Expand All @@ -42,8 +47,20 @@ contract CoverPool is
factory = factory_;
}

function initialize()
external
{
Ticks.initialize(
tickMap,
pool0,
pool1,
globalState,
ICoverPool(address(this)).immutables()
);
}

function mint(
MintParams memory params
MintCoverParams memory params
) external override
nonReentrant(globalState)
canoncialOnly
Expand Down Expand Up @@ -83,7 +100,7 @@ contract CoverPool is
}

function burn(
BurnParams memory params
BurnCoverParams memory params
) external override
nonReentrant(globalState)
canoncialOnly
Expand Down Expand Up @@ -190,7 +207,7 @@ contract CoverPool is
}

function snapshot(
SnapshotParams memory params
SnapshotCoverParams memory params
) external view override returns (
CoverPosition memory
) {
Expand Down Expand Up @@ -256,13 +273,24 @@ contract CoverPool is
tickSpread(),
twapLength(),
auctionLength(),
blockTime(),
sampleInterval(),
token0Decimals(),
token1Decimals(),
minAmountLowerPriced()
);
}

function syncLatestTick() external view returns (int24) {
return Epochs.syncLatestTick(
globalState,
immutables()
);
}

function syncGlobalState() external view returns (GlobalState memory) {
return globalState;
}

function priceBounds(
int16 tickSpacing
) external pure returns (uint160, uint160) {
Expand Down Expand Up @@ -302,24 +330,30 @@ 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,
constants.tickSpread,
constants.twapLength,
constants.auctionLength
);
bytes memory value2 = abi.encodePacked(
constants.blockTime,
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 {
if (msg.sender != owner()) revert OwnerOnly();
}

function _onlyFactory() private view {
if (msg.sender != factory) revert FactoryOnly();
}
}
154 changes: 100 additions & 54 deletions contracts/CoverPoolFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -55,37 +55,40 @@ 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.blockTime = config.blockTime;
constants.sampleInterval = config.sampleInterval;
constants.minPositionWidth = config.minPositionWidth;
constants.minAmountLowerPriced = config.minAmountLowerPriced;
}
// 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(
Expand Down Expand Up @@ -120,6 +123,9 @@ contract CoverPoolFactory is
data: encodeCover(constants)
});

// intialize twap source
ICoverPool(pool).initialize();

poolToken = constants.poolToken;

coverPools[key] = pool;
Expand All @@ -129,45 +135,13 @@ contract CoverPoolFactory is
constants.inputPool,
constants.token0,
constants.token1,
params.poolType,
params.feeTier,
params.tickSpread,
params.twapLength
params.twapLength,
params.poolTypeId
);
}

function createCoverPoolAndMint(
CoverPoolParams memory params,
ICoverPool.MintParams[] 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 (
Expand All @@ -182,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
Expand All @@ -207,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) {
Expand All @@ -218,20 +262,22 @@ 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,
constants.tickSpread,
constants.twapLength,
constants.auctionLength
);
bytes memory value2 = abi.encodePacked(
constants.blockTime,
bytes memory value3 = abi.encodePacked(
constants.sampleInterval,
constants.token0Decimals,
constants.token1Decimals,
constants.minAmountLowerPriced
);
return abi.encodePacked(value1, value2);
return abi.encodePacked(value1, value2, value3);
}
}
2 changes: 1 addition & 1 deletion contracts/base/events/CoverPoolEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
pragma solidity 0.8.13;

abstract contract CoverPoolEvents {
event Mint(
event Mint(
address indexed to,
int24 lower,
int24 upper,
Expand Down
4 changes: 2 additions & 2 deletions contracts/base/events/CoverPoolFactoryEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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,
uint16 indexed poolTypeId
);
}
Loading