ETH Price: $3,559.02 (-1.30%)

Contract

0xaaf29f2C9516062dc43c4465EF6d43cE8397CDDa

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Transfer Ownersh...200014092025-06-24 7:22:48140 days ago1750749768IN
0xaaf29f2C...E8397CDDa
0 ETH00.00010065
Set Surge Fee Mu...199646442025-06-23 21:10:03140 days ago1750713003IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000050.00184663
Set Surge Decay ...199638162025-06-23 20:56:15140 days ago1750712175IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000080.00205995
Set Max Base Fee199637282025-06-23 20:54:47140 days ago1750712087IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000090.00205592
Set Max Base Fee199636182025-06-23 20:52:57140 days ago1750711977IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000090.00206921
Set Min Base Fee199635502025-06-23 20:51:49140 days ago1750711909IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000090.00200228
Set Base Fee Fac...192987972025-06-16 4:12:36148 days ago1750047156IN
0xaaf29f2C...E8397CDDa
0 ETH00.00010057
Set Base Fee Fac...192984802025-06-16 4:07:19148 days ago1750046839IN
0xaaf29f2C...E8397CDDa
0 ETH00.00010056
Set Base Fee Fac...189265722025-06-11 20:48:51152 days ago1749674931IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000010.0001253
Set Pool POL Sha...188171842025-06-10 14:25:43153 days ago1749565543IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000030.00014884
Set Pool POL Sha...188159742025-06-10 14:05:33153 days ago1749564333IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000020.00015461
Set Pool POL Sha...187394202025-06-09 16:49:39154 days ago1749487779IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000010.00010067
Set Max Base Fee187393282025-06-09 16:48:07154 days ago1749487687IN
0xaaf29f2C...E8397CDDa
0 ETH0.000000010.00010067

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321081372025-11-11 10:21:361 min ago1762856496
0xaaf29f2C...E8397CDDa
0 ETH
321080992025-11-11 10:20:582 mins ago1762856458
0xaaf29f2C...E8397CDDa
0 ETH
321080992025-11-11 10:20:582 mins ago1762856458
0xaaf29f2C...E8397CDDa
0 ETH
321080992025-11-11 10:20:582 mins ago1762856458
0xaaf29f2C...E8397CDDa
0 ETH
321080992025-11-11 10:20:582 mins ago1762856458
0xaaf29f2C...E8397CDDa
0 ETH
321080992025-11-11 10:20:582 mins ago1762856458
0xaaf29f2C...E8397CDDa
0 ETH
321080992025-11-11 10:20:582 mins ago1762856458
0xaaf29f2C...E8397CDDa
0 ETH
321080942025-11-11 10:20:532 mins ago1762856453
0xaaf29f2C...E8397CDDa
0 ETH
321080942025-11-11 10:20:532 mins ago1762856453
0xaaf29f2C...E8397CDDa
0 ETH
321080942025-11-11 10:20:532 mins ago1762856453
0xaaf29f2C...E8397CDDa
0 ETH
321080942025-11-11 10:20:532 mins ago1762856453
0xaaf29f2C...E8397CDDa
0 ETH
321080942025-11-11 10:20:532 mins ago1762856453
0xaaf29f2C...E8397CDDa
0 ETH
321080942025-11-11 10:20:532 mins ago1762856453
0xaaf29f2C...E8397CDDa
0 ETH
321080752025-11-11 10:20:342 mins ago1762856434
0xaaf29f2C...E8397CDDa
0 ETH
321080752025-11-11 10:20:342 mins ago1762856434
0xaaf29f2C...E8397CDDa
0 ETH
321080752025-11-11 10:20:342 mins ago1762856434
0xaaf29f2C...E8397CDDa
0 ETH
321080752025-11-11 10:20:342 mins ago1762856434
0xaaf29f2C...E8397CDDa
0 ETH
321080652025-11-11 10:20:242 mins ago1762856424
0xaaf29f2C...E8397CDDa
0 ETH
321080652025-11-11 10:20:242 mins ago1762856424
0xaaf29f2C...E8397CDDa
0 ETH
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PoolPolicyManager

Compiler Version
v0.8.27+commit.40a35a09

Optimization Enabled:
Yes with 10000 runs

Other Settings:
cancun EvmVersion
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;

// - - - Solmate Deps - - -

import {Owned} from "solmate/src/auth/Owned.sol";

// - - - V4 Deps - - -

import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol";

// - - - Project Deps - - -

import {PrecisionConstants} from "./libraries/PrecisionConstants.sol";
import {Errors} from "./errors/Errors.sol";
import {PolicyManagerErrors} from "./errors/PolicyManagerErrors.sol";
import {IPoolPolicyManager} from "./interfaces/IPoolPolicyManager.sol";

