{"file_path":"src/SPBEAM.sol","creation_status":"success","source_code":"// SPDX-FileCopyrightText: 2025 Dai Foundation <www.daifoundation.org>\n// SPDX-License-Identifier: AGPL-3.0-or-later\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\npragma solidity ^0.8.24;\n\ninterface JugLike {\n    function file(bytes32 ilk, bytes32 what, uint256 data) external;\n    function ilks(bytes32 ilk) external view returns (uint256 duty, uint256 rho);\n    function drip(bytes32 ilk) external;\n}\n\ninterface PotLike {\n    function file(bytes32 what, uint256 data) external;\n    function dsr() external view returns (uint256);\n    function drip() external;\n}\n\ninterface SUSDSLike {\n    function file(bytes32 what, uint256 data) external;\n    function ssr() external view returns (uint256);\n    function drip() external;\n}\n\ninterface ConvLike {\n    function btor(uint256 bps) external pure returns (uint256 ray);\n    function rtob(uint256 ray) external pure returns (uint256 bps);\n}\n\n/// @title Stability Parameter Bounded External Access Module (SP-BEAM)\n/// @notice A module for managing protocol stability parameters with configurable constraints and safety checks\n/// @dev Provides controlled access to modify stability parameters (ilk stability fees, DSR, SSR) with:\n///      - Configurable min/max bounds and step sizes for each parameter\n///      - Cooldown periods between updates\n///      - Ordered batch updates\n///      - Emergency circuit breaker\ncontract SPBEAM {\n    // --- Structs ---\n    /// @notice Configuration for a rate parameter's constraints\n    /// @dev All values are in basis points (1 bp = 0.01%)\n    struct Cfg {\n        uint16 min; // Minimum allowed rate\n        uint16 max; // Maximum allowed rate\n        uint16 step; // Maximum allowed rate change per update\n    }\n\n    /// @notice A rate parameter update request\n    /// @dev Used in batch updates to modify multiple rates atomically\n    struct ParamChange {\n        bytes32 id; // Rate identifier (ilk, \"DSR\", or \"SSR\")\n        uint256 bps; // New rate value in bps\n    }\n\n    // --- Constants ---\n    uint256 public constant RAY = 10 ** 27;\n\n    // --- Immutables ---\n    /// @notice Stability fee rates\n    JugLike public immutable jug;\n    /// @notice DSR rate\n    PotLike public immutable pot;\n    /// @notice SSR rate\n    SUSDSLike public immutable susds;\n    /// @notice Rate conversion utility\n    ConvLike public immutable conv;\n\n    // --- Storage Variables ---\n    /// @notice Mapping of admin addresses\n    mapping(address => uint256) public wards;\n    /// @notice Mapping of addresses that can operate this module\n    mapping(address => uint256) public buds;\n    /// @notice Mapping of rate constraints\n    mapping(bytes32 => Cfg) public cfgs;\n    /// @notice Circuit breaker flag\n    uint8 public bad;\n    /// @notice Cooldown period between rate changes in seconds\n    uint64 public tau;\n    /// @notice Last time when rates were updated (Unix timestamp)\n    uint128 public toc;\n\n    // --- Events ---\n    /**\n     * @notice `usr` was granted admin access.\n     * @param usr The user address.\n     */\n    event Rely(address indexed usr);\n    /**\n     * @notice `usr` admin access was revoked.\n     * @param usr The user address.\n     */\n    event Deny(address indexed usr);\n    /**\n     * @notice `usr` was granted permission to change rates (call set()).\n     * @param usr The user address.\n     */\n    event Kiss(address indexed usr);\n    /**\n     * @notice Permission revoked for `usr` to change rates (call set()).\n     * @param usr The user address.\n     */\n    event Diss(address indexed usr);\n    /**\n     * @notice A contract parameter was updated.\n     * @param what The changed parameter name.\n     * @param data The new value of the parameter.\n     */\n    event File(bytes32 indexed what, uint256 data);\n    /**\n     * @notice A parameter was updated for an ilk, DSR, SSR.\n     * @param id The identifier (ilk, DSR, or SSR).\n     * @param what The changed parameter name.\n     * @param data The new value of the parameter.\n     */\n    event File(bytes32 indexed id, bytes32 indexed what, uint256 data);\n    /**\n     * @notice Rate change was executed.\n     * @param id The identifier (ilk, DSR, or SSR).\n     * @param bps The new rate in basis points.\n     */\n    event Set(bytes32 indexed id, uint256 bps);\n\n    // --- Modifiers ---\n    modifier auth() {\n        require(wards[msg.sender] == 1, \"SPBEAM/not-authorized\");\n        _;\n    }\n\n    modifier toll() {\n        require(buds[msg.sender] == 1, \"SPBEAM/not-facilitator\");\n        _;\n    }\n\n    modifier good() {\n        require(bad == 0, \"SPBEAM/module-halted\");\n        _;\n    }\n\n    /// @notice Initialize the SPBEAM module with core system contracts\n    /// @param _jug Jug contract for stability fee management\n    /// @param _pot Pot contract for Dai Savings Rate (DSR)\n    /// @param _susds SUSDS contract for Sky Savings Rate (SSR)\n    /// @param _conv Utility contract for rate conversions between basis points and ray\n    constructor(address _jug, address _pot, address _susds, address _conv) {\n        jug = JugLike(_jug);\n        pot = PotLike(_pot);\n        susds = SUSDSLike(_susds);\n        conv = ConvLike(_conv);\n\n        wards[msg.sender] = 1;\n        emit Rely(msg.sender);\n    }\n\n    // --- Administration ---\n    /// @notice Grant authorization to an address\n    /// @param usr The address to be authorized\n    /// @dev Sets wards[usr] to 1 and emits Rely event\n    function rely(address usr) external auth {\n        wards[usr] = 1;\n        emit Rely(usr);\n    }\n\n    /// @notice Revoke authorization from an address\n    /// @param usr The address to be deauthorized\n    /// @dev Sets wards[usr] to 0 and emits Deny event\n    function deny(address usr) external auth {\n        wards[usr] = 0;\n        emit Deny(usr);\n    }\n\n    /// @notice Add a facilitator\n    /// @param usr The address to add as a facilitator\n    /// @dev Sets buds[usr] to 1 and emits Kiss event. Facilitators can propose rate updates but cannot modify system parameters\n    function kiss(address usr) external auth {\n        buds[usr] = 1;\n        emit Kiss(usr);\n    }\n\n    /// @notice Remove a facilitator\n    /// @param usr The address to remove as a facilitator\n    /// @dev Sets buds[usr] to 0 and emits Diss event\n    function diss(address usr) external auth {\n        buds[usr] = 0;\n        emit Diss(usr);\n    }\n\n    /// @notice Configure global module parameters\n    /// @param what Parameter name (\"bad\": circuit breaker, \"tau\": cooldown period, \"toc\": last update timestamp)\n    /// @param data New parameter value\n    /// @dev Configures critical module parameters:\n    ///      - bad: Emergency circuit breaker (0: normal, 1: halted)\n    ///      - tau: Minimum time between rate updates in seconds\n    ///      - toc: Last update timestamp (set automatically)\n    function file(bytes32 what, uint256 data) external auth {\n        if (what == \"bad\") {\n            require(data == 0 || data == 1, \"SPBEAM/invalid-bad-value\");\n            bad = uint8(data);\n        } else if (what == \"tau\") {\n            require(data <= type(uint64).max, \"SPBEAM/invalid-tau-value\");\n            tau = uint64(data);\n        } else if (what == \"toc\") {\n            require(data <= type(uint128).max, \"SPBEAM/invalid-toc-value\");\n            toc = uint128(data);\n        } else {\n            revert(\"SPBEAM/file-unrecognized-param\");\n        }\n\n        emit File(what, data);\n    }\n\n    /// @notice Configure constraints for a specific rate parameter\n    /// @param id Rate identifier (ilk for collateral types, \"DSR\" for Dai Savings Rate, \"SSR\" for Sky Savings Rate)\n    /// @param what Parameter to configure:\n    ///      - \"min\": Minimum allowed rate in basis points\n    ///      - \"max\": Maximum allowed rate in basis points\n    ///      - \"step\": Maximum allowed rate change in basis points\n    /// @param data New parameter value in basis points\n    /// @dev Important considerations:\n    ///      - For ilks, verifies the collateral type is initialized in the system\n    ///      - All values must be <= uint16 max (65535 basis points)\n    ///      - When setting both min and max, set min first to avoid invalid state\n    function file(bytes32 id, bytes32 what, uint256 data) external auth {\n        if (id != \"DSR\" && id != \"SSR\") {\n            (uint256 duty,) = jug.ilks(id);\n            require(duty > 0, \"SPBEAM/ilk-not-initialized\");\n        }\n        require(data <= type(uint16).max, \"SPBEAM/invalid-value\");\n        if (what == \"min\") {\n            require(data <= cfgs[id].max, \"SPBEAM/min-too-high\");\n            cfgs[id].min = uint16(data);\n        } else if (what == \"max\") {\n            require(data >= cfgs[id].min, \"SPBEAM/max-too-low\");\n            cfgs[id].max = uint16(data);\n        } else if (what == \"step\") {\n            cfgs[id].step = uint16(data);\n        } else {\n            revert(\"SPBEAM/file-unrecognized-param\");\n        }\n\n        emit File(id, what, data);\n    }\n\n    /// @notice Execute a batch of rate updates\n    /// @param updates Array of rate changes to apply, must be ordered alphabetically by id\n    /// @dev Executes multiple rate updates in a single transaction with safety checks:\n    ///      1. Verifies cooldown period has elapsed\n    ///      2. Checks each rate is configured and within bounds\n    ///      3. Validates rate changes don't exceed max step size\n    ///      4. Ensures updates are properly ordered to prevent duplicates\n    ///      5. Calls drip() before each update to accrue fees\n    /// @dev Reverts if:\n    ///      - Caller not authorized (SPBEAM/not-facilitator)\n    ///      - Module halted, bad = 1 (SPBEAM/module-halted)\n    ///      - Empty updates array (SPBEAM/empty-batch)\n    ///      - Cooldown period not elapsed (SPBEAM/too-early)\n    ///      - Updates not ordered alphabetically by id (SPBEAM/updates-out-of-order)\n    ///      - Rate not configured, step = 0 (SPBEAM/rate-not-configured)\n    ///      - New rate < min (SPBEAM/below-min)\n    ///      - New rate > max (SPBEAM/above-max)\n    ///      - Rate change > step (SPBEAM/delta-above-step)\n    ///      - Rate conversion failed (SPBEAM/invalid-rate-conv)\n    function set(ParamChange[] calldata updates) external toll good {\n        require(updates.length > 0, \"SPBEAM/empty-batch\");\n        require(block.timestamp >= tau + toc, \"SPBEAM/too-early\");\n        toc = uint128(block.timestamp);\n\n        bytes32 last;\n        for (uint256 i = 0; i < updates.length; i++) {\n            bytes32 id = updates[i].id;\n\n            require(id > last, \"SPBEAM/updates-out-of-order\");\n            last = id;\n\n            uint256 bps = updates[i].bps;\n            Cfg memory cfg = cfgs[id];\n\n            require(cfg.step > 0, \"SPBEAM/rate-not-configured\");\n            require(bps >= cfg.min, \"SPBEAM/below-min\");\n            require(bps <= cfg.max, \"SPBEAM/above-max\");\n\n            // Check rate change is within allowed gap\n            uint256 oldBps;\n            if (id == \"DSR\") {\n                oldBps = conv.rtob(PotLike(pot).dsr());\n            } else if (id == \"SSR\") {\n                oldBps = conv.rtob(SUSDSLike(susds).ssr());\n            } else {\n                (uint256 duty,) = JugLike(jug).ilks(id);\n                oldBps = conv.rtob(duty);\n            }\n\n            if (oldBps < cfg.min) {\n                oldBps = cfg.min;\n            } else if (oldBps > cfg.max) {\n                oldBps = cfg.max;\n            }\n\n            // Calculates absolute difference between the old and the new rate\n            uint256 delta = bps > oldBps ? bps - oldBps : oldBps - bps;\n            require(delta <= cfg.step, \"SPBEAM/delta-above-step\");\n\n            // Execute the update\n            uint256 ray = conv.btor(bps);\n            require(ray >= RAY, \"SPBEAM/invalid-rate-conv\");\n            if (id == \"DSR\") {\n                pot.drip();\n                pot.file(\"dsr\", ray);\n            } else if (id == \"SSR\") {\n                susds.drip();\n                susds.file(\"ssr\", ray);\n            } else {\n                jug.drip(id);\n                jug.file(id, \"duty\", ray);\n            }\n            emit Set(id, bps);\n        }\n    }\n}\n","deployed_bytecode":"0x608060405234801561000f575f80fd5b5060043610610111575f3560e01c806365c4ce7a1161009e5780639c3674fc1161006e5780639c3674fc146102ff5780639c52a7f11461031e578063bf353dbb14610331578063cfc4af5514610350578063f29c29c414610382575f80fd5b806365c4ce7a1461028057806365fae35e1461029357806384718d89146102a657806389afb88a146102cd575f80fd5b80634ba2363a116100e45780634ba2363a1461019457806353a7d8cd146101bb578063552033c4146101e857806358b8f19c146101fb578063646544a014610222575f80fd5b806308b36870146101155780631a0b287e1461015957806329ae81141461016e578063474d857f14610181575b5f80fd5b61013c7f000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e5281565b6040516001600160a01b0390911681526020015b60405180910390f35b61016c610167366004611577565b610395565b005b61016c61017c3660046115a0565b6106ea565b61016c61018f3660046115c0565b6108e5565b61013c7f000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf781565b6101da6101c936600461162f565b60016020525f908152604090205481565b604051908152602001610150565b6101da6b033b2e3c9fd0803ce800000081565b61013c7f000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd81565b61025b61023036600461165c565b60026020525f908152604090205461ffff808216916201000081048216916401000000009091041683565b6040805161ffff94851681529284166020840152921691810191909152606001610150565b61016c61028e36600461162f565b6113af565b61016c6102a136600461162f565b611420565b61013c7f00000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f181565b6003546102e790600160481b90046001600160801b031681565b6040516001600160801b039091168152602001610150565b60035461030c9060ff1681565b60405160ff9091168152602001610150565b61016c61032c36600461162f565b611492565b6101da61033f36600461162f565b5f6020819052908152604090205481565b60035461036990610100900467ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610150565b61016c61039036600461162f565b611503565b335f908152602081905260409020546001146103cc5760405162461bcd60e51b81526004016103c390611673565b60405180910390fd5b82622229a960e91b141580156103e85750826229a9a960e91b14155b156104c957604051636cb1c69b60e11b8152600481018490525f907f00000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f16001600160a01b03169063d9638d36906024016040805180830381865afa158015610451573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061047591906116a2565b5090505f81116104c75760405162461bcd60e51b815260206004820152601a60248201527f53504245414d2f696c6b2d6e6f742d696e697469616c697a656400000000000060448201526064016103c3565b505b61ffff8111156105125760405162461bcd60e51b815260206004820152601460248201527353504245414d2f696e76616c69642d76616c756560601b60448201526064016103c3565b816236b4b760e91b0361059d575f8381526002602052604090205462010000900461ffff1681111561057c5760405162461bcd60e51b81526020600482015260136024820152720a6a0848a829a5edad2dc5ae8dede5ad0d2ced606b1b60448201526064016103c3565b5f838152600260205260409020805461ffff191661ffff83161790556106aa565b81620dac2f60eb1b03610628575f8381526002602052604090205461ffff168110156106005760405162461bcd60e51b815260206004820152601260248201527153504245414d2f6d61782d746f6f2d6c6f7760701b60448201526064016103c3565b5f838152600260205260409020805463ffff000019166201000061ffff8416021790556106aa565b81630737465760e41b03610662575f838152600260205260409020805465ffff00000000191664010000000061ffff8416021790556106aa565b60405162461bcd60e51b815260206004820152601e60248201527f53504245414d2f66696c652d756e7265636f676e697a65642d706172616d000060448201526064016103c3565b81837f851aa1caf4888170ad8875449d18f0f512fd6deb2a6571ea1a41fb9f95acbcd1836040516106dd91815260200190565b60405180910390a3505050565b335f908152602081905260409020546001146107185760405162461bcd60e51b81526004016103c390611673565b816218985960ea1b03610792578015806107325750806001145b61077e5760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d6261642d76616c7565000000000000000060448201526064016103c3565b6003805460ff191660ff83161790556108a7565b816274617560e81b0361081e5767ffffffffffffffff8111156107f75760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d7461752d76616c7565000000000000000060448201526064016103c3565b6003805468ffffffffffffffff00191661010067ffffffffffffffff8416021790556108a7565b8162746f6360e81b03610662576001600160801b038111156108825760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d746f632d76616c7565000000000000000060448201526064016103c3565b60038054600160481b600160c81b031916600160481b6001600160801b038416021790555b817fe986e40cc8c151830d4f61050f4fb2e4add8567caad2d5f5496f9158e91fe4c7826040516108d991815260200190565b60405180910390a25050565b335f908152600160208190526040909120541461093d5760405162461bcd60e51b815260206004820152601660248201527529a82122a0a697b737ba16b330b1b4b634ba30ba37b960511b60448201526064016103c3565b60035460ff16156109875760405162461bcd60e51b815260206004820152601460248201527314d4109150534bdb5bd91d5b194b5a185b1d195960621b60448201526064016103c3565b806109c95760405162461bcd60e51b81526020600482015260126024820152710a6a0848a829a5ecadae0e8f25ac4c2e8c6d60731b60448201526064016103c3565b6003546109f590600160481b81046001600160801b031690610100900467ffffffffffffffff166116d8565b6001600160801b0316421015610a405760405162461bcd60e51b815260206004820152601060248201526f53504245414d2f746f6f2d6561726c7960801b60448201526064016103c3565b60038054600160481b600160c81b031916600160481b426001600160801b0316021790555f805b828110156113a9575f848483818110610a8257610a826116ff565b9050604002015f01359050828111610adc5760405162461bcd60e51b815260206004820152601b60248201527f53504245414d2f757064617465732d6f75742d6f662d6f72646572000000000060448201526064016103c3565b8092505f858584818110610af257610af26116ff565b5f858152600260209081526040918290208251606081018452905461ffff808216835262010000820481168385015264010000000090910416818401819052939092029490940190930135935015159050610b8f5760405162461bcd60e51b815260206004820152601a60248201527f53504245414d2f726174652d6e6f742d636f6e6669677572656400000000000060448201526064016103c3565b805161ffff16821015610bd75760405162461bcd60e51b815260206004820152601060248201526f29a82122a0a697b132b637bb96b6b4b760811b60448201526064016103c3565b806020015161ffff16821115610c225760405162461bcd60e51b815260206004820152601060248201526f0a6a0848a829a5ec2c4deecca5adac2f60831b60448201526064016103c3565b5f83622229a960e91b03610d43577f000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e526001600160a01b031663538af0377f000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf76001600160a01b031663487bf0826040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cdf9190611713565b6040518263ffffffff1660e01b8152600401610cfd91815260200190565b602060405180830381865afa158015610d18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d3c9190611713565b9050610ef2565b836229a9a960e91b03610ddb577f000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e526001600160a01b031663538af0377f000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd6001600160a01b03166303607ceb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbb573d5f803e3d5ffd5b604051636cb1c69b60e11b8152600481018590525f907f00000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f16001600160a01b03169063d9638d36906024016040805180830381865afa158015610e3f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6391906116a2565b5060405163538af03760e01b8152600481018290529091507f000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e526001600160a01b03169063538af03790602401602060405180830381865afa158015610eca573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eee9190611713565b9150505b815161ffff16811015610f0b5750805161ffff16610f26565b816020015161ffff16811115610f265750602081015161ffff165b5f818411610f3d57610f38848361172a565b610f47565b610f47828561172a565b9050826040015161ffff16811115610fa15760405162461bcd60e51b815260206004820152601760248201527f53504245414d2f64656c74612d61626f76652d7374657000000000000000000060448201526064016103c3565b604051630c33fe8160e21b8152600481018590525f907f000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e526001600160a01b0316906330cffa0490602401602060405180830381865afa158015611006573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102a9190611713565b90506b033b2e3c9fd0803ce80000008110156110885760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d726174652d636f6e76000000000000000060448201526064016103c3565b85622229a960e91b0361118a577f000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf76001600160a01b0316639f678cca6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156110ed575f80fd5b505af11580156110ff573d5f803e3d5ffd5b5050604051630a6ba04560e21b8152623239b960e91b6004820152602481018490527f000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf76001600160a01b031692506329ae811491506044015b5f604051808303815f87803b15801561116f575f80fd5b505af1158015611181573d5f803e3d5ffd5b5050505061135d565b856229a9a960e91b0361125e577f000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd6001600160a01b0316639f678cca6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156111ef575f80fd5b505af1158015611201573d5f803e3d5ffd5b5050604051630a6ba04560e21b81526239b9b960e91b6004820152602481018490527f000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd6001600160a01b031692506329ae81149150604401611158565b60405163089c54b560e31b8152600481018790527f00000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f16001600160a01b0316906344e2a5a8906024015f604051808303815f87803b1580156112bd575f80fd5b505af11580156112cf573d5f803e3d5ffd5b5050604051630d05943f60e11b815260048101899052636475747960e01b6024820152604481018490527f00000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f16001600160a01b03169250631a0b287e91506064015f604051808303815f87803b158015611346575f80fd5b505af1158015611358573d5f803e3d5ffd5b505050505b857f28e3246f80515f5c1ed987b133ef2f193439b25acba6a5e69f219e896fc9d1798660405161138f91815260200190565b60405180910390a2505060019094019350610a6792505050565b50505050565b335f908152602081905260409020546001146113dd5760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f81815260016020526040808220829055517f12fdafd291eb287a54e3416070923d22aa5072f5ee04c4fb8361615e7508a37c9190a250565b335f9081526020819052604090205460011461144e5760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f908152602081905260409020546001146114c05760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b335f908152602081905260409020546001146115315760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f81815260016020819052604080832091909155517f6ffc0fabf0709270e42087e84a3bfc36041d3b281266d04ae1962185092fb2449190a250565b5f805f60608486031215611589575f80fd5b505081359360208301359350604090920135919050565b5f80604083850312156115b1575f80fd5b50508035926020909101359150565b5f80602083850312156115d1575f80fd5b823567ffffffffffffffff808211156115e8575f80fd5b818501915085601f8301126115fb575f80fd5b813581811115611609575f80fd5b8660208260061b850101111561161d575f80fd5b60209290920196919550909350505050565b5f6020828403121561163f575f80fd5b81356001600160a01b0381168114611655575f80fd5b9392505050565b5f6020828403121561166c575f80fd5b5035919050565b60208082526015908201527414d4109150534bdb9bdd0b585d5d1a1bdc9a5e9959605a1b604082015260600190565b5f80604083850312156116b3575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b038181168382160190808211156116f8576116f86116c4565b5092915050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611723575f80fd5b5051919050565b8181038181111561173d5761173d6116c4565b9291505056fea2646970667358221220171a334c3d57fecf09a30000854c87d5ce3e51116ffee51d4b016443e319f48164736f6c63430008180033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[":dss-interfaces/=lib/dss-test/lib/dss-interfaces/src/",":dss-test/=lib/dss-test/src/",":forge-std/=lib/forge-std/src/"]},"optimization_runs":200,"sourcify_repo_url":null,"decoded_constructor_args":[["0x19c0976f590D67707E62397C87829d896Dc0f1F1",{"internalType":"address","name":"_jug","type":"address"}],["0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7",{"internalType":"address","name":"_pot","type":"address"}],["0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD",{"internalType":"address","name":"_susds","type":"address"}],["0xea91A18dAFA1Cb1d2a19DFB205816034e6Fe7e52",{"internalType":"address","name":"_conv","type":"address"}]],"compiler_version":"0.8.24+commit.e11b9ed9","is_verified_via_verifier_alliance":true,"verified_at":"2025-07-20T12:40:37.838853Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x61010060405234801562000011575f80fd5b506040516200191a3803806200191a8339810160408190526200003491620000b1565b6001600160a01b0380851660805283811660a05282811660c052811660e052335f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a2505050506200010b565b80516001600160a01b0381168114620000ac575f80fd5b919050565b5f805f8060808587031215620000c5575f80fd5b620000d08562000095565b9350620000e06020860162000095565b9250620000f06040860162000095565b9150620001006060860162000095565b905092959194509250565b60805160a05160c05160e051611779620001a15f395f818161011a01528181610c3201528181610d5201528181610e7d0152610fb901525f818161020001528181610d8101528181611199015261122501525f818161019901528181610c6101528181611097015261112301525f81816102ab0152818161040501528181610df30152818161127401526112fb01526117795ff3fe608060405234801561000f575f80fd5b5060043610610111575f3560e01c806365c4ce7a1161009e5780639c3674fc1161006e5780639c3674fc146102ff5780639c52a7f11461031e578063bf353dbb14610331578063cfc4af5514610350578063f29c29c414610382575f80fd5b806365c4ce7a1461028057806365fae35e1461029357806384718d89146102a657806389afb88a146102cd575f80fd5b80634ba2363a116100e45780634ba2363a1461019457806353a7d8cd146101bb578063552033c4146101e857806358b8f19c146101fb578063646544a014610222575f80fd5b806308b36870146101155780631a0b287e1461015957806329ae81141461016e578063474d857f14610181575b5f80fd5b61013c7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61016c610167366004611577565b610395565b005b61016c61017c3660046115a0565b6106ea565b61016c61018f3660046115c0565b6108e5565b61013c7f000000000000000000000000000000000000000000000000000000000000000081565b6101da6101c936600461162f565b60016020525f908152604090205481565b604051908152602001610150565b6101da6b033b2e3c9fd0803ce800000081565b61013c7f000000000000000000000000000000000000000000000000000000000000000081565b61025b61023036600461165c565b60026020525f908152604090205461ffff808216916201000081048216916401000000009091041683565b6040805161ffff94851681529284166020840152921691810191909152606001610150565b61016c61028e36600461162f565b6113af565b61016c6102a136600461162f565b611420565b61013c7f000000000000000000000000000000000000000000000000000000000000000081565b6003546102e790600160481b90046001600160801b031681565b6040516001600160801b039091168152602001610150565b60035461030c9060ff1681565b60405160ff9091168152602001610150565b61016c61032c36600461162f565b611492565b6101da61033f36600461162f565b5f6020819052908152604090205481565b60035461036990610100900467ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610150565b61016c61039036600461162f565b611503565b335f908152602081905260409020546001146103cc5760405162461bcd60e51b81526004016103c390611673565b60405180910390fd5b82622229a960e91b141580156103e85750826229a9a960e91b14155b156104c957604051636cb1c69b60e11b8152600481018490525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d9638d36906024016040805180830381865afa158015610451573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061047591906116a2565b5090505f81116104c75760405162461bcd60e51b815260206004820152601a60248201527f53504245414d2f696c6b2d6e6f742d696e697469616c697a656400000000000060448201526064016103c3565b505b61ffff8111156105125760405162461bcd60e51b815260206004820152601460248201527353504245414d2f696e76616c69642d76616c756560601b60448201526064016103c3565b816236b4b760e91b0361059d575f8381526002602052604090205462010000900461ffff1681111561057c5760405162461bcd60e51b81526020600482015260136024820152720a6a0848a829a5edad2dc5ae8dede5ad0d2ced606b1b60448201526064016103c3565b5f838152600260205260409020805461ffff191661ffff83161790556106aa565b81620dac2f60eb1b03610628575f8381526002602052604090205461ffff168110156106005760405162461bcd60e51b815260206004820152601260248201527153504245414d2f6d61782d746f6f2d6c6f7760701b60448201526064016103c3565b5f838152600260205260409020805463ffff000019166201000061ffff8416021790556106aa565b81630737465760e41b03610662575f838152600260205260409020805465ffff00000000191664010000000061ffff8416021790556106aa565b60405162461bcd60e51b815260206004820152601e60248201527f53504245414d2f66696c652d756e7265636f676e697a65642d706172616d000060448201526064016103c3565b81837f851aa1caf4888170ad8875449d18f0f512fd6deb2a6571ea1a41fb9f95acbcd1836040516106dd91815260200190565b60405180910390a3505050565b335f908152602081905260409020546001146107185760405162461bcd60e51b81526004016103c390611673565b816218985960ea1b03610792578015806107325750806001145b61077e5760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d6261642d76616c7565000000000000000060448201526064016103c3565b6003805460ff191660ff83161790556108a7565b816274617560e81b0361081e5767ffffffffffffffff8111156107f75760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d7461752d76616c7565000000000000000060448201526064016103c3565b6003805468ffffffffffffffff00191661010067ffffffffffffffff8416021790556108a7565b8162746f6360e81b03610662576001600160801b038111156108825760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d746f632d76616c7565000000000000000060448201526064016103c3565b60038054600160481b600160c81b031916600160481b6001600160801b038416021790555b817fe986e40cc8c151830d4f61050f4fb2e4add8567caad2d5f5496f9158e91fe4c7826040516108d991815260200190565b60405180910390a25050565b335f908152600160208190526040909120541461093d5760405162461bcd60e51b815260206004820152601660248201527529a82122a0a697b737ba16b330b1b4b634ba30ba37b960511b60448201526064016103c3565b60035460ff16156109875760405162461bcd60e51b815260206004820152601460248201527314d4109150534bdb5bd91d5b194b5a185b1d195960621b60448201526064016103c3565b806109c95760405162461bcd60e51b81526020600482015260126024820152710a6a0848a829a5ecadae0e8f25ac4c2e8c6d60731b60448201526064016103c3565b6003546109f590600160481b81046001600160801b031690610100900467ffffffffffffffff166116d8565b6001600160801b0316421015610a405760405162461bcd60e51b815260206004820152601060248201526f53504245414d2f746f6f2d6561726c7960801b60448201526064016103c3565b60038054600160481b600160c81b031916600160481b426001600160801b0316021790555f805b828110156113a9575f848483818110610a8257610a826116ff565b9050604002015f01359050828111610adc5760405162461bcd60e51b815260206004820152601b60248201527f53504245414d2f757064617465732d6f75742d6f662d6f72646572000000000060448201526064016103c3565b8092505f858584818110610af257610af26116ff565b5f858152600260209081526040918290208251606081018452905461ffff808216835262010000820481168385015264010000000090910416818401819052939092029490940190930135935015159050610b8f5760405162461bcd60e51b815260206004820152601a60248201527f53504245414d2f726174652d6e6f742d636f6e6669677572656400000000000060448201526064016103c3565b805161ffff16821015610bd75760405162461bcd60e51b815260206004820152601060248201526f29a82122a0a697b132b637bb96b6b4b760811b60448201526064016103c3565b806020015161ffff16821115610c225760405162461bcd60e51b815260206004820152601060248201526f0a6a0848a829a5ec2c4deecca5adac2f60831b60448201526064016103c3565b5f83622229a960e91b03610d43577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663538af0377f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663487bf0826040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cdf9190611713565b6040518263ffffffff1660e01b8152600401610cfd91815260200190565b602060405180830381865afa158015610d18573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d3c9190611713565b9050610ef2565b836229a9a960e91b03610ddb577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663538af0377f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166303607ceb6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cbb573d5f803e3d5ffd5b604051636cb1c69b60e11b8152600481018590525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d9638d36906024016040805180830381865afa158015610e3f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6391906116a2565b5060405163538af03760e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063538af03790602401602060405180830381865afa158015610eca573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610eee9190611713565b9150505b815161ffff16811015610f0b5750805161ffff16610f26565b816020015161ffff16811115610f265750602081015161ffff165b5f818411610f3d57610f38848361172a565b610f47565b610f47828561172a565b9050826040015161ffff16811115610fa15760405162461bcd60e51b815260206004820152601760248201527f53504245414d2f64656c74612d61626f76652d7374657000000000000000000060448201526064016103c3565b604051630c33fe8160e21b8152600481018590525f907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906330cffa0490602401602060405180830381865afa158015611006573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061102a9190611713565b90506b033b2e3c9fd0803ce80000008110156110885760405162461bcd60e51b815260206004820152601860248201527f53504245414d2f696e76616c69642d726174652d636f6e76000000000000000060448201526064016103c3565b85622229a960e91b0361118a577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639f678cca6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156110ed575f80fd5b505af11580156110ff573d5f803e3d5ffd5b5050604051630a6ba04560e21b8152623239b960e91b6004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692506329ae811491506044015b5f604051808303815f87803b15801561116f575f80fd5b505af1158015611181573d5f803e3d5ffd5b5050505061135d565b856229a9a960e91b0361125e577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639f678cca6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156111ef575f80fd5b505af1158015611201573d5f803e3d5ffd5b5050604051630a6ba04560e21b81526239b9b960e91b6004820152602481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031692506329ae81149150604401611158565b60405163089c54b560e31b8152600481018790527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906344e2a5a8906024015f604051808303815f87803b1580156112bd575f80fd5b505af11580156112cf573d5f803e3d5ffd5b5050604051630d05943f60e11b815260048101899052636475747960e01b6024820152604481018490527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169250631a0b287e91506064015f604051808303815f87803b158015611346575f80fd5b505af1158015611358573d5f803e3d5ffd5b505050505b857f28e3246f80515f5c1ed987b133ef2f193439b25acba6a5e69f219e896fc9d1798660405161138f91815260200190565b60405180910390a2505060019094019350610a6792505050565b50505050565b335f908152602081905260409020546001146113dd5760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f81815260016020526040808220829055517f12fdafd291eb287a54e3416070923d22aa5072f5ee04c4fb8361615e7508a37c9190a250565b335f9081526020819052604090205460011461144e5760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f908152602081905260409020546001146114c05760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b335f908152602081905260409020546001146115315760405162461bcd60e51b81526004016103c390611673565b6001600160a01b0381165f81815260016020819052604080832091909155517f6ffc0fabf0709270e42087e84a3bfc36041d3b281266d04ae1962185092fb2449190a250565b5f805f60608486031215611589575f80fd5b505081359360208301359350604090920135919050565b5f80604083850312156115b1575f80fd5b50508035926020909101359150565b5f80602083850312156115d1575f80fd5b823567ffffffffffffffff808211156115e8575f80fd5b818501915085601f8301126115fb575f80fd5b813581811115611609575f80fd5b8660208260061b850101111561161d575f80fd5b60209290920196919550909350505050565b5f6020828403121561163f575f80fd5b81356001600160a01b0381168114611655575f80fd5b9392505050565b5f6020828403121561166c575f80fd5b5035919050565b60208082526015908201527414d4109150534bdb9bdd0b585d5d1a1bdc9a5e9959605a1b604082015260600190565b5f80604083850312156116b3575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52601160045260245ffd5b6001600160801b038181168382160190808211156116f8576116f86116c4565b5092915050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611723575f80fd5b5051919050565b8181038181111561173d5761173d6116c4565b9291505056fea2646970667358221220171a334c3d57fecf09a30000854c87d5ce3e51116ffee51d4b016443e319f48164736f6c6343000818003300000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f1000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf7000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e52","name":"SPBEAM","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_jug","type":"address"},{"internalType":"address","name":"_pot","type":"address"},{"internalType":"address","name":"_susds","type":"address"},{"internalType":"address","name":"_conv","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Diss","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Kiss","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Rely","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"bps","type":"uint256"}],"name":"Set","type":"event"},{"inputs":[],"name":"RAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bad","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"buds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"cfgs","outputs":[{"internalType":"uint16","name":"min","type":"uint16"},{"internalType":"uint16","name":"max","type":"uint16"},{"internalType":"uint16","name":"step","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"conv","outputs":[{"internalType":"contract ConvLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"diss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"uint256","name":"data","type":"uint256"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"uint256","name":"data","type":"uint256"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"jug","outputs":[{"internalType":"contract JugLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"kiss","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pot","outputs":[{"internalType":"contract PotLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"bps","type":"uint256"}],"internalType":"struct SPBEAM.ParamChange[]","name":"updates","type":"tuple[]"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"susds","outputs":[{"internalType":"contract SUSDSLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tau","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toc","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x00000000000000000000000019c0976f590d67707e62397c87829d896dc0f1f1000000000000000000000000197e90f9fad81970ba7976f33cbd77088e5d7cf7000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd000000000000000000000000ea91a18dafa1cb1d2a19dfb205816034e6fe7e52"}