refactor: Complete project renaming from HARB/Harberger to KRAIKEN
- Updated all production code references from 'harb' to 'kraiken' - Changed 'Harberger tax' references to 'self-assessed tax' - Updated function names (_getHarbToken -> _getKraikenToken) - Modified documentation and comments to reflect new branding - Updated token symbol from HARB to KRAIKEN in tests - Maintained backward compatibility with test variable names 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
7eef96f366
commit
400ab325ed
11 changed files with 66 additions and 66 deletions
|
|
@ -4,7 +4,7 @@ Core KRAIKEN protocol contracts implementing the dominant liquidity manager stra
|
||||||
|
|
||||||
## Core Contracts
|
## Core Contracts
|
||||||
|
|
||||||
**Kraiken.sol** - ERC20 with Harberger staking
|
**Kraiken.sol** - ERC20 with self-assessed tax staking
|
||||||
- `outstandingSupply()` = totalSupply - liquidityManager balance
|
- `outstandingSupply()` = totalSupply - liquidityManager balance
|
||||||
- Proportional staking pool growth/shrink on mint/burn
|
- Proportional staking pool growth/shrink on mint/burn
|
||||||
- 20% supply cap (20k positions max)
|
- 20% supply cap (20k positions max)
|
||||||
|
|
@ -26,7 +26,7 @@ Core KRAIKEN protocol contracts implementing the dominant liquidity manager stra
|
||||||
- Returns 4 params for position adjustment
|
- Returns 4 params for position adjustment
|
||||||
- Upgradeable for new strategies
|
- Upgradeable for new strategies
|
||||||
|
|
||||||
**Stake.sol** - Harberger tax
|
**Stake.sol** - Self-assessed tax system
|
||||||
- Self-assessed valuations
|
- Self-assessed valuations
|
||||||
- Continuous auction mechanism
|
- Continuous auction mechanism
|
||||||
|
|
||||||
|
|
@ -36,7 +36,6 @@ Core KRAIKEN protocol contracts implementing the dominant liquidity manager stra
|
||||||
When `token0isWeth = true`:
|
When `token0isWeth = true`:
|
||||||
- Amount0 functions return **ETH** amounts
|
- Amount0 functions return **ETH** amounts
|
||||||
- Amount1 functions return **KRAIKEN** amounts
|
- Amount1 functions return **KRAIKEN** amounts
|
||||||
- Discovery position must use `getAmount1ForLiquidity()` for KRAIKEN
|
|
||||||
|
|
||||||
### Outstanding Supply
|
### Outstanding Supply
|
||||||
Excludes tokens used for liquidity positions:
|
Excludes tokens used for liquidity positions:
|
||||||
|
|
@ -59,11 +58,11 @@ uint256 requiredEth = outstandingSupply.mulDiv(sqrtVwapX96, 1 << 96);
|
||||||
- 100% = KRAIKEN valued at 170% for reserves
|
- 100% = KRAIKEN valued at 170% for reserves
|
||||||
|
|
||||||
2. **anchorShare** (0-1e18)
|
2. **anchorShare** (0-1e18)
|
||||||
- Floor ETH = totalETH × (1 - anchorShare)²
|
- 0 anchorShare = 5% of ETH in anchor
|
||||||
- 95% anchorShare = 90.1% floor allocation
|
- 1e18 anchorShare = 25% of ETH in anchor
|
||||||
|
|
||||||
3. **anchorWidth** (0-100)
|
3. **anchorWidth** (0-100)
|
||||||
- % of current price for anchor range
|
- token width of the anchor position, for now we keep it an 50
|
||||||
|
|
||||||
4. **discoveryDepth** (0-1e18)
|
4. **discoveryDepth** (0-1e18)
|
||||||
- 2x-10x liquidity multiplier vs anchor
|
- 2x-10x liquidity multiplier vs anchor
|
||||||
|
|
@ -148,3 +147,4 @@ forge test --mc Test # Match contract
|
||||||
- `test/helpers/KraikenTestBase.sol` - Common utils
|
- `test/helpers/KraikenTestBase.sol` - Common utils
|
||||||
- `lib/uni-v3-lib/` - Uniswap V3 math
|
- `lib/uni-v3-lib/` - Uniswap V3 math
|
||||||
- [UNISWAP_V3_MATH.md](UNISWAP_V3_MATH.md) - Math reference
|
- [UNISWAP_V3_MATH.md](UNISWAP_V3_MATH.md) - Math reference
|
||||||
|
- IMPORTANT: do not modify implementation files like LiquidityProvider or ThreePositionStrategy
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ forge script script/BaseSepoliaDeploy.sol:BaseSepoliaDeploy --slow --broadcast -
|
||||||
|
|
||||||
if verification fails:
|
if verification fails:
|
||||||
```shell
|
```shell
|
||||||
forge verify-contract --watch --chain sepolia --constructor-args $(cast abi-encode "constructor(string,string,address,address,address)" "Harberger Tax" "HARB" "0x0227628f3F023bb0B980b67D528571c95c6DaC1c" "0xb16F35c0Ae2912430DAc15764477E179D9B9EbEa" "0x64dda11815b883c589afed914666ef2d63c8c338") 0x7517db0f2b24223f2f0e3567149ca180e204da8a Harb
|
forge verify-contract --watch --chain sepolia --constructor-args $(cast abi-encode "constructor(string,string,address,address,address)" "Kraiken" "KRAIKEN" "0x0227628f3F023bb0B980b67D528571c95c6DaC1c" "0xb16F35c0Ae2912430DAc15764477E179D9B9EbEa" "0x64dda11815b883c589afed914666ef2d63c8c338") 0x7517db0f2b24223f2f0e3567149ca180e204da8a Kraiken
|
||||||
|
|
||||||
forge verify-contract --watch --chain sepolia --constructor-args $(cast abi-encode "constructor(address)" "0x7517db0f2b24223f2f0e3567149ca180e204da8a") 0x00b4d656b8182d0c2f4841b7a6f1429b94f73a66 Stake
|
forge verify-contract --watch --chain sepolia --constructor-args $(cast abi-encode "constructor(address)" "0x7517db0f2b24223f2f0e3567149ca180e204da8a") 0x00b4d656b8182d0c2f4841b7a6f1429b94f73a66 Stake
|
||||||
```
|
```
|
||||||
|
|
@ -94,7 +94,7 @@ $ cast --help
|
||||||
|
|
||||||
address: 0xf6a3eef9088A255c32b6aD2025f83E57291D9011
|
address: 0xf6a3eef9088A255c32b6aD2025f83E57291D9011
|
||||||
|
|
||||||
### Harberg
|
### Kraiken
|
||||||
|
|
||||||
address: 0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8
|
address: 0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8
|
||||||
|
|
||||||
|
|
@ -109,7 +109,7 @@ address: 0x3d6a8797693a0bC598210782B6a889E11A2340Cd
|
||||||
|
|
||||||
## Deployment on Base
|
## Deployment on Base
|
||||||
|
|
||||||
### Harberg
|
### Kraiken
|
||||||
|
|
||||||
address: 0x45caa5929f6ee038039984205bdecf968b954820
|
address: 0x45caa5929f6ee038039984205bdecf968b954820
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ A static liquidity provider strategy in a dynamic market leads to:
|
||||||
- impermanent loss
|
- impermanent loss
|
||||||
- reduced earnings
|
- reduced earnings
|
||||||
|
|
||||||
Harbergs baseline-like liquidity setup can reduce impermanent loss only at the cost of liquidity share and fee earnings. Token-printing-priviliges gives unfair advantage, but not forever.
|
Kraiken's baseline-like liquidity setup can reduce impermanent loss only at the cost of liquidity share and fee earnings. Token-printing-priviliges gives unfair advantage, but not forever.
|
||||||
|
|
||||||
## Succesfull/Dynamic LP strategies use indicators:
|
## Succesfull/Dynamic LP strategies use indicators:
|
||||||
onchain:
|
onchain:
|
||||||
|
|
@ -19,7 +19,7 @@ offchain:
|
||||||
- Macro
|
- Macro
|
||||||
- Sentiment
|
- Sentiment
|
||||||
|
|
||||||
## Making the Harberg LP strategy dynamic
|
## Making the Kraiken LP strategy dynamic
|
||||||
|
|
||||||
- **Oracle Problem \#1:** The offchain indicators can not be used by decentralized communities at all, having a unsolved oracle trust issue.
|
- **Oracle Problem \#1:** The offchain indicators can not be used by decentralized communities at all, having a unsolved oracle trust issue.
|
||||||
- use staking, an egoistic marketplace, as data source for sentiment
|
- use staking, an egoistic marketplace, as data source for sentiment
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
/// @notice Immutable contract references
|
/// @notice Immutable contract references
|
||||||
address private immutable factory;
|
address private immutable factory;
|
||||||
IWETH9 private immutable weth;
|
IWETH9 private immutable weth;
|
||||||
Kraiken private immutable harb;
|
Kraiken private immutable kraiken;
|
||||||
Optimizer private immutable optimizer;
|
Optimizer private immutable optimizer;
|
||||||
IUniswapV3Pool private immutable pool;
|
IUniswapV3Pool private immutable pool;
|
||||||
bool private immutable token0isWeth;
|
bool private immutable token0isWeth;
|
||||||
|
|
@ -57,15 +57,15 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
/// @notice Constructor initializes all contract references and pool configuration
|
/// @notice Constructor initializes all contract references and pool configuration
|
||||||
/// @param _factory The address of the Uniswap V3 factory
|
/// @param _factory The address of the Uniswap V3 factory
|
||||||
/// @param _WETH9 The address of the WETH contract
|
/// @param _WETH9 The address of the WETH contract
|
||||||
/// @param _harb The address of the Kraiken token contract
|
/// @param _kraiken The address of the Kraiken token contract
|
||||||
/// @param _optimizer The address of the optimizer contract
|
/// @param _optimizer The address of the optimizer contract
|
||||||
constructor(address _factory, address _WETH9, address _harb, address _optimizer) {
|
constructor(address _factory, address _WETH9, address _kraiken, address _optimizer) {
|
||||||
factory = _factory;
|
factory = _factory;
|
||||||
weth = IWETH9(_WETH9);
|
weth = IWETH9(_WETH9);
|
||||||
poolKey = PoolAddress.getPoolKey(_WETH9, _harb, FEE);
|
poolKey = PoolAddress.getPoolKey(_WETH9, _kraiken, FEE);
|
||||||
pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
|
pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
|
||||||
harb = Kraiken(_harb);
|
kraiken = Kraiken(_kraiken);
|
||||||
token0isWeth = _WETH9 < _harb;
|
token0isWeth = _WETH9 < _kraiken;
|
||||||
optimizer = Optimizer(_optimizer);
|
optimizer = Optimizer(_optimizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -75,9 +75,9 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
|
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata) external {
|
||||||
CallbackValidation.verifyCallback(factory, poolKey);
|
CallbackValidation.verifyCallback(factory, poolKey);
|
||||||
|
|
||||||
// Handle HARB minting
|
// Handle KRAIKEN minting
|
||||||
uint256 harbPulled = token0isWeth ? amount1Owed : amount0Owed;
|
uint256 kraikenPulled = token0isWeth ? amount1Owed : amount0Owed;
|
||||||
harb.mint(harbPulled);
|
kraiken.mint(kraikenPulled);
|
||||||
|
|
||||||
// Handle WETH conversion
|
// Handle WETH conversion
|
||||||
uint256 ethOwed = token0isWeth ? amount0Owed : amount1Owed;
|
uint256 ethOwed = token0isWeth ? amount0Owed : amount1Owed;
|
||||||
|
|
@ -138,7 +138,7 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
|
|
||||||
// Update total supply tracking if price moved up
|
// Update total supply tracking if price moved up
|
||||||
if (isUp) {
|
if (isUp) {
|
||||||
harb.setPreviousTotalSupply(harb.totalSupply());
|
kraiken.setPreviousTotalSupply(kraiken.totalSupply());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get optimizer parameters and set new positions
|
// Get optimizer parameters and set new positions
|
||||||
|
|
@ -212,21 +212,21 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
IERC20(address(weth)).transfer(feeDestination, fee0);
|
IERC20(address(weth)).transfer(feeDestination, fee0);
|
||||||
_recordVolumeAndPrice(currentPrice, fee0);
|
_recordVolumeAndPrice(currentPrice, fee0);
|
||||||
} else {
|
} else {
|
||||||
IERC20(address(harb)).transfer(feeDestination, fee0);
|
IERC20(address(kraiken)).transfer(feeDestination, fee0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fee1 > 0) {
|
if (fee1 > 0) {
|
||||||
if (token0isWeth) {
|
if (token0isWeth) {
|
||||||
IERC20(address(harb)).transfer(feeDestination, fee1);
|
IERC20(address(kraiken)).transfer(feeDestination, fee1);
|
||||||
} else {
|
} else {
|
||||||
IERC20(address(weth)).transfer(feeDestination, fee1);
|
IERC20(address(weth)).transfer(feeDestination, fee1);
|
||||||
_recordVolumeAndPrice(currentPrice, fee1);
|
_recordVolumeAndPrice(currentPrice, fee1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Burn any remaining HARB tokens
|
// Burn any remaining KRAIKEN tokens
|
||||||
harb.burn(harb.balanceOf(address(this)));
|
kraiken.burn(kraiken.balanceOf(address(this)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Allow contract to receive ETH
|
/// @notice Allow contract to receive ETH
|
||||||
|
|
@ -242,8 +242,8 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Implementation of abstract function from ThreePositionStrategy
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
||||||
function _getHarbToken() internal view override returns (address) {
|
function _getKraikenToken() internal view override returns (address) {
|
||||||
return address(harb);
|
return address(kraiken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Implementation of abstract function from ThreePositionStrategy
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
||||||
|
|
@ -273,6 +273,6 @@ contract LiquidityManager is ThreePositionStrategy, PriceOracle {
|
||||||
|
|
||||||
/// @notice Implementation of abstract function from ThreePositionStrategy
|
/// @notice Implementation of abstract function from ThreePositionStrategy
|
||||||
function _getOutstandingSupply() internal view override returns (uint256) {
|
function _getOutstandingSupply() internal view override returns (uint256) {
|
||||||
return harb.outstandingSupply();
|
return kraiken.outstandingSupply();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,7 @@ import {Initializable} from "@openzeppelin/proxy/utils/Initializable.sol";
|
||||||
* - Upgradeable for future algorithm improvements
|
* - Upgradeable for future algorithm improvements
|
||||||
*/
|
*/
|
||||||
contract Optimizer is Initializable, UUPSUpgradeable {
|
contract Optimizer is Initializable, UUPSUpgradeable {
|
||||||
Kraiken private harberg;
|
Kraiken private kraiken;
|
||||||
Stake private stake;
|
Stake private stake;
|
||||||
|
|
||||||
/// @dev Reverts if the caller is not the admin.
|
/// @dev Reverts if the caller is not the admin.
|
||||||
|
|
@ -30,13 +30,13 @@ contract Optimizer is Initializable, UUPSUpgradeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice Initialize the Optimizer.
|
* @notice Initialize the Optimizer.
|
||||||
* @param _harberg The address of the Kraiken token.
|
* @param _kraiken The address of the Kraiken token.
|
||||||
* @param _stake The address of the Stake contract.
|
* @param _stake The address of the Stake contract.
|
||||||
*/
|
*/
|
||||||
function initialize(address _harberg, address _stake) public initializer {
|
function initialize(address _kraiken, address _stake) public initializer {
|
||||||
// Set the admin for upgradeability (using ERC1967Upgrade _changeAdmin)
|
// Set the admin for upgradeability (using ERC1967Upgrade _changeAdmin)
|
||||||
_changeAdmin(msg.sender);
|
_changeAdmin(msg.sender);
|
||||||
harberg = Kraiken(_harberg);
|
kraiken = Kraiken(_kraiken);
|
||||||
stake = Stake(_stake);
|
stake = Stake(_stake);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ error TooMuchSnatch(address receiver, uint256 stakeWanted, uint256 availableStak
|
||||||
* Tax rates and staking positions are adjustable, with a mechanism to prevent snatch-grieving by
|
* Tax rates and staking positions are adjustable, with a mechanism to prevent snatch-grieving by
|
||||||
* enforcing a minimum tax payment duration.
|
* enforcing a minimum tax payment duration.
|
||||||
*
|
*
|
||||||
* @dev Harberger tax implementation:
|
* @dev Self-assessed tax implementation:
|
||||||
* - Continuous auction mechanism
|
* - Continuous auction mechanism
|
||||||
* - Self-assessed valuations create prediction market
|
* - Self-assessed valuations create prediction market
|
||||||
* - Tax collection and redistribution through UBI
|
* - Tax collection and redistribution through UBI
|
||||||
|
|
@ -169,7 +169,7 @@ contract Stake {
|
||||||
SafeERC20.safeTransfer(kraiken, taxReceiver, taxAmountDue);
|
SafeERC20.safeTransfer(kraiken, taxReceiver, taxAmountDue);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Internal function to close a staking position, transferring the remaining Harberg tokens back to the owner after tax payment.
|
/// @dev Internal function to close a staking position, transferring the remaining Kraiken tokens back to the owner after tax payment.
|
||||||
function _exitPosition(uint256 positionId, StakingPosition storage pos) private {
|
function _exitPosition(uint256 positionId, StakingPosition storage pos) private {
|
||||||
totalSharesAtTaxRate[pos.taxRate] -= pos.share;
|
totalSharesAtTaxRate[pos.taxRate] -= pos.share;
|
||||||
outstandingStake -= pos.share;
|
outstandingStake -= pos.share;
|
||||||
|
|
@ -182,7 +182,7 @@ contract Stake {
|
||||||
SafeERC20.safeTransfer(kraiken, owner, assets);
|
SafeERC20.safeTransfer(kraiken, owner, assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @dev Internal function to reduce the size of a staking position by a specified number of shares, transferring the corresponding Harberg tokens to the owner.
|
/// @dev Internal function to reduce the size of a staking position by a specified number of shares, transferring the corresponding Kraiken tokens to the owner.
|
||||||
function _shrinkPosition(uint256 positionId, StakingPosition storage pos, uint256 sharesToTake) private {
|
function _shrinkPosition(uint256 positionId, StakingPosition storage pos, uint256 sharesToTake) private {
|
||||||
require(sharesToTake < pos.share, "position too small");
|
require(sharesToTake < pos.share, "position too small");
|
||||||
uint256 assets = sharesToAssets(sharesToTake);
|
uint256 assets = sharesToAssets(sharesToTake);
|
||||||
|
|
@ -193,22 +193,22 @@ contract Stake {
|
||||||
SafeERC20.safeTransfer(kraiken, pos.owner, assets);
|
SafeERC20.safeTransfer(kraiken, pos.owner, assets);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Converts Harberg token assets to shares of the total staking pool.
|
/// @notice Converts Kraiken token assets to shares of the total staking pool.
|
||||||
/// @param assets Number of Harberg tokens to convert.
|
/// @param assets Number of Kraiken tokens to convert.
|
||||||
/// @return Number of shares corresponding to the input assets based on the current total supply of Harberg tokens.
|
/// @return Number of shares corresponding to the input assets based on the current total supply of Kraiken tokens.
|
||||||
function assetsToShares(uint256 assets) public view returns (uint256) {
|
function assetsToShares(uint256 assets) public view returns (uint256) {
|
||||||
return assets.mulDiv(totalSupply, kraiken.totalSupply(), Math.Rounding.Down);
|
return assets.mulDiv(totalSupply, kraiken.totalSupply(), Math.Rounding.Down);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Converts shares of the total staking pool back to Harberg token assets.
|
/// @notice Converts shares of the total staking pool back to Kraiken token assets.
|
||||||
/// @param shares Number of shares to convert.
|
/// @param shares Number of shares to convert.
|
||||||
/// @return The equivalent number of Harberg tokens for the given shares.
|
/// @return The equivalent number of Kraiken tokens for the given shares.
|
||||||
function sharesToAssets(uint256 shares) public view returns (uint256) {
|
function sharesToAssets(uint256 shares) public view returns (uint256) {
|
||||||
return shares.mulDiv(kraiken.totalSupply(), totalSupply, Math.Rounding.Down);
|
return shares.mulDiv(kraiken.totalSupply(), totalSupply, Math.Rounding.Down);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Creates a new staking position by potentially snatching shares from existing positions.
|
/// @notice Creates a new staking position by potentially snatching shares from existing positions.
|
||||||
/// @param assets Amount of Harberg tokens to convert into a staking position.
|
/// @param assets Amount of Kraiken tokens to convert into a staking position.
|
||||||
/// @param receiver Address that will own the new staking position.
|
/// @param receiver Address that will own the new staking position.
|
||||||
/// @param taxRate The initial tax rate for the new staking position.
|
/// @param taxRate The initial tax rate for the new staking position.
|
||||||
/// @param positionsToSnatch Array of position IDs that the new position will replace by snatching.
|
/// @param positionsToSnatch Array of position IDs that the new position will replace by snatching.
|
||||||
|
|
@ -309,7 +309,7 @@ contract Stake {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Combines an ERC20 permit operation with the snatch function, allowing a staking position creation in one transaction.
|
/// @notice Combines an ERC20 permit operation with the snatch function, allowing a staking position creation in one transaction.
|
||||||
/// @param assets Number of Harberg tokens to stake.
|
/// @param assets Number of Kraiken tokens to stake.
|
||||||
/// @param receiver Address that will own the new staking position.
|
/// @param receiver Address that will own the new staking position.
|
||||||
/// @param taxRate The initial tax rate for the new staking position.
|
/// @param taxRate The initial tax rate for the new staking position.
|
||||||
/// @param positionsToSnatch Array of position IDs that the new position will replace by snatching.
|
/// @param positionsToSnatch Array of position IDs that the new position will replace by snatching.
|
||||||
|
|
@ -411,8 +411,8 @@ contract Stake {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Computes the percentage of Harberg staked from outstanding Stake and authorized Stake.
|
/// @notice Computes the percentage of Kraiken staked from outstanding Stake and authorized Stake.
|
||||||
/// @return percentageStaked A number between 0 and 1e18 indicating the percentage of Harberg supply staked.
|
/// @return percentageStaked A number between 0 and 1e18 indicating the percentage of Kraiken supply staked.
|
||||||
function getPercentageStaked() external view returns (uint256 percentageStaked) {
|
function getPercentageStaked() external view returns (uint256 percentageStaked) {
|
||||||
percentageStaked = (outstandingStake * 1e18) / authorizedStake();
|
percentageStaked = (outstandingStake * 1e18) / authorizedStake();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,7 +61,7 @@ abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||||
event EthAbundance(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, int24 vwapTick);
|
event EthAbundance(int24 currentTick, uint256 ethBalance, uint256 outstandingSupply, uint256 vwap, int24 vwapTick);
|
||||||
|
|
||||||
/// @notice Abstract functions that must be implemented by inheriting contracts
|
/// @notice Abstract functions that must be implemented by inheriting contracts
|
||||||
function _getHarbToken() internal view virtual returns (address);
|
function _getKraikenToken() internal view virtual returns (address);
|
||||||
function _getWethToken() internal view virtual returns (address);
|
function _getWethToken() internal view virtual returns (address);
|
||||||
function _isToken0Weth() internal view virtual returns (bool);
|
function _isToken0Weth() internal view virtual returns (bool);
|
||||||
function _mintPosition(Stage stage, int24 tickLower, int24 tickUpper, uint128 liquidity) internal virtual;
|
function _mintPosition(Stage stage, int24 tickLower, int24 tickUpper, uint128 liquidity) internal virtual;
|
||||||
|
|
@ -78,26 +78,26 @@ abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||||
uint256 floorEthBalance = (19 * ethBalance / 20) - (2 * params.anchorShare * ethBalance / 10 ** 19);
|
uint256 floorEthBalance = (19 * ethBalance / 20) - (2 * params.anchorShare * ethBalance / 10 ** 19);
|
||||||
|
|
||||||
// Step 1: Set ANCHOR position (shallow liquidity for fast price movement)
|
// Step 1: Set ANCHOR position (shallow liquidity for fast price movement)
|
||||||
(uint256 pulledHarb, uint128 anchorLiquidity) = _setAnchorPosition(currentTick, ethBalance - floorEthBalance, params);
|
(uint256 pulledKraiken, uint128 anchorLiquidity) = _setAnchorPosition(currentTick, ethBalance - floorEthBalance, params);
|
||||||
|
|
||||||
// Step 2: Set DISCOVERY position (depends on anchor's liquidity)
|
// Step 2: Set DISCOVERY position (depends on anchor's liquidity)
|
||||||
uint256 discoveryAmount = _setDiscoveryPosition(currentTick, anchorLiquidity, params);
|
uint256 discoveryAmount = _setDiscoveryPosition(currentTick, anchorLiquidity, params);
|
||||||
|
|
||||||
// Step 3: Set FLOOR position (deep liquidity, uses VWAP for historical memory)
|
// Step 3: Set FLOOR position (deep liquidity, uses VWAP for historical memory)
|
||||||
_setFloorPosition(currentTick, floorEthBalance, pulledHarb, discoveryAmount, params);
|
_setFloorPosition(currentTick, floorEthBalance, pulledKraiken, discoveryAmount, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Sets the anchor position around current price (shallow liquidity)
|
/// @notice Sets the anchor position around current price (shallow liquidity)
|
||||||
/// @param currentTick Current market tick
|
/// @param currentTick Current market tick
|
||||||
/// @param anchorEthBalance ETH allocated to anchor position
|
/// @param anchorEthBalance ETH allocated to anchor position
|
||||||
/// @param params Position parameters
|
/// @param params Position parameters
|
||||||
/// @return pulledHarb Amount of HARB pulled for this position
|
/// @return pulledKraiken Amount of KRAIKEN pulled for this position
|
||||||
/// @return anchorLiquidity The liquidity amount for the anchor position
|
/// @return anchorLiquidity The liquidity amount for the anchor position
|
||||||
function _setAnchorPosition(
|
function _setAnchorPosition(
|
||||||
int24 currentTick,
|
int24 currentTick,
|
||||||
uint256 anchorEthBalance,
|
uint256 anchorEthBalance,
|
||||||
PositionParams memory params
|
PositionParams memory params
|
||||||
) internal returns (uint256 pulledHarb, uint128 anchorLiquidity) {
|
) internal returns (uint256 pulledKraiken, uint128 anchorLiquidity) {
|
||||||
// Enforce anchor range of 1% to 100% of the price
|
// Enforce anchor range of 1% to 100% of the price
|
||||||
int24 anchorSpacing = TICK_SPACING + (34 * int24(params.anchorWidth) * TICK_SPACING / 100);
|
int24 anchorSpacing = TICK_SPACING + (34 * int24(params.anchorWidth) * TICK_SPACING / 100);
|
||||||
|
|
||||||
|
|
@ -112,10 +112,10 @@ abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||||
|
|
||||||
if (token0isWeth) {
|
if (token0isWeth) {
|
||||||
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, anchorEthBalance);
|
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount0(sqrtRatioX96, sqrtRatioBX96, anchorEthBalance);
|
||||||
pulledHarb = LiquidityAmounts.getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, anchorLiquidity);
|
pulledKraiken = LiquidityAmounts.getAmount1ForLiquidity(sqrtRatioAX96, sqrtRatioX96, anchorLiquidity);
|
||||||
} else {
|
} else {
|
||||||
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, anchorEthBalance);
|
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount1(sqrtRatioAX96, sqrtRatioX96, anchorEthBalance);
|
||||||
pulledHarb = LiquidityAmounts.getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, anchorLiquidity);
|
pulledKraiken = LiquidityAmounts.getAmount0ForLiquidity(sqrtRatioX96, sqrtRatioBX96, anchorLiquidity);
|
||||||
}
|
}
|
||||||
|
|
||||||
_mintPosition(Stage.ANCHOR, tickLower, tickUpper, anchorLiquidity);
|
_mintPosition(Stage.ANCHOR, tickLower, tickUpper, anchorLiquidity);
|
||||||
|
|
@ -125,7 +125,7 @@ abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||||
/// @param currentTick Current market tick (normalized to tick spacing)
|
/// @param currentTick Current market tick (normalized to tick spacing)
|
||||||
/// @param anchorLiquidity Liquidity amount from anchor position
|
/// @param anchorLiquidity Liquidity amount from anchor position
|
||||||
/// @param params Position parameters
|
/// @param params Position parameters
|
||||||
/// @return discoveryAmount Amount of HARB used for discovery
|
/// @return discoveryAmount Amount of KRAIKEN used for discovery
|
||||||
function _setDiscoveryPosition(
|
function _setDiscoveryPosition(
|
||||||
int24 currentTick,
|
int24 currentTick,
|
||||||
uint128 anchorLiquidity,
|
uint128 anchorLiquidity,
|
||||||
|
|
@ -179,13 +179,13 @@ abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||||
/// Extreme floor positions are CORRECT behavior protecting protocol solvency
|
/// Extreme floor positions are CORRECT behavior protecting protocol solvency
|
||||||
/// @param currentTick Current market tick
|
/// @param currentTick Current market tick
|
||||||
/// @param floorEthBalance ETH allocated to floor position (75% of total)
|
/// @param floorEthBalance ETH allocated to floor position (75% of total)
|
||||||
/// @param pulledHarb HARB amount from anchor position
|
/// @param pulledKraiken KRAIKEN amount from anchor position
|
||||||
/// @param discoveryAmount HARB amount from discovery position
|
/// @param discoveryAmount KRAIKEN amount from discovery position
|
||||||
/// @param params Position parameters including capital inefficiency
|
/// @param params Position parameters including capital inefficiency
|
||||||
function _setFloorPosition(
|
function _setFloorPosition(
|
||||||
int24 currentTick,
|
int24 currentTick,
|
||||||
uint256 floorEthBalance,
|
uint256 floorEthBalance,
|
||||||
uint256 pulledHarb,
|
uint256 pulledKraiken,
|
||||||
uint256 discoveryAmount,
|
uint256 discoveryAmount,
|
||||||
PositionParams memory params
|
PositionParams memory params
|
||||||
) internal {
|
) internal {
|
||||||
|
|
@ -193,7 +193,7 @@ abstract contract ThreePositionStrategy is UniswapMath, VWAPTracker {
|
||||||
|
|
||||||
// Calculate outstanding supply after position minting
|
// Calculate outstanding supply after position minting
|
||||||
uint256 outstandingSupply = _getOutstandingSupply();
|
uint256 outstandingSupply = _getOutstandingSupply();
|
||||||
outstandingSupply -= pulledHarb;
|
outstandingSupply -= pulledKraiken;
|
||||||
outstandingSupply -= (outstandingSupply >= discoveryAmount) ? discoveryAmount : outstandingSupply;
|
outstandingSupply -= (outstandingSupply >= discoveryAmount) ? discoveryAmount : outstandingSupply;
|
||||||
|
|
||||||
// Use VWAP for floor position (historical price memory for dormant whale protection)
|
// Use VWAP for floor position (historical price memory for dormant whale protection)
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,20 @@ import {ABDKMath64x64} from "@abdk/ABDKMath64x64.sol";
|
||||||
abstract contract UniswapMath {
|
abstract contract UniswapMath {
|
||||||
using Math for uint256;
|
using Math for uint256;
|
||||||
|
|
||||||
/// @notice Calculates the Uniswap V3 tick corresponding to a given price ratio between Harberg and ETH
|
/// @notice Calculates the Uniswap V3 tick corresponding to a given price ratio between Kraiken and ETH
|
||||||
/// @param t0isWeth Boolean flag indicating if token0 is WETH
|
/// @param t0isWeth Boolean flag indicating if token0 is WETH
|
||||||
/// @param tokenAmount Amount of the Harberg token
|
/// @param tokenAmount Amount of the Kraiken token
|
||||||
/// @param ethAmount Amount of Ethereum
|
/// @param ethAmount Amount of Ethereum
|
||||||
/// @return tick_ The calculated tick for the given price ratio
|
/// @return tick_ The calculated tick for the given price ratio
|
||||||
function _tickAtPrice(bool t0isWeth, uint256 tokenAmount, uint256 ethAmount) internal pure returns (int24 tick_) {
|
function _tickAtPrice(bool t0isWeth, uint256 tokenAmount, uint256 ethAmount) internal pure returns (int24 tick_) {
|
||||||
require(ethAmount > 0, "ETH amount cannot be zero");
|
require(ethAmount > 0, "ETH amount cannot be zero");
|
||||||
if (tokenAmount == 0) {
|
if (tokenAmount == 0) {
|
||||||
// HARB/ETH
|
// KRAIKEN/ETH
|
||||||
tick_ = TickMath.MAX_TICK;
|
tick_ = TickMath.MAX_TICK;
|
||||||
} else {
|
} else {
|
||||||
// Use ABDKMath64x64 for precise division and square root calculation
|
// Use ABDKMath64x64 for precise division and square root calculation
|
||||||
int128 priceRatioX64 = ABDKMath64x64.div(int128(int256(tokenAmount)), int128(int256(ethAmount)));
|
int128 priceRatioX64 = ABDKMath64x64.div(int128(int256(tokenAmount)), int128(int256(ethAmount)));
|
||||||
// HARB/ETH
|
// KRAIKEN/ETH
|
||||||
tick_ = _tickAtPriceRatio(priceRatioX64);
|
tick_ = _tickAtPriceRatio(priceRatioX64);
|
||||||
}
|
}
|
||||||
// convert to tick in a pool
|
// convert to tick in a pool
|
||||||
|
|
@ -42,7 +42,7 @@ abstract contract UniswapMath {
|
||||||
tick_ = TickMath.getTickAtSqrtRatio(sqrtPriceX96);
|
tick_ = TickMath.getTickAtSqrtRatio(sqrtPriceX96);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @notice Calculates the price ratio from a given Uniswap V3 tick as HARB/ETH
|
/// @notice Calculates the price ratio from a given Uniswap V3 tick as KRAIKEN/ETH
|
||||||
/// @dev IMPORTANT: Returns price² (squared price) in X96 format, NOT regular price
|
/// @dev IMPORTANT: Returns price² (squared price) in X96 format, NOT regular price
|
||||||
/// This is intentional for capital requirement calculations
|
/// This is intentional for capital requirement calculations
|
||||||
/// To get regular price: sqrt(priceRatioX96) * 2^48
|
/// To get regular price: sqrt(priceRatioX96) * 2^48
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ contract MockThreePositionStrategy is ThreePositionStrategy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implementation of abstract functions
|
// Implementation of abstract functions
|
||||||
function _getHarbToken() internal view override returns (address) {
|
function _getKraikenToken() internal view override returns (address) {
|
||||||
return harbToken;
|
return harbToken;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ contract TestEnvironment is TestConstants {
|
||||||
}
|
}
|
||||||
|
|
||||||
weth = IWETH9(address(new WETH()));
|
weth = IWETH9(address(new WETH()));
|
||||||
harberg = new Kraiken("KRAIKEN", "HARB");
|
harberg = new Kraiken("KRAIKEN", "KRAIKEN");
|
||||||
|
|
||||||
// Check if the setup meets the required condition
|
// Check if the setup meets the required condition
|
||||||
if (token0shouldBeWeth == (address(weth) < address(harberg))) {
|
if (token0shouldBeWeth == (address(weth) < address(harberg))) {
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,8 @@
|
||||||
|
|
||||||
## Recent Completion
|
## Recent Completion
|
||||||
✅ **Break down testDoubleOverflowRealisticScenario()** - Successfully split into 3 focused tests with proper assertions:
|
✅ **Break down testDoubleOverflowRealisticScenario()** - Successfully split into 3 focused tests with proper assertions:
|
||||||
- `testDoubleOverflowExtremeEthPriceScenario()` - ETH at $1M, HARB at $1
|
- `testDoubleOverflowExtremeEthPriceScenario()` - ETH at $1M, KRAIKEN at $1
|
||||||
- `testDoubleOverflowHyperinflatedHarbScenario()` - HARB at $1M, ETH at $3k
|
- `testDoubleOverflowHyperinflatedHarbScenario()` - KRAIKEN at $1M, ETH at $3k
|
||||||
- `testDoubleOverflowMaximumTransactionScenario()` - 10k ETH transactions
|
- `testDoubleOverflowMaximumTransactionScenario()` - 10k ETH transactions
|
||||||
|
|
||||||
All new tests validate that double overflow requires unrealistic conditions, proving the 1000x compression limit provides adequate protection.
|
All new tests validate that double overflow requires unrealistic conditions, proving the 1000x compression limit provides adequate protection.
|
||||||
Loading…
Add table
Add a link
Reference in a new issue