ETH Price: $2,279.53 (+2.77%)

Contract

0xFEcda5a66D077972446Add1748b6092b3Bba9A09
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
Age
From
To

There are no matching entries

1 Internal Transaction found.

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Method Block
Age
From
To
0x3d6100f8217477042025-01-31 23:10:4733 days ago1738365047
 Contract Creation
0 ETH
Loading...
Loading

Minimal Proxy Contract for 0xdf9832fd5583f3ed52c28d401cde96ba51bd1b41

Contract Name:
BunniToken

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 7500 runs

Other Settings:
cancun EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 59 : BunniToken.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.15;
import {Clone} from "clones-with-immutable-args/Clone.sol";
import {LibMulticaller} from "multicaller/LibMulticaller.sol";
import "@uniswap/v4-core/src/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {SafeTransferLib} from "solady/utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import "./base/Errors.sol";
import "./base/Constants.sol";
import {ERC20} from "./base/ERC20.sol";
import {Ownable} from "./base/Ownable.sol";
import {IERC20} from "./interfaces/IERC20.sol";
import {HookletLib} from "./lib/HookletLib.sol";
import {IHooklet} from "./interfaces/IHooklet.sol";
import {IBunniHub} from "./interfaces/IBunniHub.sol";
import {IBunniToken} from "./interfaces/IBunniToken.sol";
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 2 of 59 : Clone.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: BSD
pragma solidity ^0.8.4;
/// @title Clone
/// @author zefram.eth
/// @notice Provides helper functions for reading immutable args from calldata
contract Clone {
/// @notice Reads an immutable arg with type address
/// @param argOffset The offset of the arg in the packed data
/// @return arg The arg value
function _getArgAddress(
uint256 argOffset
) internal pure returns (address arg) {
uint256 offset = _getImmutableArgsOffset();
// solhint-disable-next-line no-inline-assembly
assembly {
arg := shr(0x60, calldataload(add(offset, argOffset)))
}
}
/// @notice Reads an immutable arg with type uint256
/// @param argOffset The offset of the arg in the packed data
/// @return arg The arg value
function _getArgUint256(
uint256 argOffset
) internal pure returns (uint256 arg) {
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 3 of 59 : LibMulticaller.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/**
* @title LibMulticaller
* @author vectorized.eth
* @notice Library to read the `msg.sender` of the multicaller with sender contract.
*
* @dev Note:
* The functions in this library do NOT guard against reentrancy.
* A single transaction can recurse through different Multicallers
* (e.g. `MulticallerWithSender -> contract -> MulticallerWithSigner -> contract`).
*
* Think of these functions like `msg.sender`.
*
* If your contract `C` can handle reentrancy safely with plain old `msg.sender`
* for any `A -> C -> B -> C`, you should be fine substituting `msg.sender` with these functions.
*/
library LibMulticaller {
/**
* @dev The address of the multicaller contract.
*/
address internal constant MULTICALLER = 0x0000000000002Bdbf1Bf3279983603Ec279CC6dF;
/**
* @dev The address of the multicaller with sender contract.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 4 of 59 : Currency.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IERC20Minimal} from "../interfaces/external/IERC20Minimal.sol";
import {CustomRevert} from "../libraries/CustomRevert.sol";
type Currency is address;
using {greaterThan as >, lessThan as <, greaterThanOrEqualTo as >=, equals as ==} for Currency global;
using CurrencyLibrary for Currency global;
function equals(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) == Currency.unwrap(other);
}
function greaterThan(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) > Currency.unwrap(other);
}
function lessThan(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) < Currency.unwrap(other);
}
function greaterThanOrEqualTo(Currency currency, Currency other) pure returns (bool) {
return Currency.unwrap(currency) >= Currency.unwrap(other);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 5 of 59 : PoolKey.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Currency} from "./Currency.sol";
import {IHooks} from "../interfaces/IHooks.sol";
import {PoolIdLibrary} from "./PoolId.sol";
using PoolIdLibrary for PoolKey global;
/// @notice Returns the key for identifying a pool
struct PoolKey {
/// @notice The lower currency of the pool, sorted numerically
Currency currency0;
/// @notice The higher currency of the pool, sorted numerically
Currency currency1;
/// @notice The pool LP fee, capped at 1_000_000. If the highest bit is 1, the pool has a dynamic fee and must be exactly equal to 0x800000
uint24 fee;
/// @notice Ticks that involve positions must be a multiple of tick spacing
int24 tickSpacing;
/// @notice The hooks of the pool
IHooks hooks;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 6 of 59 : IHooks.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {IPoolManager} from "./IPoolManager.sol";
import {BeforeSwapDelta} from "../types/BeforeSwapDelta.sol";
/// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits
/// of the address that the hooks contract is deployed to.
/// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400
/// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used.
/// See the Hooks library for the full spec.
/// @dev Should only be callable by the v4 PoolManager.
interface IHooks {
/// @notice The hook called before the state of a pool is initialized
/// @param sender The initial msg.sender for the initialize call
/// @param key The key for the pool being initialized
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
/// @return bytes4 The function selector for the hook
function beforeInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96) external returns (bytes4);
/// @notice The hook called after the state of a pool is initialized
/// @param sender The initial msg.sender for the initialize call
/// @param key The key for the pool being initialized
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 7 of 59 : IPoolManager.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {Currency} from "../types/Currency.sol";
import {PoolKey} from "../types/PoolKey.sol";
import {IHooks} from "./IHooks.sol";
import {IERC6909Claims} from "./external/IERC6909Claims.sol";
import {IProtocolFees} from "./IProtocolFees.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {PoolId} from "../types/PoolId.sol";
import {IExtsload} from "./IExtsload.sol";
import {IExttload} from "./IExttload.sol";
/// @notice Interface for the PoolManager
interface IPoolManager is IProtocolFees, IERC6909Claims, IExtsload, IExttload {
/// @notice Thrown when a currency is not netted out after the contract is unlocked
error CurrencyNotSettled();
/// @notice Thrown when trying to interact with a non-initialized pool
error PoolNotInitialized();
/// @notice Thrown when unlock is called, but the contract is already unlocked
error AlreadyUnlocked();
/// @notice Thrown when a function is called that requires the contract to be unlocked, but it is not
error ManagerLocked();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 8 of 59 : IUnlockCallback.sol
1
2
3
4
5
6
7
8
9
10
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Interface for the callback executed when an address unlocks the pool manager
interface IUnlockCallback {
/// @notice Called by the pool manager on `msg.sender` when the manager is unlocked
/// @param data The data that was passed to the call to unlock
/// @return Any data that you want to be returned from the unlock call
function unlockCallback(bytes calldata data) external returns (bytes memory);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 9 of 59 : SafeTransferLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
library SafeTransferLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/// @dev The ERC20 `transferFrom` has failed.
error TransferFromFailed();
/// @dev The ERC20 `transfer` has failed.
error TransferFailed();
/// @dev The ERC20 `approve` has failed.
error ApproveFailed();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 10 of 59 : FixedPointMathLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Arithmetic library with operations for fixed-point numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/FixedPointMathLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol)
library FixedPointMathLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The operation failed, as the output exceeds the maximum value of uint256.
error ExpOverflow();
/// @dev The operation failed, as the output exceeds the maximum value of uint256.
error FactorialOverflow();
/// @dev The operation failed, due to an overflow.
error RPowOverflow();
/// @dev The mantissa is too big to fit.
error MantissaOverflow();
/// @dev The operation failed, due to an multiplication overflow.
error MulWadFailed();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 11 of 59 : Errors.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
pragma abicoder v2;
error BunniHub__Paused();
error BunniHub__ZeroInput();
error BunniHub__PastDeadline();
error BunniHub__Unauthorized();
error BunniHub__InvalidReferrer();
error BunniHub__LDFCannotBeZero();
error BunniHub__MaxNonceReached();
error BunniHub__SlippageTooHigh();
error BunniHub__WithdrawalPaused();
error BunniHub__HookCannotBeZero();
error BunniHub__ZeroSharesMinted();
error BunniHub__InvalidLDFParams();
error BunniHub__InvalidHookParams();
error BunniHub__VaultFeeIncorrect();
error BunniHub__VaultAssetMismatch();
error BunniHub__GracePeriodExpired();
error BunniHub__NoExpiredWithdrawal();
error BunniHub__MsgValueInsufficient();
error BunniHub__DepositAmountTooSmall();
error BunniHub__QueuedWithdrawalNotReady();
error BunniHub__BunniTokenNotInitialized();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 12 of 59 : Constants.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
pragma abicoder v2;
uint256 constant WAD = 1e18;
uint256 constant Q96 = 0x1000000000000000000000000;
uint256 constant MAX_NONCE = 1e6;
uint256 constant MIN_INITIAL_SHARES = 1e12;
uint256 constant MAX_SWAP_FEE_RATIO = 2.88e20; // max ratio that avoids overflow in swap fee calculation, roughly sqrt(SWAP_FEE_BASE) * sqrt(sqrt
    ((type(uint256).max - SWAP_FEE_BASE) / type(uint24).max) - 1)
uint256 constant SWAP_FEE_BASE = 1e6;
uint256 constant SWAP_FEE_BASE_SQUARED = 1e12;
uint256 constant RAW_TOKEN_RATIO_BASE = 1e6;
uint256 constant LN2_WAD = 693147180559945309;
uint256 constant MAX_VAULT_FEE_ERROR = 1e6;
uint256 constant MAX_CARDINALITY = 2 ** 24 - 1;
uint56 constant WITHDRAW_DELAY = 1 minutes;
uint56 constant WITHDRAW_GRACE_PERIOD = 3 minutes;
uint256 constant REFERRAL_REWARD_PER_TOKEN_PRECISION = 1e30;
uint256 constant MODIFIER_BASE = 1e6;
uint256 constant MIN_DEPOSIT_BALANCE_INCREASE = 1e6;
uint24 constant MAX_AMAMM_FEE = 0.1e6;
uint256 constant REBALANCE_MAX_SLIPPAGE_BASE = 1e5;
uint16 constant MAX_SURGE_HALFLIFE = 1 hours;
uint16 constant MAX_SURGE_AUTOSTART_TIME = 1 hours;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 13 of 59 : ERC20.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {IERC20} from "../interfaces/IERC20.sol";
/// @notice Simple ERC20 + EIP-2612 implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
///
/// @dev Note:
/// - The ERC20 standard allows minting and transferring to and from the zero address,
/// minting and transferring zero tokens, as well as self-approvals.
/// For performance, this implementation WILL NOT revert for such actions.
/// Please add any checks with overrides if desired.
/// - The `permit` function uses the ecrecover precompile (0x1).
///
/// If you are overriding:
/// - NEVER violate the ERC20 invariant:
/// the total sum of all balances must be equal to `totalSupply()`.
/// - Check that the overridden function is actually used in the function you want to
/// change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC20 is IERC20 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 14 of 59 : Ownable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {IOwnable} from "../interfaces/IOwnable.sol";
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable is IOwnable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 15 of 59 : IERC20.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
* Modified from OpenZeppelin's IERC20 contract
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 16 of 59 : HookletLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {CustomRevert} from "@uniswap/v4-core/src/libraries/CustomRevert.sol";
import {IPoolManager, PoolKey} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import "../base/Constants.sol";
import {IHooklet} from "../interfaces/IHooklet.sol";
import {IBunniHub} from "../interfaces/IBunniHub.sol";
import {IBunniToken} from "../interfaces/IBunniToken.sol";
/// @dev Adapted from Uniswap v4's Hooks.sol
library HookletLib {
using CustomRevert for bytes4;
using HookletLib for IHooklet;
using FixedPointMathLib for *;
uint160 internal constant ALL_FLAGS_MASK = 0xFFF;
uint160 internal constant BEFORE_TRANSFER_FLAG = 1 << 11;
uint160 internal constant AFTER_TRANSFER_FLAG = 1 << 10;
uint160 internal constant BEFORE_INITIALIZE_FLAG = 1 << 9;
uint160 internal constant AFTER_INITIALIZE_FLAG = 1 << 8;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 17 of 59 : IHooklet.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IPoolManager, PoolKey} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IBunniHub} from "./IBunniHub.sol";
import {IBunniToken} from "./IBunniToken.sol";
/// @title Hooklet
/// @notice Hooklets let developers execute custom logic before/after Bunni operations.
/// Each Bunni pool can have one hooklet attached to it. The least significant bits of the hooklet's
/// address is used to flag which hooklet functions should be callled.
interface IHooklet {
/// @notice Return data of an initialize operation.
/// @member bunniToken The BunniToken deployed.
/// @member key The Uniswap v4 pool's key.
struct InitializeReturnData {
IBunniToken bunniToken;
PoolKey key;
}
/// @notice Return data of a deposit operation.
/// @member shares The amount of shares minted.
/// @member amount0 The amount of token0 deposited.
/// @member amount1 The amount of token1 deposited.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 18 of 59 : IBunniHub.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
pragma abicoder v2;
import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
import {IPoolManager, PoolKey} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {WETH} from "solady/tokens/WETH.sol";
import {ERC4626} from "solady/tokens/ERC4626.sol";
import "../types/LDFType.sol";
import "../types/IdleBalance.sol";
import "../base/SharedStructs.sol";
import {IERC20} from "./IERC20.sol";
import {IHooklet} from "./IHooklet.sol";
import {IOwnable} from "./IOwnable.sol";
import {IBunniHook} from "./IBunniHook.sol";
import {IBunniToken} from "./IBunniToken.sol";
import {PoolState} from "../types/PoolState.sol";
import {ILiquidityDensityFunction} from "./ILiquidityDensityFunction.sol";
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 19 of 59 : IBunniToken.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
import "@uniswap/v4-core/src/types/Currency.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {IERC20} from "./IERC20.sol";
import {IOwnable} from "./IOwnable.sol";
import {IHooklet} from "./IHooklet.sol";
import {IBunniHub} from "./IBunniHub.sol";
import {IERC20Referrer} from "./IERC20Referrer.sol";
import {IERC20Lockable} from "./IERC20Lockable.sol";
/// @title BunniToken
/// @author zefram.eth
/// @notice ERC20 token that represents a user's LP position
interface IBunniToken is IERC20, IERC20Referrer, IERC20Lockable, IOwnable, IUnlockCallback {
event ClaimReferralRewards(address indexed referrer, uint256 reward0, uint256 reward1);
event SetMetadataURI(string newURI);
function hub() external view returns (IBunniHub);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 20 of 59 : ERC20Referrer.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.4;
import {LibMulticaller} from "multicaller/LibMulticaller.sol";
import "./Constants.sol";
import {ERC20} from "./ERC20.sol";
import {IERC20Lockable} from "../interfaces/IERC20Lockable.sol";
import {IERC20Unlocker} from "../interfaces/IERC20Unlocker.sol";
import {IERC20Referrer} from "../interfaces/IERC20Referrer.sol";
/// @title ERC20Referrer
/// @notice An ERC20 token with referrer tracking and Multicaller support. Tracks
/// the score of each referrer, which is the sum of all balances of accounts that
/// have the referrer as their referrer. Supports locking accounts which enables
/// transfer-less staking contracts that don't disrupt the referrer tracking.
/// @dev Balances are stored as uint232 instead of uint256 since the upper 24 bits
/// of the storage slot are used to store the lock flag & referrer.
/// Referrer 0 should be reserved for the protocol since it's the default referrer.
abstract contract ERC20Referrer is ERC20, IERC20Referrer, IERC20Lockable {
/// -----------------------------------------------------------------------
/// Errors
/// -----------------------------------------------------------------------
/// @dev Error when the balance overflows uint232.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 21 of 59 : IERC20Minimal.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Minimal ERC20 interface for Uniswap
/// @notice Contains a subset of the full ERC20 interface that is used in Uniswap V3
interface IERC20Minimal {
/// @notice Returns an account's balance in the token
/// @param account The account for which to look up the number of tokens it has, i.e. its balance
/// @return The number of tokens held by the account
function balanceOf(address account) external view returns (uint256);
/// @notice Transfers the amount of token from the `msg.sender` to the recipient
/// @param recipient The account that will receive the amount transferred
/// @param amount The number of tokens to send from the sender to the recipient
/// @return Returns true for a successful transfer, false for an unsuccessful transfer
function transfer(address recipient, uint256 amount) external returns (bool);
/// @notice Returns the current allowance given to a spender by an owner
/// @param owner The account of the token owner
/// @param spender The account of the token spender
/// @return The current allowance granted by `owner` to `spender`
function allowance(address owner, address spender) external view returns (uint256);
/// @notice Sets the allowance of a spender from the `msg.sender` to the value `amount`
/// @param spender The account which will be allowed to spend a given amount of the owners tokens
/// @param amount The amount of tokens allowed to be used by `spender`
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 22 of 59 : CustomRevert.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title Library for reverting with custom errors efficiently
/// @notice Contains functions for reverting with custom errors with different argument types efficiently
/// @dev To use this library, declare `using CustomRevert for bytes4;` and replace `revert CustomError()` with
/// `CustomError.selector.revertWith()`
/// @dev The functions may tamper with the free memory pointer but it is fine since the call context is exited immediately
library CustomRevert {
/// @dev ERC-7751 error for wrapping bubbled up reverts
error WrappedError(address target, bytes4 selector, bytes reason, bytes details);
/// @dev Reverts with the selector of a custom error in the scratch space
function revertWith(bytes4 selector) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
revert(0, 0x04)
}
}
/// @dev Reverts with a custom error with an address argument in the scratch space
function revertWith(bytes4 selector, address addr) internal pure {
assembly ("memory-safe") {
mstore(0, selector)
mstore(0x04, and(addr, 0xffffffffffffffffffffffffffffffffffffffff))
revert(0, 0x24)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 23 of 59 : PoolId.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {PoolKey} from "./PoolKey.sol";
type PoolId is bytes32;
/// @notice Library for computing the ID of a pool
library PoolIdLibrary {
/// @notice Returns value equal to keccak256(abi.encode(poolKey))
function toId(PoolKey memory poolKey) internal pure returns (PoolId poolId) {
assembly ("memory-safe") {
// 0xa0 represents the total size of the poolKey struct (5 slots of 32 bytes)
poolId := keccak256(poolKey, 0xa0)
}
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 24 of 59 : BalanceDelta.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {SafeCast} from "../libraries/SafeCast.sol";
/// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0
/// and the lower 128 bits represent the amount1.
type BalanceDelta is int256;
using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global;
using BalanceDeltaLibrary for BalanceDelta global;
using SafeCast for int256;
function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) {
assembly ("memory-safe") {
balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1))
}
}
function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
int256 res0;
int256 res1;
assembly ("memory-safe") {
let a0 := sar(128, a)
let a1 := signextend(15, a)
let b0 := sar(128, b)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 25 of 59 : BeforeSwapDelta.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Return type of the beforeSwap hook.
// Upper 128 bits is the delta in specified tokens. Lower 128 bits is delta in unspecified tokens (to match the afterSwap hook)
type BeforeSwapDelta is int256;
// Creates a BeforeSwapDelta from specified and unspecified
function toBeforeSwapDelta(int128 deltaSpecified, int128 deltaUnspecified)
pure
returns (BeforeSwapDelta beforeSwapDelta)
{
assembly ("memory-safe") {
beforeSwapDelta := or(shl(128, deltaSpecified), and(sub(shl(128, 1), 1), deltaUnspecified))
}
}
/// @notice Library for getting the specified and unspecified deltas from the BeforeSwapDelta type
library BeforeSwapDeltaLibrary {
/// @notice A BeforeSwapDelta of 0
BeforeSwapDelta public constant ZERO_DELTA = BeforeSwapDelta.wrap(0);
/// extracts int128 from the upper 128 bits of the BeforeSwapDelta
/// returned by beforeSwap
function getSpecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaSpecified) {
assembly ("memory-safe") {
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 26 of 59 : IERC6909Claims.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Interface for claims over a contract balance, wrapped as a ERC6909
interface IERC6909Claims {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/
event OperatorSet(address indexed owner, address indexed operator, bool approved);
event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);
event Transfer(address caller, address indexed from, address indexed to, uint256 indexed id, uint256 amount);
/*//////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////*/
/// @notice Owner balance of an id.
/// @param owner The address of the owner.
/// @param id The id of the token.
/// @return amount The balance of the token.
function balanceOf(address owner, uint256 id) external view returns (uint256 amount);
/// @notice Spender allowance of an id.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 27 of 59 : IProtocolFees.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Currency} from "../types/Currency.sol";
import {PoolId} from "../types/PoolId.sol";
import {PoolKey} from "../types/PoolKey.sol";
/// @notice Interface for all protocol-fee related functions in the pool manager
interface IProtocolFees {
/// @notice Thrown when protocol fee is set too high
error ProtocolFeeTooLarge(uint24 fee);
/// @notice Thrown when collectProtocolFees or setProtocolFee is not called by the controller.
error InvalidCaller();
/// @notice Thrown when collectProtocolFees is attempted on a token that is synced.
error ProtocolFeeCurrencySynced();
/// @notice Emitted when the protocol fee controller address is updated in setProtocolFeeController.
event ProtocolFeeControllerUpdated(address indexed protocolFeeController);
/// @notice Emitted when the protocol fee is updated for a pool.
event ProtocolFeeUpdated(PoolId indexed id, uint24 protocolFee);
/// @notice Given a currency address, returns the protocol fees accrued in that currency
/// @param currency The currency to check
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 28 of 59 : IExtsload.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Interface for functions to access any storage slot in a contract
interface IExtsload {
/// @notice Called by external contracts to access granular pool state
/// @param slot Key of slot to sload
/// @return value The value of the slot as bytes32
function extsload(bytes32 slot) external view returns (bytes32 value);
/// @notice Called by external contracts to access granular pool state
/// @param startSlot Key of slot to start sloading from
/// @param nSlots Number of slots to load into return value
/// @return values List of loaded values.
function extsload(bytes32 startSlot, uint256 nSlots) external view returns (bytes32[] memory values);
/// @notice Called by external contracts to access sparse pool state
/// @param slots List of slots to SLOAD from.
/// @return values List of loaded values.
function extsload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 29 of 59 : IExttload.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
/// @notice Interface for functions to access any transient storage slot in a contract
interface IExttload {
/// @notice Called by external contracts to access transient storage of the contract
/// @param slot Key of slot to tload
/// @return value The value of the slot as bytes32
function exttload(bytes32 slot) external view returns (bytes32 value);
/// @notice Called by external contracts to access sparse transient pool state
/// @param slots List of slots to tload
/// @return values List of loaded values
function exttload(bytes32[] calldata slots) external view returns (bytes32[] memory values);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 30 of 59 : IOwnable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IOwnable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 31 of 59 : TickMath.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {BitMath} from "./BitMath.sol";
import {CustomRevert} from "./CustomRevert.sol";
/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
using CustomRevert for bytes4;
/// @notice Thrown when the tick passed to #getSqrtPriceAtTick is not between MIN_TICK and MAX_TICK
error InvalidTick(int24 tick);
/// @notice Thrown when the price passed to #getTickAtSqrtPrice does not correspond to a price between MIN_TICK and MAX_TICK
error InvalidSqrtPrice(uint160 sqrtPriceX96);
/// @dev The minimum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**-128
/// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used
int24 internal constant MIN_TICK = -887272;
/// @dev The maximum tick that may be passed to #getSqrtPriceAtTick computed from log base 1.0001 of 2**128
/// @dev If ever MIN_TICK and MAX_TICK are not centered around 0, the absTick logic in getSqrtPriceAtTick cannot be used
int24 internal constant MAX_TICK = 887272;
/// @dev The minimum tick spacing value drawn from the range of type int16 that is greater than 0, i.e. min from the range [1, 32767]
int24 internal constant MIN_TICK_SPACING = 1;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 32 of 59 : WETH.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {ERC20} from "./ERC20.sol";
/// @notice Simple Wrapped Ether implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/WETH.sol)
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol)
/// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol)
contract WETH is ERC20 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC20 METADATA */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the name of the token.
function name() public view virtual override returns (string memory) {
return "Wrapped Ether";
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 33 of 59 : ERC4626.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {ERC20} from "./ERC20.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
/// @notice Simple ERC4626 tokenized Vault implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC4626.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/mixins/ERC4626.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC4626
    .sol)
abstract contract ERC4626 is ERC20 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The default underlying decimals.
uint8 internal constant _DEFAULT_UNDERLYING_DECIMALS = 18;
/// @dev The default decimals offset.
uint8 internal constant _DEFAULT_DECIMALS_OFFSET = 0;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 34 of 59 : LDFType.sol
1
2
3
4
5
6
7
8
9
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
enum LDFType {
STATIC, // LDF does not change ever
DYNAMIC_NOT_STATEFUL, // LDF can change, does not use ldfState
DYNAMIC_AND_STATEFUL // LDF can change, uses ldfState
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 35 of 59 : IdleBalance.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import {subReLU} from "../lib/Math.sol";
type IdleBalance is bytes32;
using {equals as ==, notEqual as !=} for IdleBalance global;
using IdleBalanceLibrary for IdleBalance global;
function equals(IdleBalance bal, IdleBalance other) pure returns (bool) {
return IdleBalance.unwrap(bal) == IdleBalance.unwrap(other);
}
function notEqual(IdleBalance bal, IdleBalance other) pure returns (bool) {
return IdleBalance.unwrap(bal) != IdleBalance.unwrap(other);
}
library IdleBalanceLibrary {
using FixedPointMathLib for uint256;
using IdleBalanceLibrary for uint256;
uint256 private constant _BALANCE_MASK = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
/// @dev Set isToken0 to true in ZERO to keep storage slots dirty
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 36 of 59 : SharedStructs.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
pragma abicoder v2;
import {PoolId, PoolKey} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {ERC4626} from "solady/tokens/ERC4626.sol";
import "./Constants.sol";
import "../types/IdleBalance.sol";
import {Oracle} from "../lib/Oracle.sol";
import {RawPoolState} from "../types/PoolState.sol";
import {IBunniHook} from "../interfaces/IBunniHook.sol";
import {IBunniToken} from "../interfaces/IBunniToken.sol";
import {ILiquidityDensityFunction} from "../interfaces/ILiquidityDensityFunction.sol";
/// @title Contains structs shared between multiple contracts
struct QueuedWithdrawal {
uint200 shareAmount;
uint56 unlockTimestamp;
}
/// @notice The storage of BunniHub
/// @member poolState The state of a given pool
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 37 of 59 : IBunniHook.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
import {IHooks} from "@uniswap/v4-core/src/interfaces/IHooks.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {IUnlockCallback} from "@uniswap/v4-core/src/interfaces/callback/IUnlockCallback.sol";
import {IAmAmm} from "biddog/interfaces/IAmAmm.sol";
import "flood-contracts/src/interfaces/IZone.sol";
import "flood-contracts/src/interfaces/IFloodPlain.sol";
import {IERC1271} from "permit2/src/interfaces/IERC1271.sol";
import "../base/Constants.sol";
import "../base/SharedStructs.sol";
import {IOwnable} from "./IOwnable.sol";
import {Oracle} from "../lib/Oracle.sol";
import {IBunniHub} from "./IBunniHub.sol";
import {IBaseHook} from "./IBaseHook.sol";
/// @title BunniHook
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 38 of 59 : PoolState.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {PoolId, PoolKey, Currency} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {SSTORE2} from "solady/utils/SSTORE2.sol";
import {ERC4626} from "solady/tokens/ERC4626.sol";
import "./LDFType.sol";
import "./IdleBalance.sol";
import "../base/Errors.sol";
import {IHooklet} from "../interfaces/IHooklet.sol";
import {HubStorage} from "../base/SharedStructs.sol";
import {IBunniToken} from "../interfaces/IBunniToken.sol";
import {ILiquidityDensityFunction} from "../interfaces/ILiquidityDensityFunction.sol";
using SSTORE2 for address;
/// @notice The state of a Bunni pool
/// @member liquidityDensityFunction The LDF that dictates how liquidity is distributed
/// @member bunniToken The BunniToken for this pool
/// @member hooklet The hooklet for this pool. Set to address(0) if the pool does not have a hooklet.
/// @member twapSecondsAgo The time window for the TWAP used by the LDF. Set to 0 if the LDF does not use the TWAP.
/// @member ldfParams The parameters for the LDF
/// @member hookParams The hook parameters for the pool
/// @member vault0 The ERC4626 vault used for currency0
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 39 of 59 : ILiquidityDensityFunction.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0;
pragma abicoder v2;
import {PoolKey} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
/// @title ILiquidityDensityFunction
/// @author zefram.eth
/// @notice Interface for liquidity density functions (LDFs) that dictate how liquidity is distributed over a pool's rounded ticks (each with
    `tickSpacing` ticks).
/// Each rounded tick is identified by its leftmost tick, which is a multiple of `tickSpacing`. The liquidity density of all rounded ticks should add
    up to 1, similar to probability density functions (PDFs).
/// Also contains functions for efficiently computing the cumulative amount of tokens in a consecutive range of rounded ticks, as well as their
    inverse functions. These are essential for computing swaps.
/// Enables arbitrary liquidity shapes, shifting liquidity across ticks, and switching from one liquidity shape to another.
interface ILiquidityDensityFunction {
/// @notice Queries the liquidity density function for the given pool and rounded tick.
/// Returns the density of the rounded tick, cumulative token densities at adjacent ticks, and state relevant info.
/// @param key The key of the Uniswap v4 pool
/// @param roundedTick The rounded tick to query
/// @param twapTick The TWAP tick. Is 0 if `twapSecondsAgo` is 0. It's up to `isValidParams` to ensure `twapSecondsAgo != 0` if the LDF uses the
        TWAP.
/// @param spotPriceTick The spot price tick.
/// @param ldfParams The parameters for the liquidity density function
/// @param ldfState The current state of the liquidity density function
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 40 of 59 : IERC20Referrer.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
interface IERC20Referrer {
/// @notice Returns the score of a referrer. The score is the sum of all
/// balances of accounts that have the referrer as their referrer.
/// @param referrer The referrer whose score is to be returned.
/// @return score The score of the referrer.
function scoreOf(address referrer) external view returns (uint256 score);
/// @notice Returns the referrer of an account. Default referrer is 0.
/// @param account The account whose referrer is to be returned.
/// @return referrer The referrer of the account.
function referrerOf(address account) external view returns (address referrer);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 41 of 59 : IERC20Lockable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
import "./IERC20Unlocker.sol";
/// @title IERC20Lockable - Interface for a lockable token account.
/// @notice A token holder can lock their account, preventing any transfers from the account.
/// An unlocker contract is able to unlock the account. The unlocker contract is expected to
/// implement the `IERC20Unlocker` interface.
/// Used mainly for staking contracts that don't require transferring the token into the contract.
interface IERC20Lockable {
event Lock(address indexed account, IERC20Unlocker indexed unlocker);
event Unlock(address indexed account, IERC20Unlocker indexed unlocker);
/// @dev Error when calling lock() and the account is already locked.
error AlreadyLocked();
/// @dev Error when calling unlock() and the account is already unlocked.
error AlreadyUnlocked();
/// @dev Error when the caller is not the unlocker of the account.
error NotUnlocker();
/// @dev Error when trasferring tokens from a locked account.
error AccountLocked();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 42 of 59 : IERC20Unlocker.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;
/// @title IERC20Unlocker - Interface for an unlocker contract for `IERC20Lockable`.
/// @notice An unlocker contract is able to unlock accounts that have been locked by a `IERC20Lockable` contract.
/// The unlocker contract is expected to implement the `IERC20Unlocker` interface.
interface IERC20Unlocker {
/// @notice Called when an account calls `IERC20Lockable.lock()` and specifies this contract as the unlocker.
/// @param account The account that called `IERC20Lockable.lock()`.
/// @param balance The balance of the account after the lock.
/// @param data The data passed to `IERC20Lockable.lock()`.
function lockCallback(address account, uint256 balance, bytes calldata data) external;
/// @notice Called when a locked account with this contract as the unlocker receives tokens.
/// @param account The account that received tokens.
/// @param receiveAmount The amount of tokens received.
function lockedUserReceiveCallback(address account, uint256 receiveAmount) external;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 43 of 59 : SafeCast.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {CustomRevert} from "./CustomRevert.sol";
/// @title Safe casting methods
/// @notice Contains methods for safely casting between types
library SafeCast {
using CustomRevert for bytes4;
error SafeCastOverflow();
/// @notice Cast a uint256 to a uint160, revert on overflow
/// @param x The uint256 to be downcasted
/// @return y The downcasted integer, now type uint160
function toUint160(uint256 x) internal pure returns (uint160 y) {
y = uint160(x);
if (y != x) SafeCastOverflow.selector.revertWith();
}
/// @notice Cast a uint256 to a uint128, revert on overflow
/// @param x The uint256 to be downcasted
/// @return y The downcasted integer, now type uint128
function toUint128(uint256 x) internal pure returns (uint128 y) {
y = uint128(x);
if (x != y) SafeCastOverflow.selector.revertWith();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 44 of 59 : BitMath.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @title BitMath
/// @dev This library provides functionality for computing bit properties of an unsigned integer
/// @author Solady (https://github.com/Vectorized/solady/blob/8200a70e8dc2a77ecb074fc2e99a2a0d36547522/src/utils/LibBit.sol)
library BitMath {
/// @notice Returns the index of the most significant bit of the number,
/// where the least significant bit is at index 0 and the most significant bit is at index 255
/// @param x the value for which to compute the most significant bit, must be greater than 0
/// @return r the index of the most significant bit
function mostSignificantBit(uint256 x) internal pure returns (uint8 r) {
require(x > 0);
assembly ("memory-safe") {
r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
r := or(r, shl(4, lt(0xffff, shr(r, x))))
r := or(r, shl(3, lt(0xff, shr(r, x))))
// forgefmt: disable-next-item
r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
0x0706060506020500060203020504000106050205030304010505030400000000))
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 45 of 59 : ERC20.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple ERC20 + EIP-2612 implementation.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol)
///
/// @dev Note:
/// - The ERC20 standard allows minting and transferring to and from the zero address,
/// minting and transferring zero tokens, as well as self-approvals.
/// For performance, this implementation WILL NOT revert for such actions.
/// Please add any checks with overrides if desired.
/// - The `permit` function uses the ecrecover precompile (0x1).
///
/// If you are overriding:
/// - NEVER violate the ERC20 invariant:
/// the total sum of all balances must be equal to `totalSupply()`.
/// - Check that the overridden function is actually used in the function you want to
/// change the behavior of. Much of the code has been manually inlined for performance.
abstract contract ERC20 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The total supply has overflowed.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 46 of 59 : Math.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {SafeCastLib} from "solady/utils/SafeCastLib.sol";
import {TickMath} from "@uniswap/v4-core/src/libraries/TickMath.sol";
import {FixedPointMathLib} from "solady/utils/FixedPointMathLib.sol";
import "../base/Constants.sol";
using FixedPointMathLib for int256;
using FixedPointMathLib for uint256;
/// @dev modified from solady
function dist(uint256 x, uint256 y) pure returns (uint256 z) {
/// @solidity memory-safe-assembly
assembly {
z := xor(mul(xor(sub(y, x), sub(x, y)), gt(x, y)), sub(y, x))
}
}
/// @dev modified from solady
function absDiff(uint256 x, uint256 y) pure returns (bool positive, uint256 diff) {
/// @solidity memory-safe-assembly
assembly {
positive := gt(x, y)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 47 of 59 : Oracle.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {MAX_CARDINALITY} from "../base/Constants.sol";
/// @title Oracle
/// @notice Provides price data useful for a wide variety of system designs. Based on Uniswap's
/// truncated oracle.
/// @dev Instances of stored oracle data, "observations", are collected in the oracle array
/// Every pool is initialized with an oracle array length of 1. Anyone can pay the SSTOREs to increase the
/// maximum length of the oracle array. New slots will be added when the array is fully populated.
/// Observations are overwritten when the full length of the oracle array is populated.
/// The most recent observation is available, independent of the length of the oracle array, by passing 0 to observe()
/// A minimum observation interval is enforced to make the choice of cardinality more meaningful. This is done by
/// only recording an observation if the time elapsed since the last observation is >= minInterval, and recording the data
/// into a separate "intermediate" observation slot otherwise to ensure tickCumulative is accurate.
library Oracle {
/// @notice Thrown when trying to interact with an Oracle of a non-initialized pool
error OracleCardinalityCannotBeZero();
/// @notice Thrown when trying to observe a price that is older than the oldest recorded price
/// @param oldestTimestamp Timestamp of the oldest remaining observation
/// @param targetTimestamp Invalid timestamp targeted to be observed
error TargetPredatesOldestObservation(uint32 oldestTimestamp, uint32 targetTimestamp);
/// @notice This is the max amount of ticks in either direction that the pool is allowed to move at one time
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 48 of 59 : IAmAmm.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.0;
import {PoolId} from "@uniswap/v4-core/src/types/PoolId.sol";
import {Currency} from "@uniswap/v4-core/src/types/Currency.sol";
interface IAmAmm {
error AmAmm__BidLocked();
error AmAmm__InvalidBid();
error AmAmm__NotEnabled();
error AmAmm__Unauthorized();
error AmAmm__InvalidDepositAmount();
event SubmitBid(
PoolId indexed id,
address indexed manager,
uint48 indexed blockIdx,
bytes6 payload,
uint128 rent,
uint128 deposit
);
event DepositIntoTopBid(PoolId indexed id, address indexed manager, uint128 amount);
event WithdrawFromTopBid(PoolId indexed id, address indexed manager, address indexed recipient, uint128 amount);
event DepositIntoNextBid(PoolId indexed id, address indexed manager, uint128 amount);
event WithdrawFromNextBid(PoolId indexed id, address indexed manager, address indexed recipient, uint128 amount);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 49 of 59 : IZone.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {IFloodPlain} from "./IFloodPlain.sol";
interface IZone {
struct FeeInfo {
address recipient;
uint64 bps;
}
/**
* @notice Check if a fulfiller belongs to the zone.
*
* @dev Fulfiller must still ensure that
* - msg.sender is a the BOOK.
* - Book caller is authorized.
*
* @param order Order being fulfilled.
* @param fulfiller The address that will fulfill the order by supplying consideration items.
*
* @return True if fulfiller is enabled, false if fulfiller is not enabled.
*/
function validate(IFloodPlain.Order calldata order, address fulfiller) external view returns (bool);
/**
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 50 of 59 : IFloodPlain.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";
interface IFloodPlain {
error InsufficientAmountReceived();
error NotAContract();
error ZoneDenied();
error DuplicateItems();
error ArrayLengthMismatch();
event OrderFulfilled(bytes32 indexed orderHash, address indexed zone, address indexed fulfiller, uint256 amountOut);
struct SignedOrder {
Order order;
bytes signature;
}
struct Order {
address offerer;
address zone;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 51 of 59 : IERC1271.sol
1
2
3
4
5
6
7
8
9
10
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IERC1271 {
/// @dev Should return whether the signature provided is valid for the provided data
/// @param hash Hash of the data to be signed
/// @param signature Signature byte array associated with _data
/// @return magicValue The bytes4 magic value 0x1626ba7e
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 52 of 59 : IBaseHook.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {BeforeSwapDelta} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol";
interface IBaseHook {
error NotPoolManager();
function poolManager() external view returns (IPoolManager);
/// @notice The hook called after the state of a pool is initialized
/// @param sender The initial msg.sender for the initialize call
/// @param key The key for the pool being initialized
/// @param sqrtPriceX96 The sqrt(price) of the pool as a Q64.96
/// @param tick The current tick after the state of a pool is initialized
/// @return bytes4 The function selector for the hook
function afterInitialize(address sender, PoolKey calldata key, uint160 sqrtPriceX96, int24 tick)
external
returns (bytes4);
/// @notice The hook called before a swap
/// @param sender The initial msg.sender for the swap call
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 53 of 59 : SSTORE2.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Read and write to persistent storage at a fraction of the cost.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SSTORE2.sol)
/// @author Saw-mon-and-Natalie (https://github.com/Saw-mon-and-Natalie)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)
/// @author Modified from SSTORE3 (https://github.com/Philogy/sstore3)
library SSTORE2 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The proxy initialization code.
uint256 private constant _CREATE3_PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3;
/// @dev Hash of the `_CREATE3_PROXY_INITCODE`.
/// Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`.
bytes32 internal constant CREATE3_PROXY_INITCODE_HASH =
0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 54 of 59 : SafeCastLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Safe integer casting library that reverts on overflow.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeCastLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol)
/// @dev Optimized for runtime gas for very high number of optimizer runs (i.e. >= 1000000).
library SafeCastLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unable to cast to the target type due to overflow.
error Overflow();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* UNSIGNED INTEGER SAFE CASTING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Casts `x` to a uint8. Reverts on overflow.
function toUint8(uint256 x) internal pure returns (uint8) {
if (x >= 1 << 8) _revertOverflow();
return uint8(x);
}
/// @dev Casts `x` to a uint16. Reverts on overflow.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 55 of 59 : ISignatureTransfer.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IEIP712} from "./IEIP712.sol";
/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer is IEIP712 {
/// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
/// @param maxAmount The maximum amount a spender can request to transfer
error InvalidAmount(uint256 maxAmount);
/// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
/// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
error LengthMismatch();
/// @notice Emits an event when the owner successfully invalidates an unordered nonce.
event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);
/// @notice The token and amount details for a transfer signed in the permit transfer signature
struct TokenPermissions {
// ERC20 token address
address token;
// the maximum amount that can be spent
uint256 amount;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 56 of 59 : Hooks.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {PoolKey} from "../types/PoolKey.sol";
import {IHooks} from "../interfaces/IHooks.sol";
import {SafeCast} from "./SafeCast.sol";
import {LPFeeLibrary} from "./LPFeeLibrary.sol";
import {BalanceDelta, toBalanceDelta, BalanceDeltaLibrary} from "../types/BalanceDelta.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "../types/BeforeSwapDelta.sol";
import {IPoolManager} from "../interfaces/IPoolManager.sol";
import {ParseBytes} from "./ParseBytes.sol";
import {CustomRevert} from "./CustomRevert.sol";
/// @notice V4 decides whether to invoke specific hooks by inspecting the least significant bits
/// of the address that the hooks contract is deployed to.
/// For example, a hooks contract deployed to address: 0x0000000000000000000000000000000000002400
/// has the lowest bits '10 0100 0000 0000' which would cause the 'before initialize' and 'after add liquidity' hooks to be used.
library Hooks {
using LPFeeLibrary for uint24;
using Hooks for IHooks;
using SafeCast for int256;
using BeforeSwapDeltaLibrary for BeforeSwapDelta;
using ParseBytes for bytes;
using CustomRevert for bytes4;
uint160 internal constant ALL_HOOK_MASK = uint160((1 << 14) - 1);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 57 of 59 : IEIP712.sol
1
2
3
4
5
6
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IEIP712 {
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 58 of 59 : LPFeeLibrary.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {CustomRevert} from "./CustomRevert.sol";
/// @notice Library of helper functions for a pools LP fee
library LPFeeLibrary {
using LPFeeLibrary for uint24;
using CustomRevert for bytes4;
/// @notice Thrown when the static or dynamic fee on a pool exceeds 100%.
error LPFeeTooLarge(uint24 fee);
/// @notice An lp fee of exactly 0b1000000... signals a dynamic fee pool. This isn't a valid static fee as it is > MAX_LP_FEE
uint24 public constant DYNAMIC_FEE_FLAG = 0x800000;
/// @notice the second bit of the fee returned by beforeSwap is used to signal if the stored LP fee should be overridden in this swap
// only dynamic-fee pools can return a fee via the beforeSwap hook
uint24 public constant OVERRIDE_FEE_FLAG = 0x400000;
/// @notice mask to remove the override fee flag from a fee returned by the beforeSwaphook
uint24 public constant REMOVE_OVERRIDE_MASK = 0xBFFFFF;
/// @notice the lp fee is represented in hundredths of a bip, so the max is 100%
uint24 public constant MAX_LP_FEE = 1000000;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 59 of 59 : ParseBytes.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Parses bytes returned from hooks and the byte selector used to check return selectors from hooks.
/// @dev parseSelector also is used to parse the expected selector
/// For parsing hook returns, note that all hooks return either bytes4 or (bytes4, 32-byte-delta) or (bytes4, 32-byte-delta, uint24).
library ParseBytes {
function parseSelector(bytes memory result) internal pure returns (bytes4 selector) {
// equivalent: (selector,) = abi.decode(result, (bytes4, int256));
assembly ("memory-safe") {
selector := mload(add(result, 0x20))
}
}
function parseFee(bytes memory result) internal pure returns (uint24 lpFee) {
// equivalent: (,, lpFee) = abi.decode(result, (bytes4, int256, uint24));
assembly ("memory-safe") {
lpFee := mload(add(result, 0x60))
}
}
function parseReturnDelta(bytes memory result) internal pure returns (int256 hookReturn) {
// equivalent: (, hookReturnDelta) = abi.decode(result, (bytes4, int256));
assembly ("memory-safe") {
hookReturn := mload(add(result, 0x40))
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Settings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"remappings": [
"@uniswap/v4-core/=lib/v4-core/",
"solmate/src/=lib/solmate/src/",
"solmate/utils/=lib/solmate/src/utils/",
"@ensdomains/=lib/v4-core/node_modules/@ensdomains/",
"@openzeppelin/=lib/v4-core/lib/openzeppelin-contracts/",
"@openzeppelin/contracts/=lib/v4-core/lib/openzeppelin-contracts/contracts/",
"biddog/=lib/biddog/src/",
"clones-with-immutable-args/=lib/clones-with-immutable-args/src/",
"create3-factory/=lib/create3-factory/",
"ds-test/=lib/clones-with-immutable-args/lib/ds-test/src/",
"erc4626-tests/=lib/v4-core/lib/openzeppelin-contracts/lib/erc4626-tests/",
"flood-contracts/=lib/flood-contracts/",
"forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/",
"forge-std/=lib/forge-std/src/",
"hardhat/=lib/v4-core/node_modules/hardhat/",
"leb128-nooffset/=lib/flood-contracts/lib/leb128-nooffset/src/",
"leb128/=lib/flood-contracts/lib/leb128-nooffset/src/",
"multicaller/=lib/multicaller/src/",
"openzeppelin-contracts/=lib/v4-core/lib/openzeppelin-contracts/",
"permit2/=lib/permit2/",
"solady/=lib/solady/src/",
"v4-core/=lib/v4-core/src/"
],
"optimizer": {
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Contract ABI

API
[{"inputs":[],"name":"AccountLocked","type":"error"},{"inputs":[],"name":"AllowanceOverflow","type":"error"},{"inputs":[],"name":"AllowanceUnderflow","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AlreadyLocked","type":"error"},{"inputs":[],"name":"AlreadyUnlocked","type":"error"},{"inputs":[],"name":"BalanceOverflow","type":"error"},{"inputs":[],"name":"BunniToken__NotBunniHub","type":"error"},{"inputs":[],"name":"BunniToken__NotPoolManager","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotUnlocker","type":"error"},{"inputs":[],"name":"PermitExpired","type":"error"},{"inputs":[],"name":"TotalSupplyOverflow","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"referrer","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward1","type":"uint256"}],"name":"ClaimReferralRewards","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"contract IERC20Unlocker","name":"unlocker","type":"address"}],"name":"Lock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"SetMetadataURI","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"contract IERC20Unlocker","name":"unlocker","type":"address"}],"name":"Unlock","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"result","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"claimReferralRewards","outputs":[{"internalType":"uint256","name":"reward0","type":"uint256"},{"internalType":"uint256","name":"reward1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isToken0","type":"bool"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"distributeReferralRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"getClaimableReferralRewards","outputs":[{"internalType":"uint256","name":"reward0","type":"uint256"},{"internalType":"uint256","name":"reward1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hooklet","outputs":[{"internalType":"contract IHooklet","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"hub","outputs":[{"internalType":"contract IBunniHub","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"incrementNonce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"string","name":"metadataURI_","type":"string"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isLocked","outputs":[{"internalType":"bool","name":"locked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Unlocker","name":"unlocker","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"metadataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"referrer","type":"address"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolKey","outputs":[{"components":[{"internalType":"Currency","name":"currency0","type":"address"},{"internalType":"Currency","name":"currency1","type":"address"},{"internalType":"uint24","name":"fee","type":"uint24"},{"internalType":"int24","name":"tickSpacing","type":"int24"},{"internalType":"contract IHooks","name":"hooks","type":"address"}],"internalType":"struct PoolKey","name":"","type":"tuple"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"poolManager","outputs":[{"internalType":"contract IPoolManager","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"referrerOf","outputs":[{"internalType":"address","name":"referrer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referrerRewardPerToken0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"referrerRewardPerToken1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"referrerRewardPerTokenPaid0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"referrerRewardPerTokenPaid1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"referrerRewardUnclaimed0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"referrerRewardUnclaimed1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"referrer","type":"address"}],"name":"scoreOf","outputs":[{"internalType":"uint256","name":"score","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"metadataURI_","type":"string"}],"name":"setMetadataURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"Currency","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"Currency","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"unlockCallback","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"unlockerOf","outputs":[{"internalType":"contract IERC20Unlocker","name":"unlocker","type":"address"}],"stateMutability":"view","type":"function"}]

Block Age Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Age Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Age Amount
View All Withdrawals

Transaction Hash Block Age Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.