/// @title PoolPolicyManager
/// @notice Consolidated policy manager implementing the IPoolPolicyManager interface
/// @dev Handles all policy functionality for pool configuration and fee management
contract PoolPolicyManager is IPoolPolicyManager, Owned {
    // === Constants ===

    uint24 private constant MIN_TRADING_FEE = 100; // 0.01%
    uint24 private constant MAX_TRADING_FEE = 50_000; // 5%

    uint32 private constant DEFAULT_CAP_BUDGET_DECAY_WINDOW = 15_552_000;
    uint32 private constant DEFAULT_SURGE_DECAY_PERIOD_SECONDS = 3600;
    uint24 private constant DEFAULT_SURGE_FEE_MULTIPLIER_PPM = 3_000_000;

    uint24 private constant DEFAULT_MAX_TICKS_PER_BLOCK = 50;

    /// @notice Maximum step for base fee updates (10% per step)
    uint32 private constant MAX_STEP_PPM = 100_000;

    /// @notice Default base fee step size (2% per step)
    uint32 private constant DEFAULT_BASE_FEE_STEP_PPM = 20_000;

    /// @notice Default base fee update interval (1 day)
    uint32 private constant DEFAULT_BASE_FEE_UPDATE_INTERVAL_SECS = 1 days;

    /// @notice Default base fee factor (1 tick = 100 PPM)
    uint32 private constant DEFAULT_BASE_FEE_FACTOR_PPM = 100;

    /// @notice Maximum base fee factor to prevent overflow (1 tick = 1000 PPM max)
    uint32 private constant MAX_BASE_FEE_FACTOR_PPM = 1000;

    // === Dynamic Fee Configuration Struct ===

    struct DynamicFeeConfig {
        uint32 capBudgetDecayWindow;
        uint24 minBaseFeePpm;
        uint24 maxBaseFeePpm;
        uint32 surgeDecayPeriodSeconds;
        uint24 surgeFeeMultiplierPpm;
    }

    struct BaseFeeParams {
        uint32 stepPpm;
        uint32 updateIntervalSecs;
    }

    // === State Variables ===

    /// @notice Manual fee override per pool (if non-zero)
    mapping(PoolId => uint24) private _poolManualFee;

    /// @notice Flag to indicate if a manual fee is set for a pool
    mapping(PoolId => bool) private _hasPoolManualFee;

    /// @notice Pool-specific POL share percentages
    mapping(PoolId => uint256) private _poolPolSharePpm;

    /// @notice Pool-specific dynamic fee configurations
    mapping(PoolId => DynamicFeeConfig) private _poolDynamicFeeConfig;

    /// @notice Base fee parameters per pool
    mapping(PoolId => BaseFeeParams) private _poolBaseFeeParams;

    /// @notice Default daily budget for CAP events (ppm/day) 1e6 is 1 per day, 1e7 is 10 per day
    uint32 private _defaultCapBudgetDailyPpm;

    /// @notice Pool-specific daily budget for CAP events (0 means use default)
    mapping(PoolId => uint32) private _poolCapBudgetDailyPpm;

    /// @notice Linear decay half-life for the budget counter (seconds)
    uint32 private _capBudgetDecayWindow;

    /// @notice Pool-specific base fee factor for converting oracle ticks to PPM
    mapping(PoolId => uint32) private _poolBaseFeeFactor;

    /// @notice Constructor initializes the policy manager with default values
    /// @param _governance The owner of the contract
    /// @param _dailyBudget Initial daily budget
    constructor(address _governance, uint256 _dailyBudget) Owned(_governance) {
        if (_governance == address(0)) revert Errors.ZeroAddress();
        // Initialize global parameters
        _defaultCapBudgetDailyPpm = _dailyBudget == 0 ? 1_000_000 : uint32(_dailyBudget);
        _capBudgetDecayWindow = 15_552_000; // 180 days
    }

    // === Fee Allocation Functions ===

    /// @inheritdoc IPoolPolicyManager
    function setPoolPOLShare(PoolId poolId, uint256 newPolSharePpm) external override onlyOwner {
        // Validate POL share is within valid range (0-100%)
        if (newPolSharePpm > PrecisionConstants.PPM_SCALE) {
            revert Errors.ParameterOutOfRange(newPolSharePpm, 0, PrecisionConstants.PPM_SCALE);
        }

        uint256 oldShare = _poolPolSharePpm[poolId];
        if (oldShare != newPolSharePpm) {
            _poolPolSharePpm[poolId] = newPolSharePpm;
            emit PoolPOLShareChanged(poolId, newPolSharePpm);
        }
    }

    /// @inheritdoc IPoolPolicyManager
    function getPoolPOLShare(PoolId poolId) external view override returns (uint256 poolSpecificPolShare) {
        poolSpecificPolShare = _poolPolSharePpm[poolId];
    }

    // === Manual Fee Override Functions ===

    /// @inheritdoc IPoolPolicyManager
    function getManualFee(PoolId poolId) external view override returns (uint24 manualFee, bool isSet) {
        return (_poolManualFee[poolId], _hasPoolManualFee[poolId]);
    }

    /// @inheritdoc IPoolPolicyManager
    function setManualFee(PoolId poolId, uint24 manualFee) external override onlyOwner {
        if (manualFee < MIN_TRADING_FEE || manualFee > MAX_TRADING_FEE) {
            revert Errors.ParameterOutOfRange(manualFee, MIN_TRADING_FEE, MAX_TRADING_FEE);
        }

        _poolManualFee[poolId] = manualFee;
        _hasPoolManualFee[poolId] = true;

        emit ManualFeeSet(poolId, manualFee);
    }

    /// @inheritdoc IPoolPolicyManager
    function clearManualFee(PoolId poolId) external override onlyOwner {
        if (_hasPoolManualFee[poolId]) {
            _poolManualFee[poolId] = 0;
            _hasPoolManualFee[poolId] = false;

            emit ManualFeeSet(poolId, 0);
        }
    }

    // === Dynamic Fee Configuration Getters ===

    /// @inheritdoc IPoolPolicyManager
    function getMinBaseFee(PoolId poolId) external view override returns (uint24) {
        if (_poolDynamicFeeConfig[poolId].minBaseFeePpm != 0) {
            return _poolDynamicFeeConfig[poolId].minBaseFeePpm;
        }
        return MIN_TRADING_FEE;
    }

    /// @inheritdoc IPoolPolicyManager
    function getMaxBaseFee(PoolId poolId) external view override returns (uint24) {
        if (_poolDynamicFeeConfig[poolId].maxBaseFeePpm != 0) {
            return _poolDynamicFeeConfig[poolId].maxBaseFeePpm;
        }
        return MAX_TRADING_FEE;
    }

    /// @inheritdoc IPoolPolicyManager
    function getSurgeDecayPeriodSeconds(PoolId poolId) external view override returns (uint32) {
        if (_poolDynamicFeeConfig[poolId].surgeDecayPeriodSeconds != 0) {
            return _poolDynamicFeeConfig[poolId].surgeDecayPeriodSeconds;
        }
        return DEFAULT_SURGE_DECAY_PERIOD_SECONDS;
    }

    /// @inheritdoc IPoolPolicyManager
    function getSurgeFeeMultiplierPpm(PoolId poolId) external view override returns (uint24) {
        if (_poolDynamicFeeConfig[poolId].surgeFeeMultiplierPpm != 0) {
            return _poolDynamicFeeConfig[poolId].surgeFeeMultiplierPpm;
        }
        return DEFAULT_SURGE_FEE_MULTIPLIER_PPM;
    }

    /// @inheritdoc IPoolPolicyManager
    function getDefaultDailyBudgetPpm() external view override returns (uint32) {
        return _defaultCapBudgetDailyPpm;
    }

    /// @inheritdoc IPoolPolicyManager
    function getDailyBudgetPpm(PoolId poolId) external view override returns (uint32) {
        uint32 poolBudget = _poolCapBudgetDailyPpm[poolId];
        return poolBudget == 0 ? _defaultCapBudgetDailyPpm : poolBudget;
    }

    /// @inheritdoc IPoolPolicyManager
    function getCapBudgetDecayWindow(PoolId poolId) external view override returns (uint32) {
        if (_poolDynamicFeeConfig[poolId].capBudgetDecayWindow != 0) {
            return _poolDynamicFeeConfig[poolId].capBudgetDecayWindow;
        }
        return _capBudgetDecayWindow;
    }

    /// @inheritdoc IPoolPolicyManager
    function getDefaultMaxTicksPerBlock(PoolId) external pure override returns (uint24) {
        return DEFAULT_MAX_TICKS_PER_BLOCK;
    }

    /// @inheritdoc IPoolPolicyManager
    function getBaseFeeStepPpm(PoolId poolId) public view override returns (uint32) {
        uint32 val = _poolBaseFeeParams[poolId].stepPpm;
        return val == 0 ? DEFAULT_BASE_FEE_STEP_PPM : val;
    }

    /// @inheritdoc IPoolPolicyManager
    function getBaseFeeUpdateIntervalSeconds(PoolId poolId) public view override returns (uint32) {
        uint32 val = _poolBaseFeeParams[poolId].updateIntervalSecs;
        return val == 0 ? DEFAULT_BASE_FEE_UPDATE_INTERVAL_SECS : val;
    }

    /// @inheritdoc IPoolPolicyManager
    function getBaseFeeFactor(PoolId poolId) external view override returns (uint32) {
        uint32 factor = _poolBaseFeeFactor[poolId];
        return factor == 0 ? DEFAULT_BASE_FEE_FACTOR_PPM : factor;
    }

    // === Dynamic Fee Configuration Setters ===

    /// @inheritdoc IPoolPolicyManager
    function setMinBaseFee(PoolId poolId, uint24 newMinFee) external override onlyOwner {
        uint24 maxFee = this.getMaxBaseFee(poolId);
        if (newMinFee < MIN_TRADING_FEE || newMinFee > maxFee) {
            revert PolicyManagerErrors.InvalidFeeRange(newMinFee, MIN_TRADING_FEE, maxFee);
        }
        _poolDynamicFeeConfig[poolId].minBaseFeePpm = newMinFee;
        emit MinBaseFeeSet(poolId, newMinFee);
    }

    /// @inheritdoc IPoolPolicyManager
    function setMaxBaseFee(PoolId poolId, uint24 newMaxFee) external override onlyOwner {
        uint24 minFee = this.getMinBaseFee(poolId);
        if (newMaxFee < minFee || newMaxFee > MAX_TRADING_FEE) {
            revert PolicyManagerErrors.InvalidFeeRange(newMaxFee, minFee, MAX_TRADING_FEE);
        }
        _poolDynamicFeeConfig[poolId].maxBaseFeePpm = newMaxFee;
        emit MaxBaseFeeSet(poolId, newMaxFee);
    }

    /// @inheritdoc IPoolPolicyManager
    function setCapBudgetDecayWindow(PoolId poolId, uint32 newCapBudgetDecayWindow) external override onlyOwner {
        if (newCapBudgetDecayWindow == 0 || newCapBudgetDecayWindow > type(uint32).max) {
            revert Errors.ParameterOutOfRange(newCapBudgetDecayWindow, 1, type(uint32).max);
        }

        _poolDynamicFeeConfig[poolId].capBudgetDecayWindow = newCapBudgetDecayWindow;
        emit CapBudgetDecayWindowSet(poolId, newCapBudgetDecayWindow);
    }

    /// @inheritdoc IPoolPolicyManager
    function setSurgeDecayPeriodSeconds(PoolId poolId, uint32 newSurgeDecayPeriodSeconds) external override onlyOwner {
        if (newSurgeDecayPeriodSeconds < 60 || newSurgeDecayPeriodSeconds > 1 days) {
            revert Errors.ParameterOutOfRange(newSurgeDecayPeriodSeconds, 60, 1 days);
        }

        _poolDynamicFeeConfig[poolId].surgeDecayPeriodSeconds = newSurgeDecayPeriodSeconds;
        emit SurgeDecayPeriodSet(poolId, newSurgeDecayPeriodSeconds);
    }

    /// @inheritdoc IPoolPolicyManager
    function setSurgeFeeMultiplierPpm(PoolId poolId, uint24 multiplier) external override onlyOwner {
        if (multiplier == 0 || multiplier > 3_000_000) revert Errors.ParameterOutOfRange(multiplier, 1, 3_000_000);

        _poolDynamicFeeConfig[poolId].surgeFeeMultiplierPpm = multiplier;
        emit SurgeFeeMultiplierSet(poolId, multiplier);
    }

    /// @inheritdoc IPoolPolicyManager
    function setBaseFeeParams(PoolId poolId, uint32 stepPpm, uint32 updateIntervalSecs) external override onlyOwner {
        if (stepPpm > MAX_STEP_PPM) revert Errors.ParameterOutOfRange(stepPpm, 0, MAX_STEP_PPM);
        if (updateIntervalSecs == 0) {
            revert Errors.ParameterOutOfRange(updateIntervalSecs, 1, type(uint32).max);
        }

        _poolBaseFeeParams[poolId] = BaseFeeParams({stepPpm: stepPpm, updateIntervalSecs: updateIntervalSecs});

        emit BaseFeeParamsSet(poolId, stepPpm, updateIntervalSecs);
    }

    /// @inheritdoc IPoolPolicyManager
    function setDailyBudgetPpm(uint32 newCapBudgetDailyPpm) external override onlyOwner {
        if (newCapBudgetDailyPpm == 0 || newCapBudgetDailyPpm > 10 * PrecisionConstants.PPM_SCALE) {
            revert Errors.ParameterOutOfRange(newCapBudgetDailyPpm, 1, 10 * PrecisionConstants.PPM_SCALE);
        }
        _defaultCapBudgetDailyPpm = newCapBudgetDailyPpm;
        emit DailyBudgetSet(newCapBudgetDailyPpm);
    }

    /// @inheritdoc IPoolPolicyManager
    function setPoolDailyBudgetPpm(PoolId poolId, uint32 newBudget) external override onlyOwner {
        // Validate: 0 means "use default", or 1 to 10*PPM_SCALE
        if (newBudget != 0 && (newBudget < 1 || newBudget > 10 * PrecisionConstants.PPM_SCALE)) {
            revert Errors.ParameterOutOfRange(newBudget, 1, 10 * PrecisionConstants.PPM_SCALE);
        }

        _poolCapBudgetDailyPpm[poolId] = newBudget;
        emit PoolDailyBudgetSet(poolId, newBudget);
    }

    /// @inheritdoc IPoolPolicyManager
    function setDecayWindow(uint32 newCapBudgetDecayWindow) external override onlyOwner {
        if (newCapBudgetDecayWindow == 0) revert PolicyManagerErrors.ZeroValue();
        _capBudgetDecayWindow = newCapBudgetDecayWindow;
        emit GlobalDecayWindowSet(newCapBudgetDecayWindow);
    }

    /// @inheritdoc IPoolPolicyManager
    function setBaseFeeFactor(PoolId poolId, uint32 factor) external override onlyOwner {
        // Validate factor is reasonable (0 means use default)
        if (factor != 0 && (factor < 1 || factor > MAX_BASE_FEE_FACTOR_PPM)) {
            revert Errors.ParameterOutOfRange(factor, 1, MAX_BASE_FEE_FACTOR_PPM);
        }

        _poolBaseFeeFactor[poolId] = factor;
        emit BaseFeeFactorSet(poolId, factor);
    }
}

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnershipTransferred(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

// 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)
        }
    }
}

File 4 of 16 : PrecisionConstants.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.27;

/// @title PrecisionConstants
/// @notice Centralized library for precision-related constants used throughout the protocol
/// @dev This ensures consistency in scaling factors across all contracts
library PrecisionConstants {
    /// @notice Standard high-precision scaling factor (10^18)
    /// @dev Used for interest rates, LTV ratios, and other high-precision calculations
    uint256 internal constant PRECISION = 1e18;

    /// @notice Parts-per-million scaling factor (10^6)
    /// @dev Used for fee percentages, allocation shares, and other percentage-based calculations
    uint256 internal constant PPM_SCALE = 1e6;
}

File 5 of 16 : Errors.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {PoolId} from "v4-core/src/types/PoolId.sol";

// TODO: cleanup unused errors

/**
 * @title Errors
 * @notice Collection of all custom errors used in the protocol
 */
library Errors {
    // --- Access Control ---
    error AccessDenied();
    error AccessOnlyGovernance(address caller);
    error AccessOnlyPoolManager(address caller);
    error AccessNotAuthorized(address caller);
    error AccessOnlyEmergencyAdmin(address caller);
    error Unauthorized();
    error CallerNotPoolManager(address caller);
    error CallerNotMarginContract();
    error AccessOnlyOwner(address caller);
    error UnauthorizedCaller(address caller);
    error GovernanceNotInitialized();
    error HookAddressAlreadySet();
    error InvalidHookAddress();
    error ZeroDestination();
    error NotPoolManager();

    // --- Validation & Input ---
    error InvalidHookAuthorization(address expected, address actual);
    error PoolPositionManagerMismatch();
    error ValidationDeadlinePassed(uint32 deadline, uint32 blockTime);
    error ValidationZeroAddress(string target);
    error ValidationInvalidInput(string reason);
    error ValidationZeroAmount(string parameter);
    error ValidationInvalidLength(string parameter);
    error ValidationInvalidAddress(address target);
    error ValidationInvalidRange(string parameter);
    error ValidationInvalidFee(uint24 fee);
    error ValidationInvalidTickSpacing(int24 tickSpacing);
    error ValidationInvalidTick(int24 tick);
    error ValidationInvalidSlippage(uint256 slippage);
    error ParameterOutOfRange(uint256 value, uint256 min, uint256 max);
    error DeadlinePassed(uint32 deadline, uint32 blockTime);
    error ArrayLengthMismatch();
    error InvalidCallbackSalt();
    error InvalidPolicyImplementationsLength(uint256 length);
    error NotInitialized();
    error AlreadyInitialized(string component);
    error ReinvestmentDisabled();
    error RateLimited();
    error InvalidPoolKey();
    error InvalidPoolId();
    error InvalidTwapPeriod();
    error InvalidTickTolerance();
    error ZeroAddress();
    error ZeroAmount();
    error ZeroLiquidity();
    error ZeroShares();
    error ZeroPolicyManagerAddress();
    error ZeroPoolManagerAddress();
    error ZeroFullRangeAddress();
    error InvalidCallbackType(uint8 callbackType);
    error InvalidTickRange();
    error InvalidParameter(string parameterName, uint256 value);
    error ExpiryTooSoon(uint256 expiry, uint256 requiredTime);
    error ExpiryTooFar(uint256 expiry, uint256 requiredTime);

    // --- Math & Calculation ---
    error DivisionByZero();
    error Overflow();
    error Underflow();
    error InvalidCalculation();
    error InvalidConversion();
    error InvalidRatio();
    error InvalidAmount();
    error InvalidShare();
    error InvalidPercentage();
    error InvalidFee();
    error InvalidPrice(uint160 sqrtPriceX96);
    error InvalidLiquidity();
    error InvalidInput();
    error StaleOracle();
    error FeeTooHigh();
    error AmountTooLarge(uint256 amount, uint256 maximum);
    error SlippageExceeded(uint256 required, uint256 actual);
    error CalculationError(string reason);
    error MathOverflow();
    error MathUnderflow();
    error InsufficientInitialLiquidity();

    // --- System & State ---
    error HookDispatchFailed(bytes4 selector);
    error DelegateCallFailed();
    error NotImplemented();
    error ContractPaused();
    error InternalError(string message);
    error InconsistentState(string reason);

    // --- Pool State & Operations ---
    error PoolNotInitialized(bytes32 poolId);
    error PoolAlreadyInitialized(bytes32 poolId);
    error PoolNotFound(PoolId poolId);
    error PoolPaused(bytes32 poolId);
    error PoolLocked(bytes32 poolId);
    error PoolInvalidState(bytes32 poolId);
    error PoolInvalidOperation(bytes32 poolId);
    error PoolInvalidParameter(bytes32 poolId);
    error PoolUnsupportedFee(uint24 fee);
    error PoolUnsupportedTickSpacing(int24 tickSpacing);
    error PoolInvalidFeeOrTickSpacing(uint24 fee, int24 tickSpacing);
    error PoolTickOutOfRange(int24 tick, int24 minTick, int24 maxTick);
    error PoolInEmergencyState(bytes32 poolId);
    error PoolInvalidStateTransition(bytes32 poolId, string currentState, string targetState);
    error OnlyDynamicFeePoolAllowed();
    error FailedToReadPoolData(PoolId poolId);
    error PoolKeyAlreadyStored(bytes32 poolId);

    // --- Liquidity & Shares ---
    error PositionNotFound(PoolId poolId);
    error InsufficientAmount(uint256 requested, uint256 available);
    error InsufficientLiquidity(uint256 requested, uint256 available);
    error InsufficientShares(uint256 requested, uint256 available);
    error InsufficientBalance(uint256 requested, uint256 available);
    error InsufficientAllowance(uint256 requested, uint256 available);
    error LiquidityOverflow();
    error LiquidityUnderflow();
    error LiquidityLocked();
    error LiquidityRangeTooWide();
    error LiquidityRangeTooNarrow();
    error LiquidityAlreadyExists();
    error LiquidityDoesNotExist();
    error LiquidityNotAvailable();
    error DepositTooSmall();
    error InitialDepositTooSmall(uint256 minAmount, uint256 actualAmount);
    error WithdrawAmountTooSmall();

    // --- Policy ---
    error PolicyNotFound();
    error PolicyAlreadyExists();
    error PolicyInvalidState();
    error PolicyInvalidParameter();
    error PolicyInvalidOperation();
    error PolicyUnauthorized();
    error PolicyLocked();
    error PolicyExpired();
    error PolicyNotActive();
    error PolicyNotImplemented();
    error AllocationSumError(uint256 polShare, uint256 expected);

    // --- Hooks ---
    error HookNotFound();
    error HookAlreadyExists();
    error HookInvalidState();
    error HookInvalidParameter();
    error HookInvalidOperation();
    error HookUnauthorized();
    error HookLocked();
    error HookExpired();
    error HookNotActive();
    error HookNotImplemented();
    error HookInvalidAddress(address hook);
    error HookOnlyInitialization();
    error HookOnlyModifyLiquidity();
    error HookOnlySwap();
    error HookOnlyDonate();
    error HookNotSet();

    // --- Token & ETH Transfers ---
    error TokenNotFound();
    error TokenAlreadyExists();
    error TokenInvalidState();
    error TokenInvalidParameter();
    error TokenInvalidOperation();
    error TokenUnauthorized();
    error TokenLocked();
    error TokenExpired();
    error TokenNotActive();
    error TokenNotImplemented();
    error TokenTransferFailed();
    error TokenApprovalFailed();
    error TokenEthNotAccepted();
    error TokenInsufficientEth(uint256 required, uint256 provided);
    error TokenEthTransferFailed(address to, uint256 amount);
    error NonzeroNativeValue();
    error InsufficientETH(uint256 required, uint256 provided);
    error InsufficientContractBalance(uint256 required, uint256 available);
    error ETHTransferFailed();
    error TransferFailed();
    error TransferFromFailed();
    error InsufficientReserves();
    error TooLittleAmount0(uint256 min, uint256 actual);
    error TooLittleAmount1(uint256 min, uint256 actual);

    // --- Oracle ---
    error OracleOperationFailed(string operation, string reason);
    error OracleNotInitialized(PoolId poolId);
    error OracleUpdateFailed(PoolId poolId, string reason);
    error OraclePriceInvalid(uint160 sqrtPriceX96);
    error OracleTickInvalid(int24 tick);
    error OracleCapExceeded(PoolId poolId, int24 tick, int24 maxMove);

    // --- Fee Reinvestment ---
    error FeeExtractionFailed(string reason);
    error InvalidPolPercentage(uint256 provided, uint256 min, uint256 max);
    error PoolSpecificPolPercentageNotAllowed();
    error InvalidFeeDistribution(uint256 polShare, uint256 lpShare, uint256 expected);
    error PoolReinvestmentBlocked(PoolId poolId);
    error CollectionIntervalTooShort(uint256 provided, uint256 minimum);
    error CollectionIntervalTooLong(uint256 provided, uint256 maximum);
    error HookCallbackFailed(string reason);
    error FeesNotAvailable();
    error ExtractionAmountExceedsFees();
    error CacheStale(uint32 lastUpdate, uint32 currentTime, uint32 maxAge);
    error FeeReinvestNotAuthorized(address caller);
    error CannotWithdrawProtocolFees();
    error ReinvestmentAmountTooSmall(uint256 amount0, uint256 amount1);
    error ReinvestmentCooldownNotMet(uint64 lastReinvest, uint64 cooldown);
    error ReinvestmentThresholdNotMet(uint256 balance0, uint256 balance1, uint256 min0, uint256 min1);

    // --- Margin & Vault ---
    error WithdrawalWouldMakeVaultInsolvent();
    error NoDebtToRepay();
    error DepositFailed();
    error InsufficientCollateral(uint256 debt, uint256 collateral, uint256 threshold);
    error PoolUtilizationTooHigh();
    error InsufficientPhysicalShares(uint256 requested, uint256 available);
    error InterestModelNotSet();
    error MarginContractNotSet();
    error RepayAmountExceedsDebt(uint256 sharesToRepay, uint256 currentDebtShares);
    error DepositForRepayFailed();
    error InvalidAsset();
    error MaxPoolUtilizationExceeded(uint256 currentUtilization, uint256 maxUtilization);

    // --- Liquidation ---
    error NotLiquidatable(uint256 currentRatio, uint256 threshold);
    error LiquidationTooSmall(uint256 requestedAmount, uint256 minimumAmount);
    error InvalidLiquidationParams();

    // --- Invariants ---

    error InvalidSwapDelta();
    error ETHRefundFailed();
    error InvariantETHTransferFailed();
}

File 6 of 16 : PolicyManagerErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

import {PoolId, PoolIdLibrary} from "v4-core/src/types/PoolId.sol";

/**
 * @title Errors
 * @notice Custom errors used throughout the Spot system
 */
library PolicyManagerErrors {
    // === General errors ===
    error ZeroAddress();
    error UnauthorizedCaller(address caller);
    error ETHRefundFailed();
    error ParameterOutOfRange(uint256 value, uint256 min, uint256 max);
    error AllocationSumError(uint256 pol, uint256 fullRange, uint256 lp, uint256 expected);
    error InvalidFeeRange(uint24 value, uint24 min, uint24 max);
    error ZeroValue();

    // === Pool-specific errors ===
    error PoolNotFound(PoolId poolId);
    error PositionNotFound(PoolId poolId);
    error PoolPositionManagerMismatch();
    error InvalidHookAuthorization(address expected, address actual);

    // === Liquidity operations errors ===
    error TooLittleAmount0(uint256 minimum, uint256 actual);
    error TooLittleAmount1(uint256 minimum, uint256 actual);
    error InsufficientETH(uint256 required, uint256 provided);
    error InvalidPrice(uint160 price);
    error InvalidSwapDelta();

    // === Manual fee errors ===
    error ManualFeeNotSet(PoolId poolId);
    error ManualFeeAlreadySet(PoolId poolId);
}

// SPDX-License-Identifier: MIT
pragma solidity >=0.5.0;

import {PoolId} from "v4-core/src/types/PoolId.sol";

/// @title IPoolPolicyManager
/// @notice Consolidated interface for all policy types in the Spot system
/// @dev Combines fee, tick scaling, v-tier, and various other policies into a single interface
interface IPoolPolicyManager {
    /// === Events ===

    /// @notice Emitted when a pool's POL share is changed
    /// @param poolId The ID of the pool
    /// @param polSharePpm The new POL share in PPM
    event PoolPOLShareChanged(PoolId indexed poolId, uint256 polSharePpm);

    /// @notice Emitted when the daily budget is set
    /// @param newBudget The new daily budget
    event DailyBudgetSet(uint32 newBudget);

    /// @notice Emitted when a pool-specific daily budget is set
    /// @param poolId The pool ID
    /// @param newBudget The new daily budget
    event PoolDailyBudgetSet(PoolId indexed poolId, uint32 newBudget);

    /// @notice Emitted when base fee parameters are set
    /// @param poolId The ID of the pool
    /// @param stepPpm The step size in PPM
    /// @param updateIntervalSecs The update interval in seconds
    event BaseFeeParamsSet(PoolId indexed poolId, uint32 stepPpm, uint32 updateIntervalSecs);

    /// @notice Emitted when a manual fee is set for a pool
    /// @param poolId The ID of the pool
    /// @param manualFee The manual fee in PPM
    event ManualFeeSet(PoolId indexed poolId, uint24 manualFee);

    /// @notice Emitted when the minimum base fee is set for a pool
    /// @param poolId The ID of the pool
    /// @param minBaseFeePpm The new minimum base fee in PPM
    event MinBaseFeeSet(PoolId indexed poolId, uint24 minBaseFeePpm);

    /// @notice Emitted when the maximum base fee is set for a pool
    /// @param poolId The ID of the pool
    /// @param maxBaseFeePpm The new maximum base fee in PPM
    event MaxBaseFeeSet(PoolId indexed poolId, uint24 maxBaseFeePpm);

    /// @notice Emitted when the cap budget decay window is set for a pool
    /// @param poolId The ID of the pool
    /// @param decayWindow The new decay window in seconds
    event CapBudgetDecayWindowSet(PoolId indexed poolId, uint32 decayWindow);

    /// @notice Emitted when the surge decay period is set for a pool
    /// @param poolId The ID of the pool
    /// @param decayPeriod The new decay period in seconds
    event SurgeDecayPeriodSet(PoolId indexed poolId, uint32 decayPeriod);

    /// @notice Emitted when the surge fee multiplier is set for a pool
    /// @param poolId The ID of the pool
    /// @param multiplier The new multiplier in PPM
    event SurgeFeeMultiplierSet(PoolId indexed poolId, uint24 multiplier);

    /// @notice Emitted when the global decay window is set
    /// @param decayWindow The new decay window in seconds
    event GlobalDecayWindowSet(uint32 decayWindow);

    /// @notice Emitted when the base fee factor is set for a pool
    /// @param poolId The pool ID
    /// @param factor The new base fee factor
    event BaseFeeFactorSet(PoolId indexed poolId, uint32 factor);

    /// === Fee Configuration Functions ===

    /// @notice Sets the POL share percentage for a specific pool
    /// @param poolId The pool ID
    /// @param polSharePpm The POL share in PPM (parts per million)
    function setPoolPOLShare(PoolId poolId, uint256 polSharePpm) external;

    /// @notice Gets the POL share percentage for a specific pool
    /// @param poolId The pool ID to get the POL share for
    /// @return The POL share in PPM (parts per million)
    function getPoolPOLShare(PoolId poolId) external view returns (uint256);

    /// === Manual Fee Functions ===

    /// @notice Gets the manual fee for a pool, if set
    /// @param poolId The pool ID to get the manual fee for
    /// @return manualFee The manual fee in PPM, 0 if not set
    /// @return isSet Whether a manual fee is set for this pool
    function getManualFee(PoolId poolId) external view returns (uint24 manualFee, bool isSet);

    /// @notice Sets a manual fee for a pool, overriding the dynamic fee calculation
    /// @param poolId The pool ID
    /// @param manualFee The manual fee in PPM
    function setManualFee(PoolId poolId, uint24 manualFee) external;

    /// @notice Clears a manual fee for a pool, reverting to dynamic fee calculation
    /// @param poolId The pool ID
    function clearManualFee(PoolId poolId) external;

    /// === Dynamic Fee Configuration Functions ===

    /// @notice Returns the surge decay period in seconds for the given pool
    /// @param poolId The pool ID
    /// @return Surge decay period in seconds
    function getSurgeDecayPeriodSeconds(PoolId poolId) external view returns (uint32);

    /// @notice Gets the default/global/fallback daily budget for CAP events
    /// @return The default daily budget in PPM
    function getDefaultDailyBudgetPpm() external view returns (uint32);

    /// @notice Returns the daily budget for CAP events in PPM for the given pool
    /// @param poolId The pool ID
    /// @return Daily budget in PPM
    function getDailyBudgetPpm(PoolId poolId) external view returns (uint32);

    /// @notice Returns the budget decay window in seconds for the given pool
    /// @param poolId The pool ID
    /// @return Budget decay window in seconds
    function getCapBudgetDecayWindow(PoolId poolId) external view returns (uint32);

    /// @notice Returns the minimum base fee in PPM for the given pool
    /// @param poolId The pool ID
    /// @return Minimum base fee in PPM
    function getMinBaseFee(PoolId poolId) external view returns (uint24);

    /// @notice Returns the maximum base fee in PPM for the given pool
    /// @param poolId The pool ID
    /// @return Maximum base fee in PPM
    function getMaxBaseFee(PoolId poolId) external view returns (uint24);

    /// @notice Returns the surge fee multiplier in PPM for the given pool
    /// @param poolId The pool ID
    /// @return Surge fee multiplier in PPM
    function getSurgeFeeMultiplierPpm(PoolId poolId) external view returns (uint24);

    /// @notice Returns the default maximum ticks per block for a pool
    /// @param poolId The pool ID
    /// @return Default maximum ticks per block
    function getDefaultMaxTicksPerBlock(PoolId poolId) external view returns (uint24);

    /// @notice Returns the base fee step size in PPM for the given pool
    /// @param poolId The pool ID
    /// @return Base fee step size in PPM
    function getBaseFeeStepPpm(PoolId poolId) external view returns (uint32);

    /// @notice Returns the base fee update interval in seconds for the given pool
    /// @param poolId The pool ID
    /// @return Base fee update interval in seconds
    function getBaseFeeUpdateIntervalSeconds(PoolId poolId) external view returns (uint32);

    /// @notice Gets the base fee factor for converting oracle ticks to fee PPM
    /// @param poolId The pool ID
    function getBaseFeeFactor(PoolId poolId) external view returns (uint32);

    /// === Dynamic Fee Setter Functions ===

    /// @notice Sets the cap budget decay window for a pool
    /// @param poolId The pool ID
    /// @param decayWindow The decay window in seconds
    function setCapBudgetDecayWindow(PoolId poolId, uint32 decayWindow) external;

    /// @notice Sets the minimum base fee for a pool
    /// @param poolId The pool ID
    /// @param minBaseFee The minimum base fee in PPM
    function setMinBaseFee(PoolId poolId, uint24 minBaseFee) external;

    /// @notice Sets the maximum base fee for a pool
    /// @param poolId The pool ID
    /// @param maxBaseFee The maximum base fee in PPM
    function setMaxBaseFee(PoolId poolId, uint24 maxBaseFee) external;

    /// @notice Sets the surge decay period in seconds for a pool
    /// @param poolId The pool ID
    /// @param surgeDecaySeconds The surge decay period in seconds
    function setSurgeDecayPeriodSeconds(PoolId poolId, uint32 surgeDecaySeconds) external;

    /// @notice Sets the surge fee multiplier for a pool
    /// @param poolId The pool ID
    /// @param multiplier The surge fee multiplier in PPM
    function setSurgeFeeMultiplierPpm(PoolId poolId, uint24 multiplier) external;

    /// @notice Sets base fee parameters for a pool
    /// @param poolId The pool ID
    /// @param stepPpm The step size in PPM
    /// @param updateIntervalSecs The update interval in seconds
    function setBaseFeeParams(PoolId poolId, uint32 stepPpm, uint32 updateIntervalSecs) external;

    /// @notice Sets the daily budget in PPM
    /// @param ppm The daily budget in PPM
    function setDailyBudgetPpm(uint32 ppm) external;

    /// @notice Sets the daily budget for CAP events for a specific pool
    /// @param poolId The pool ID
    /// @param newBudget The new daily budget in PPM (0 means use default)
    function setPoolDailyBudgetPpm(PoolId poolId, uint32 newBudget) external;

    /// @notice Sets the decay window in seconds
    /// @param secs The decay window in seconds
    function setDecayWindow(uint32 secs) external;

    /// @notice Sets the base fee factor for a specific pool
    /// @param poolId The pool ID
    /// @param factor The new base fee factor (1 tick = X PPM)
    function setBaseFeeFactor(PoolId poolId, uint32 factor) external;
}

File 8 of 16 : PoolKey.sol
// 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;
}

// 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);
}

/// @title CurrencyLibrary
/// @dev This library allows for transferring and holding native tokens and ERC20 tokens
library CurrencyLibrary {
    /// @notice Additional context for ERC-7751 wrapped error when a native transfer fails
    error NativeTransferFailed();

    /// @notice Additional context for ERC-7751 wrapped error when an ERC20 transfer fails
    error ERC20TransferFailed();

    /// @notice A constant to represent the native currency
    Currency public constant ADDRESS_ZERO = Currency.wrap(address(0));

    function transfer(Currency currency, address to, uint256 amount) internal {
        // altered from https://github.com/transmissions11/solmate/blob/44a9963d4c78111f77caa0e65d677b8b46d6f2e6/src/utils/SafeTransferLib.sol
        // modified custom error selectors

        bool success;
        if (currency.isAddressZero()) {
            assembly ("memory-safe") {
                // Transfer the ETH and revert if it fails.
                success := call(gas(), to, amount, 0, 0, 0, 0)
            }
            // revert with NativeTransferFailed, containing the bubbled up error as an argument
            if (!success) {
                CustomRevert.bubbleUpAndRevertWith(to, bytes4(0), NativeTransferFailed.selector);
            }
        } else {
            assembly ("memory-safe") {
                // Get a pointer to some free memory.
                let fmp := mload(0x40)

                // Write the abi-encoded calldata into memory, beginning with the function selector.
                mstore(fmp, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
                mstore(add(fmp, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
                mstore(add(fmp, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

                success :=
                    and(
                        // Set success to whether the call reverted, if not we check it either
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
                        or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                        // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                        // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                        // Counterintuitively, this call must be positioned second to the or() call in the
                        // surrounding and() call or else returndatasize() will be zero during the computation.
                        call(gas(), currency, 0, fmp, 68, 0, 32)
                    )

                // Now clean the memory we used
                mstore(fmp, 0) // 4 byte `selector` and 28 bytes of `to` were stored here
                mstore(add(fmp, 0x20), 0) // 4 bytes of `to` and 28 bytes of `amount` were stored here
                mstore(add(fmp, 0x40), 0) // 4 bytes of `amount` were stored here
            }
            // revert with ERC20TransferFailed, containing the bubbled up error as an argument
            if (!success) {
                CustomRevert.bubbleUpAndRevertWith(
                    Currency.unwrap(currency), IERC20Minimal.transfer.selector, ERC20TransferFailed.selector
                );
            }
        }
    }

    function balanceOfSelf(Currency currency) internal view returns (uint256) {
        if (currency.isAddressZero()) {
            return address(this).balance;
        } else {
            return IERC20Minimal(Currency.unwrap(currency)).balanceOf(address(this));
        }
    }

    function balanceOf(Currency currency, address owner) internal view returns (uint256) {
        if (currency.isAddressZero()) {
            return owner.balance;
        } else {
            return IERC20Minimal(Currency.unwrap(currency)).balanceOf(owner);
        }
    }

    function isAddressZero(Currency currency) internal pure returns (bool) {
        return Currency.unwrap(currency) == Currency.unwrap(ADDRESS_ZERO);
    }

    function toId(Currency currency) internal pure returns (uint256) {
        return uint160(Currency.unwrap(currency));
    }

    // If the upper 12 bytes are non-zero, they will be zero-ed out
    // Therefore, fromId() and toId() are not inverses of each other
    function fromId(uint256 id) internal pure returns (Currency) {
        return Currency.wrap(address(uint160(id)));
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";
import {ModifyLiquidityParams, SwapParams} from "../types/PoolOperation.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
    /// @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 liquidity is added
    /// @param sender The initial msg.sender for the add liquidity call
    /// @param key The key for the pool
    /// @param params The parameters for adding liquidity
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook
    /// @return bytes4 The function selector for the hook
    function beforeAddLiquidity(
        address sender,
        PoolKey calldata key,
        ModifyLiquidityParams calldata params,
        bytes calldata hookData
    ) external returns (bytes4);

    /// @notice The hook called after liquidity is added
    /// @param sender The initial msg.sender for the add liquidity call
    /// @param key The key for the pool
    /// @param params The parameters for adding liquidity
    /// @param delta The caller's balance delta after adding liquidity; the sum of principal delta, fees accrued, and hook delta
    /// @param feesAccrued The fees accrued since the last time fees were collected from this position
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be passed on to the hook
    /// @return bytes4 The function selector for the hook
    /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
    function afterAddLiquidity(
        address sender,
        PoolKey calldata key,
        ModifyLiquidityParams calldata params,
        BalanceDelta delta,
        BalanceDelta feesAccrued,
        bytes calldata hookData
    ) external returns (bytes4, BalanceDelta);

    /// @notice The hook called before liquidity is removed
    /// @param sender The initial msg.sender for the remove liquidity call
    /// @param key The key for the pool
    /// @param params The parameters for removing liquidity
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook
    /// @return bytes4 The function selector for the hook
    function beforeRemoveLiquidity(
        address sender,
        PoolKey calldata key,
        ModifyLiquidityParams calldata params,
        bytes calldata hookData
    ) external returns (bytes4);

    /// @notice The hook called after liquidity is removed
    /// @param sender The initial msg.sender for the remove liquidity call
    /// @param key The key for the pool
    /// @param params The parameters for removing liquidity
    /// @param delta The caller's balance delta after removing liquidity; the sum of principal delta, fees accrued, and hook delta
    /// @param feesAccrued The fees accrued since the last time fees were collected from this position
    /// @param hookData Arbitrary data handed into the PoolManager by the liquidity provider to be be passed on to the hook
    /// @return bytes4 The function selector for the hook
    /// @return BalanceDelta The hook's delta in token0 and token1. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
    function afterRemoveLiquidity(
        address sender,
        PoolKey calldata key,
        ModifyLiquidityParams calldata params,
        BalanceDelta delta,
        BalanceDelta feesAccrued,
        bytes calldata hookData
    ) external returns (bytes4, BalanceDelta);

    /// @notice The hook called before a swap
    /// @param sender The initial msg.sender for the swap call
    /// @param key The key for the pool
    /// @param params The parameters for the swap
    /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook
    /// @return bytes4 The function selector for the hook
    /// @return BeforeSwapDelta The hook's delta in specified and unspecified currencies. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
    /// @return uint24 Optionally override the lp fee, only used if three conditions are met: 1. the Pool has a dynamic fee, 2. the value's 2nd highest bit is set (23rd bit, 0x400000), and 3. the value is less than or equal to the maximum fee (1 million)
    function beforeSwap(address sender, PoolKey calldata key, SwapParams calldata params, bytes calldata hookData)
        external
        returns (bytes4, BeforeSwapDelta, uint24);

    /// @notice The hook called after a swap
    /// @param sender The initial msg.sender for the swap call
    /// @param key The key for the pool
    /// @param params The parameters for the swap
    /// @param delta The amount owed to the caller (positive) or owed to the pool (negative)
    /// @param hookData Arbitrary data handed into the PoolManager by the swapper to be be passed on to the hook
    /// @return bytes4 The function selector for the hook
    /// @return int128 The hook's delta in unspecified currency. Positive: the hook is owed/took currency, negative: the hook owes/sent currency
    function afterSwap(
        address sender,
        PoolKey calldata key,
        SwapParams calldata params,
        BalanceDelta delta,
        bytes calldata hookData
    ) external returns (bytes4, int128);

    /// @notice The hook called before donate
    /// @param sender The initial msg.sender for the donate call
    /// @param key The key for the pool
    /// @param amount0 The amount of token0 being donated
    /// @param amount1 The amount of token1 being donated
    /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook
    /// @return bytes4 The function selector for the hook
    function beforeDonate(
        address sender,
        PoolKey calldata key,
        uint256 amount0,
        uint256 amount1,
        bytes calldata hookData
    ) external returns (bytes4);

    /// @notice The hook called after donate
    /// @param sender The initial msg.sender for the donate call
    /// @param key The key for the pool
    /// @param amount0 The amount of token0 being donated
    /// @param amount1 The amount of token1 being donated
    /// @param hookData Arbitrary data handed into the PoolManager by the donor to be be passed on to the hook
    /// @return bytes4 The function selector for the hook
    function afterDonate(
        address sender,
        PoolKey calldata key,
        uint256 amount0,
        uint256 amount1,
        bytes calldata hookData
    ) external returns (bytes4);
}

// 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`
    /// @return Returns true for a successful approval, false for unsuccessful
    function approve(address spender, uint256 amount) external returns (bool);

    /// @notice Transfers `amount` tokens from `sender` to `recipient` up to the allowance given to the `msg.sender`
    /// @param sender The account from which the transfer will be initiated
    /// @param recipient The recipient of the transfer
    /// @param amount The amount of the transfer
    /// @return Returns true for a successful transfer, false for unsuccessful
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /// @notice Event emitted when tokens are transferred from one address to another, either via `#transfer` or `#transferFrom`.
    /// @param from The account from which the tokens were sent, i.e. the balance decreased
    /// @param to The account to which the tokens were sent, i.e. the balance increased
    /// @param value The amount of tokens that were transferred
    event Transfer(address indexed from, address indexed to, uint256 value);

    /// @notice Event emitted when the approval amount for the spender of a given owner's tokens changes.
    /// @param owner The account that approved spending of its tokens
    /// @param spender The account for which the spending allowance was modified
    /// @param value The new allowance from the owner to the spender
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// 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)
        }
    }

    /// @dev Reverts with a custom error with an int24 argument in the scratch space
    function revertWith(bytes4 selector, int24 value) internal pure {
        assembly ("memory-safe") {
            mstore(0, selector)
            mstore(0x04, signextend(2, value))
            revert(0, 0x24)
        }
    }

    /// @dev Reverts with a custom error with a uint160 argument in the scratch space
    function revertWith(bytes4 selector, uint160 value) internal pure {
        assembly ("memory-safe") {
            mstore(0, selector)
            mstore(0x04, and(value, 0xffffffffffffffffffffffffffffffffffffffff))
            revert(0, 0x24)
        }
    }

    /// @dev Reverts with a custom error with two int24 arguments
    function revertWith(bytes4 selector, int24 value1, int24 value2) internal pure {
        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(fmp, selector)
            mstore(add(fmp, 0x04), signextend(2, value1))
            mstore(add(fmp, 0x24), signextend(2, value2))
            revert(fmp, 0x44)
        }
    }

    /// @dev Reverts with a custom error with two uint160 arguments
    function revertWith(bytes4 selector, uint160 value1, uint160 value2) internal pure {
        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(fmp, selector)
            mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))
            mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))
            revert(fmp, 0x44)
        }
    }

    /// @dev Reverts with a custom error with two address arguments
    function revertWith(bytes4 selector, address value1, address value2) internal pure {
        assembly ("memory-safe") {
            let fmp := mload(0x40)
            mstore(fmp, selector)
            mstore(add(fmp, 0x04), and(value1, 0xffffffffffffffffffffffffffffffffffffffff))
            mstore(add(fmp, 0x24), and(value2, 0xffffffffffffffffffffffffffffffffffffffff))
            revert(fmp, 0x44)
        }
    }

    /// @notice bubble up the revert message returned by a call and revert with a wrapped ERC-7751 error
    /// @dev this method can be vulnerable to revert data bombs
    function bubbleUpAndRevertWith(
        address revertingContract,
        bytes4 revertingFunctionSelector,
        bytes4 additionalContext
    ) internal pure {
        bytes4 wrappedErrorSelector = WrappedError.selector;
        assembly ("memory-safe") {
            // Ensure the size of the revert data is a multiple of 32 bytes
            let encodedDataSize := mul(div(add(returndatasize(), 31), 32), 32)

            let fmp := mload(0x40)

            // Encode wrapped error selector, address, function selector, offset, additional context, size, revert reason
            mstore(fmp, wrappedErrorSelector)
            mstore(add(fmp, 0x04), and(revertingContract, 0xffffffffffffffffffffffffffffffffffffffff))
            mstore(
                add(fmp, 0x24),
                and(revertingFunctionSelector, 0xffffffff00000000000000000000000000000000000000000000000000000000)
            )
            // offset revert reason
            mstore(add(fmp, 0x44), 0x80)
            // offset additional context
            mstore(add(fmp, 0x64), add(0xa0, encodedDataSize))
            // size revert reason
            mstore(add(fmp, 0x84), returndatasize())
            // revert reason
            returndatacopy(add(fmp, 0xa4), 0, returndatasize())
            // size additional context
            mstore(add(fmp, add(0xa4, encodedDataSize)), 0x04)
            // additional context
            mstore(
                add(fmp, add(0xc4, encodedDataSize)),
                and(additionalContext, 0xffffffff00000000000000000000000000000000000000000000000000000000)
            )
            revert(fmp, add(0xe4, encodedDataSize))
        }
    }
}

// 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)
        let b1 := signextend(15, b)
        res0 := add(a0, b0)
        res1 := add(a1, b1)
    }
    return toBalanceDelta(res0.toInt128(), res1.toInt128());
}

function sub(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)
        let b1 := signextend(15, b)
        res0 := sub(a0, b0)
        res1 := sub(a1, b1)
    }
    return toBalanceDelta(res0.toInt128(), res1.toInt128());
}

function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
    return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b);
}

function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
    return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b);
}

/// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type
library BalanceDeltaLibrary {
    /// @notice A BalanceDelta of 0
    BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0);

    function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) {
        assembly ("memory-safe") {
            _amount0 := sar(128, balanceDelta)
        }
    }

    function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) {
        assembly ("memory-safe") {
            _amount1 := signextend(15, balanceDelta)
        }
    }
}

File 14 of 16 : PoolOperation.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {PoolKey} from "../types/PoolKey.sol";
import {BalanceDelta} from "../types/BalanceDelta.sol";

/// @notice Parameter struct for `ModifyLiquidity` pool operations
struct ModifyLiquidityParams {
    // the lower and upper tick of the position
    int24 tickLower;
    int24 tickUpper;
    // how to modify the liquidity
    int256 liquidityDelta;
    // a value to set if you want unique liquidity positions at the same range
    bytes32 salt;
}

/// @notice Parameter struct for `Swap` pool operations
struct SwapParams {
    /// Whether to swap token0 for token1 or vice versa
    bool zeroForOne;
    /// The desired input amount if negative (exactIn), or the desired output amount if positive (exactOut)
    int256 amountSpecified;
    /// The sqrt price at which, if reached, the swap will stop executing
    uint160 sqrtPriceLimitX96;
}

// 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") {
            deltaSpecified := sar(128, delta)
        }
    }

    /// extracts int128 from the lower 128 bits of the BeforeSwapDelta
    /// returned by beforeSwap and afterSwap
    function getUnspecifiedDelta(BeforeSwapDelta delta) internal pure returns (int128 deltaUnspecified) {
        assembly ("memory-safe") {
            deltaUnspecified := signextend(15, delta)
        }
    }
}

// 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();
    }

    /// @notice Cast a int128 to a uint128, revert on overflow or underflow
    /// @param x The int128 to be casted
    /// @return y The casted integer, now type uint128
    function toUint128(int128 x) internal pure returns (uint128 y) {
        if (x < 0) SafeCastOverflow.selector.revertWith();
        y = uint128(x);
    }

    /// @notice Cast a int256 to a int128, revert on overflow or underflow
    /// @param x The int256 to be downcasted
    /// @return y The downcasted integer, now type int128
    function toInt128(int256 x) internal pure returns (int128 y) {
        y = int128(x);
        if (y != x) SafeCastOverflow.selector.revertWith();
    }

    /// @notice Cast a uint256 to a int256, revert on overflow
    /// @param x The uint256 to be casted
    /// @return y The casted integer, now type int256
    function toInt256(uint256 x) internal pure returns (int256 y) {
        y = int256(x);
        if (y < 0) SafeCastOverflow.selector.revertWith();
    }

    /// @notice Cast a uint256 to a int128, revert on overflow
    /// @param x The uint256 to be downcasted
    /// @return The downcasted integer, now type int128
    function toInt128(uint256 x) internal pure returns (int128) {
        if (x >= 1 << 127) SafeCastOverflow.selector.revertWith();
        return int128(int256(x));
    }
}

Settings
{
  "remappings": [
    "solmate/=node_modules/solmate/",
    "@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/",
    "openzeppelin/=node_modules/@openzeppelin/contracts/",
    "openzeppelin-contracts/=node_modules/@openzeppelin/",
    "forge-std/=node_modules/forge-std/src/",
    "ds-test/=node_modules/ds-test/src/",
    "v4-core/=node_modules/@uniswap/v4-core/",
    "@uniswap/v4-core/=node_modules/@uniswap/v4-core/",
    "v4-periphery/=node_modules/@uniswap/v4-periphery/",
    "@uniswap/v4-periphery/=node_modules/@uniswap/v4-periphery/",
    "uniswap-hooks/=node_modules/uniswap-hooks/src/",
    "utils/=test/utils/",
    "mocks/=test/mocks/",
    "permit2/=node_modules/permit2/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_governance","type":"address"},{"internalType":"uint256","name":"_dailyBudget","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint24","name":"value","type":"uint24"},{"internalType":"uint24","name":"min","type":"uint24"},{"internalType":"uint24","name":"max","type":"uint24"}],"name":"InvalidFeeRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"ParameterOutOfRange","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"factor","type":"uint32"}],"name":"BaseFeeFactorSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"stepPpm","type":"uint32"},{"indexed":false,"internalType":"uint32","name":"updateIntervalSecs","type":"uint32"}],"name":"BaseFeeParamsSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"decayWindow","type":"uint32"}],"name":"CapBudgetDecayWindowSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"newBudget","type":"uint32"}],"name":"DailyBudgetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"decayWindow","type":"uint32"}],"name":"GlobalDecayWindowSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint24","name":"manualFee","type":"uint24"}],"name":"ManualFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint24","name":"maxBaseFeePpm","type":"uint24"}],"name":"MaxBaseFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint24","name":"minBaseFeePpm","type":"uint24"}],"name":"MinBaseFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"newBudget","type":"uint32"}],"name":"PoolDailyBudgetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"polSharePpm","type":"uint256"}],"name":"PoolPOLShareChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"decayPeriod","type":"uint32"}],"name":"SurgeDecayPeriodSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint24","name":"multiplier","type":"uint24"}],"name":"SurgeFeeMultiplierSet","type":"event"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"clearManualFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getBaseFeeFactor","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getBaseFeeStepPpm","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getBaseFeeUpdateIntervalSeconds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getCapBudgetDecayWindow","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getDailyBudgetPpm","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDefaultDailyBudgetPpm","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"","type":"bytes32"}],"name":"getDefaultMaxTicksPerBlock","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getManualFee","outputs":[{"internalType":"uint24","name":"manualFee","type":"uint24"},{"internalType":"bool","name":"isSet","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getMaxBaseFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getMinBaseFee","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getPoolPOLShare","outputs":[{"internalType":"uint256","name":"poolSpecificPolShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getSurgeDecayPeriodSeconds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"}],"name":"getSurgeFeeMultiplierPpm","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint32","name":"factor","type":"uint32"}],"name":"setBaseFeeFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint32","name":"stepPpm","type":"uint32"},{"internalType":"uint32","name":"updateIntervalSecs","type":"uint32"}],"name":"setBaseFeeParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint32","name":"newCapBudgetDecayWindow","type":"uint32"}],"name":"setCapBudgetDecayWindow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newCapBudgetDailyPpm","type":"uint32"}],"name":"setDailyBudgetPpm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"newCapBudgetDecayWindow","type":"uint32"}],"name":"setDecayWindow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint24","name":"manualFee","type":"uint24"}],"name":"setManualFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint24","name":"newMaxFee","type":"uint24"}],"name":"setMaxBaseFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint24","name":"newMinFee","type":"uint24"}],"name":"setMinBaseFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint32","name":"newBudget","type":"uint32"}],"name":"setPoolDailyBudgetPpm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint256","name":"newPolSharePpm","type":"uint256"}],"name":"setPoolPOLShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint32","name":"newSurgeDecayPeriodSeconds","type":"uint32"}],"name":"setSurgeDecayPeriodSeconds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"bytes32"},{"internalType":"uint24","name":"multiplier","type":"uint24"}],"name":"setSurgeFeeMultiplierPpm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

6080346100f057601f6114f638819003918201601f19168301916001600160401b038311848410176100f45780849260409485528339810103126100f05780516001600160a01b03811691908290036100f057602001515f80546001600160a01b03191683178155604051929081907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3156100e157806100d4575063ffffffff620f42405b1663ffffffff19600654161760065562ed4e0063ffffffff1960085416176008556113ed90816101098239f35b63ffffffff8091166100a7565b63d92e233d60e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806319387f22146110885780631b80db7514610fc05780632020a71214610f80578063265f001214610ed557806331e2171514610e8d57806340943f8314610e6f5780634c2d4eee14610e335780634ca3d1e814610e155780635233477f14610df2578063594fce1e14610c8f5780635eddee2114610c7357806365007e5714610af5578063764ec8b9146109f45780638609b0d81461095e5780638da5cb5b1461092c5780638f349b1b1461090257806391dce1a1146108bf578063a574ccb3146107de578063b1dce181146107c0578063bea1c84414610794578063c567d3bc146106b9578063c606f7e814610675578063c6be21a114610559578063d586643514610476578063dddada05146102fa578063f1f859671461021e578063f2fde38b1461017c5763f32a75ca1461014d575f80fd5b3461017857602060031936011261017857602061016b600435611380565b62ffffff60405191168152f35b5f80fd5b346101785760206003193601126101785760043573ffffffffffffffffffffffffffffffffffffffff811680910361017857807fffffffffffffffffffffffff00000000000000000000000000000000000000005f546101f373ffffffffffffffffffffffffffffffffffffffff821633146111df565b16175f55337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b346101785760206003193601126101785760043561025473ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b805f52600260205260ff60405f20541661026a57005b805f52600160205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000008154169055805f52600260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557f9083d025f8c64d59acea1fdf714c5516cf7a6a0ec3d8ad02dba4b4020581670e60206040515f8152a2005b3461017857610308366111bd565b61032a73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b6040517f4ca3d1e8000000000000000000000000000000000000000000000000000000008152826004820152602081602481305afa801561046b5762ffffff915f9161043c575b50169062ffffff8116918083108015610431575b6103fc57507f2f5debd6daca65c6366789854a2dc3af21dc997a9a5efea24aaa5909bf2b92a991602091845f526004835260405f20907fffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffff69ffffff0000000000000083549260381b169116179055604051908152a2005b827f2541552c000000000000000000000000000000000000000000000000000000005f5260045260245261c35060445260645ffd5b5061c3508311610385565b61045e915060203d602011610464575b61045681836112b3565b8101906112f4565b84610371565b503d61044c565b6040513d5f823e3d90fd5b346101785760406003193601126101785760043563ffffffff610497611197565b6104b973ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b1680151580610543575b61050c5760207fd7e72b0fc5beacd7d45da90e00eae118e8631408a96ec944fca72198d70a0aba91835f526007825260405f208163ffffffff19825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f5260045260016024526298968060445260645ffd5b5060018110806104c357506298968081116104c3565b346101785762ffffff61056b366111bd565b61059073ffffffffffffffffffffffffffffffffffffffff5f949394541633146111df565b1660648110801561066a575b6106345760207f9083d025f8c64d59acea1fdf714c5516cf7a6a0ec3d8ad02dba4b4020581670e91835f526001825260405f20817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000825416179055835f526002825260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f52600452606460245261c35060445260645ffd5b5061c350811161059c565b34610178576020600319360112610178576040600435805f52600160205262ffffff825f205416905f52600260205260ff825f205416825191825215156020820152f35b346101785760406003193601126101785760043563ffffffff6106da611197565b6106fc73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b1680158015610787575b61074f5760207f66ee5e9b760bb90b7fd9e7d2d5a734bbad7ad1a680014d26d7e645d8e9e166ad91835f526004825260405f208163ffffffff19825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f52600452600160245263ffffffff60445260645ffd5b5063ffffffff8111610706565b346101785760206003193601126101785760206107b2600435611347565b63ffffffff60405191168152f35b3461017857602060031936011261017857602061016b60043561130f565b346101785760406003193601126101785760043563ffffffff6107ff611197565b61082173ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b16801515806108aa575b6108745760207fc8d20789bc2cb7bff2e11840599da787d4a2b2df695b7e772f2679356159cddc91835f526009825260405f208163ffffffff19825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f5260045260016024526103e860445260645ffd5b50600181108061082b57506103e8811161082b565b34610178576020600319360112610178576004355f52600960205263ffffffff60405f20541680155f146108fa575060405160648152602090f35b6020906107b2565b34610178576020600319360112610178576004355f526003602052602060405f2054604051908152f35b34610178575f60031936011261017857602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b346101785760206003193601126101785763ffffffff61097c6111aa565b61099e73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b16801580156109e8575b61050c576020817f3f1bd9e18fc1d3973140743a18a170a8d611e75425f827c4a96f2454326f68859263ffffffff196006541617600655604051908152a1005b506298968081116109a8565b3461017857610a02366111bd565b610a2473ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b62ffffff81169081158015610ae9575b610ab1577ff6dfc5609f3aae34feebcd990ea035721d1dcdf52d7ce41d2075ceddec87595391602091845f526004835260405f20907fffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffff70ffffff000000000000000000000000000083549260701b169116179055604051908152a2005b507fd3f93ee8000000000000000000000000000000000000000000000000000000005f526004526001602452622dc6c060445260645ffd5b50622dc6c08211610a34565b3461017857606060031936011261017857600435610b11611197565b6044359063ffffffff82168092036101785763ffffffff90610b4b73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b1690620186a08211610c3c57801561074f5760405191604083019183831067ffffffffffffffff841117610c0f577f0e49e7eb0b09c860e745288083a908c9113d3782c23a133a490c171adca7277393604093845282815260208101828152865f52600560205263ffffffff80865f209351161663ffffffff19835416178255517fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff67ffffffff0000000083549260201b16911617905582519182526020820152a2005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b507fd3f93ee8000000000000000000000000000000000000000000000000000000005f526004525f602452620186a060445260645ffd5b3461017857602060031936011261017857602060405160328152f35b3461017857610c9d366111bd565b610cbf73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b604051907ff32a75ca000000000000000000000000000000000000000000000000000000008252826004830152602082602481305afa91821561046b575f92610dd1575b5062ffffff811691606483108015610dc3575b610d8957507f8933b881da6cef5bce0dd8e24a6e051cc8621a1502bbde1d4bd6e76f791b0d3491602091845f526004835260405f20907fffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffff66ffffff00000000835492861b169116179055604051908152a2005b62ffffff90837f2541552c000000000000000000000000000000000000000000000000000000005f5260045260646024521660445260645ffd5b5062ffffff81168311610d16565b610deb91925060203d6020116104645761045681836112b3565b9083610d03565b34610178575f60031936011261017857602063ffffffff60065416604051908152f35b3461017857602060031936011261017857602061016b60043561127d565b34610178576020600319360112610178576004355f52600560205263ffffffff60405f20541680155f146108fa5750604051614e208152602090f35b346101785760206003193601126101785760206107b2600435611244565b34610178576020600319360112610178576004355f52600760205263ffffffff60405f20541680155f146108fa5750602063ffffffff6006541663ffffffff60405191168152f35b346101785760206003193601126101785763ffffffff610ef36111aa565b610f1573ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b168015610f58576020817f0caae632587dc39fce6f52625e76b77fc72c9973598cce01fdc747f944365c8f9263ffffffff196008541617600855604051908152a1005b7f7c946ed7000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610178576020600319360112610178576004355f52600560205263ffffffff60405f205460201c1680155f146108fa5750604051620151808152602090f35b3461017857604060031936011261017857600435602435610ff973ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b620f4240811161105257815f5260036020528060405f20540361101857005b60207fc22c4cd36600aa7bb9e64762f7b5cd1fb2f5f8d101b8f4c24e6c41e53beab3db91835f52600382528060405f2055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f526004525f602452620f424060445260645ffd5b34610178576040600319360112610178576004356110a4611197565b6110c673ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b63ffffffff811690603c8210801561118b575b611153577fd2bd771962d916ee2dbf5ed4eeb2544de7646b2afb24ce617921f5f5b24de4b191602091845f526004835260405f20907fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff6dffffffff0000000000000000000083549260501b169116179055604051908152a2005b507fd3f93ee8000000000000000000000000000000000000000000000000000000005f52600452603c6024526201518060445260645ffd5b506201518082116110d9565b6024359063ffffffff8216820361017857565b6004359063ffffffff8216820361017857565b6003196040910112610178576004359060243562ffffff811681036101785790565b156111e657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152fd5b805f52600460205263ffffffff60405f205416611268575063ffffffff6008541690565b5f52600460205263ffffffff60405f20541690565b805f52600460205262ffffff60405f205460201c1661129c5750606490565b5f52600460205262ffffff60405f205460201c1690565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610c0f57604052565b90816020910312610178575162ffffff811681036101785790565b805f52600460205262ffffff60405f205460701c166113305750622dc6c090565b5f52600460205262ffffff60405f205460701c1690565b805f52600460205263ffffffff60405f205460501c166113685750610e1090565b5f52600460205263ffffffff60405f205460501c1690565b805f52600460205262ffffff60405f205460381c166113a0575061c35090565b5f52600460205262ffffff60405f205460381c169056fea2646970667358221220a17cd97e008e54202ec70dbaa5c9805952c5d5cf7900205958978e11cb99473964736f6c634300081b003300000000000000000000000036b89a2be57541e9e1f0b44cb085e573192f15140000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x60806040526004361015610011575f80fd5b5f3560e01c806319387f22146110885780631b80db7514610fc05780632020a71214610f80578063265f001214610ed557806331e2171514610e8d57806340943f8314610e6f5780634c2d4eee14610e335780634ca3d1e814610e155780635233477f14610df2578063594fce1e14610c8f5780635eddee2114610c7357806365007e5714610af5578063764ec8b9146109f45780638609b0d81461095e5780638da5cb5b1461092c5780638f349b1b1461090257806391dce1a1146108bf578063a574ccb3146107de578063b1dce181146107c0578063bea1c84414610794578063c567d3bc146106b9578063c606f7e814610675578063c6be21a114610559578063d586643514610476578063dddada05146102fa578063f1f859671461021e578063f2fde38b1461017c5763f32a75ca1461014d575f80fd5b3461017857602060031936011261017857602061016b600435611380565b62ffffff60405191168152f35b5f80fd5b346101785760206003193601126101785760043573ffffffffffffffffffffffffffffffffffffffff811680910361017857807fffffffffffffffffffffffff00000000000000000000000000000000000000005f546101f373ffffffffffffffffffffffffffffffffffffffff821633146111df565b16175f55337f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b346101785760206003193601126101785760043561025473ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b805f52600260205260ff60405f20541661026a57005b805f52600160205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000008154169055805f52600260205260405f207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0081541690557f9083d025f8c64d59acea1fdf714c5516cf7a6a0ec3d8ad02dba4b4020581670e60206040515f8152a2005b3461017857610308366111bd565b61032a73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b6040517f4ca3d1e8000000000000000000000000000000000000000000000000000000008152826004820152602081602481305afa801561046b5762ffffff915f9161043c575b50169062ffffff8116918083108015610431575b6103fc57507f2f5debd6daca65c6366789854a2dc3af21dc997a9a5efea24aaa5909bf2b92a991602091845f526004835260405f20907fffffffffffffffffffffffffffffffffffffffffffff000000ffffffffffffff69ffffff0000000000000083549260381b169116179055604051908152a2005b827f2541552c000000000000000000000000000000000000000000000000000000005f5260045260245261c35060445260645ffd5b5061c3508311610385565b61045e915060203d602011610464575b61045681836112b3565b8101906112f4565b84610371565b503d61044c565b6040513d5f823e3d90fd5b346101785760406003193601126101785760043563ffffffff610497611197565b6104b973ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b1680151580610543575b61050c5760207fd7e72b0fc5beacd7d45da90e00eae118e8631408a96ec944fca72198d70a0aba91835f526007825260405f208163ffffffff19825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f5260045260016024526298968060445260645ffd5b5060018110806104c357506298968081116104c3565b346101785762ffffff61056b366111bd565b61059073ffffffffffffffffffffffffffffffffffffffff5f949394541633146111df565b1660648110801561066a575b6106345760207f9083d025f8c64d59acea1fdf714c5516cf7a6a0ec3d8ad02dba4b4020581670e91835f526001825260405f20817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000825416179055835f526002825260405f2060017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f52600452606460245261c35060445260645ffd5b5061c350811161059c565b34610178576020600319360112610178576040600435805f52600160205262ffffff825f205416905f52600260205260ff825f205416825191825215156020820152f35b346101785760406003193601126101785760043563ffffffff6106da611197565b6106fc73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b1680158015610787575b61074f5760207f66ee5e9b760bb90b7fd9e7d2d5a734bbad7ad1a680014d26d7e645d8e9e166ad91835f526004825260405f208163ffffffff19825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f52600452600160245263ffffffff60445260645ffd5b5063ffffffff8111610706565b346101785760206003193601126101785760206107b2600435611347565b63ffffffff60405191168152f35b3461017857602060031936011261017857602061016b60043561130f565b346101785760406003193601126101785760043563ffffffff6107ff611197565b61082173ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b16801515806108aa575b6108745760207fc8d20789bc2cb7bff2e11840599da787d4a2b2df695b7e772f2679356159cddc91835f526009825260405f208163ffffffff19825416179055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f5260045260016024526103e860445260645ffd5b50600181108061082b57506103e8811161082b565b34610178576020600319360112610178576004355f52600960205263ffffffff60405f20541680155f146108fa575060405160648152602090f35b6020906107b2565b34610178576020600319360112610178576004355f526003602052602060405f2054604051908152f35b34610178575f60031936011261017857602073ffffffffffffffffffffffffffffffffffffffff5f5416604051908152f35b346101785760206003193601126101785763ffffffff61097c6111aa565b61099e73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b16801580156109e8575b61050c576020817f3f1bd9e18fc1d3973140743a18a170a8d611e75425f827c4a96f2454326f68859263ffffffff196006541617600655604051908152a1005b506298968081116109a8565b3461017857610a02366111bd565b610a2473ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b62ffffff81169081158015610ae9575b610ab1577ff6dfc5609f3aae34feebcd990ea035721d1dcdf52d7ce41d2075ceddec87595391602091845f526004835260405f20907fffffffffffffffffffffffffffffff000000ffffffffffffffffffffffffffff70ffffff000000000000000000000000000083549260701b169116179055604051908152a2005b507fd3f93ee8000000000000000000000000000000000000000000000000000000005f526004526001602452622dc6c060445260645ffd5b50622dc6c08211610a34565b3461017857606060031936011261017857600435610b11611197565b6044359063ffffffff82168092036101785763ffffffff90610b4b73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b1690620186a08211610c3c57801561074f5760405191604083019183831067ffffffffffffffff841117610c0f577f0e49e7eb0b09c860e745288083a908c9113d3782c23a133a490c171adca7277393604093845282815260208101828152865f52600560205263ffffffff80865f209351161663ffffffff19835416178255517fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff67ffffffff0000000083549260201b16911617905582519182526020820152a2005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b507fd3f93ee8000000000000000000000000000000000000000000000000000000005f526004525f602452620186a060445260645ffd5b3461017857602060031936011261017857602060405160328152f35b3461017857610c9d366111bd565b610cbf73ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b604051907ff32a75ca000000000000000000000000000000000000000000000000000000008252826004830152602082602481305afa91821561046b575f92610dd1575b5062ffffff811691606483108015610dc3575b610d8957507f8933b881da6cef5bce0dd8e24a6e051cc8621a1502bbde1d4bd6e76f791b0d3491602091845f526004835260405f20907fffffffffffffffffffffffffffffffffffffffffffffffffff000000ffffffff66ffffff00000000835492861b169116179055604051908152a2005b62ffffff90837f2541552c000000000000000000000000000000000000000000000000000000005f5260045260646024521660445260645ffd5b5062ffffff81168311610d16565b610deb91925060203d6020116104645761045681836112b3565b9083610d03565b34610178575f60031936011261017857602063ffffffff60065416604051908152f35b3461017857602060031936011261017857602061016b60043561127d565b34610178576020600319360112610178576004355f52600560205263ffffffff60405f20541680155f146108fa5750604051614e208152602090f35b346101785760206003193601126101785760206107b2600435611244565b34610178576020600319360112610178576004355f52600760205263ffffffff60405f20541680155f146108fa5750602063ffffffff6006541663ffffffff60405191168152f35b346101785760206003193601126101785763ffffffff610ef36111aa565b610f1573ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b168015610f58576020817f0caae632587dc39fce6f52625e76b77fc72c9973598cce01fdc747f944365c8f9263ffffffff196008541617600855604051908152a1005b7f7c946ed7000000000000000000000000000000000000000000000000000000005f5260045ffd5b34610178576020600319360112610178576004355f52600560205263ffffffff60405f205460201c1680155f146108fa5750604051620151808152602090f35b3461017857604060031936011261017857600435602435610ff973ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b620f4240811161105257815f5260036020528060405f20540361101857005b60207fc22c4cd36600aa7bb9e64762f7b5cd1fb2f5f8d101b8f4c24e6c41e53beab3db91835f52600382528060405f2055604051908152a2005b7fd3f93ee8000000000000000000000000000000000000000000000000000000005f526004525f602452620f424060445260645ffd5b34610178576040600319360112610178576004356110a4611197565b6110c673ffffffffffffffffffffffffffffffffffffffff5f541633146111df565b63ffffffff811690603c8210801561118b575b611153577fd2bd771962d916ee2dbf5ed4eeb2544de7646b2afb24ce617921f5f5b24de4b191602091845f526004835260405f20907fffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffff6dffffffff0000000000000000000083549260501b169116179055604051908152a2005b507fd3f93ee8000000000000000000000000000000000000000000000000000000005f52600452603c6024526201518060445260645ffd5b506201518082116110d9565b6024359063ffffffff8216820361017857565b6004359063ffffffff8216820361017857565b6003196040910112610178576004359060243562ffffff811681036101785790565b156111e657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f554e415554484f52495a454400000000000000000000000000000000000000006044820152fd5b805f52600460205263ffffffff60405f205416611268575063ffffffff6008541690565b5f52600460205263ffffffff60405f20541690565b805f52600460205262ffffff60405f205460201c1661129c5750606490565b5f52600460205262ffffff60405f205460201c1690565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610c0f57604052565b90816020910312610178575162ffffff811681036101785790565b805f52600460205262ffffff60405f205460701c166113305750622dc6c090565b5f52600460205262ffffff60405f205460701c1690565b805f52600460205263ffffffff60405f205460501c166113685750610e1090565b5f52600460205263ffffffff60405f205460501c1690565b805f52600460205262ffffff60405f205460381c166113a0575061c35090565b5f52600460205262ffffff60405f205460381c169056fea2646970667358221220a17cd97e008e54202ec70dbaa5c9805952c5d5cf7900205958978e11cb99473964736f6c634300081b0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000036b89a2be57541e9e1f0b44cb085e573192f15140000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _governance (address): 0x36b89a2Be57541e9e1f0B44cb085e573192F1514
Arg [1] : _dailyBudget (uint256): 0

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000036b89a2be57541e9e1f0b44cb085e573192f1514
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block 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.