{"file_path":"apps/tokenization/SygToken/contracts/SygToken.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport {StorageLayout} from './storage/StorageLayout.sol';\nimport {Initializable} from \"libs/Initializable/Initializable.sol\";\nimport {ERC20SygToken} from \"./ERC20SygToken.sol\";\nimport {UUPSTimelockUpgradeable} from \"libs/UUPS/UUPSTimelockUpgradeable.sol\";\nimport {ChainlinkDataFeed} from \"./ChainlinkDataFeed.sol\";\nimport {ISygFactory} from \"apps/tokenization/SygFactory/interfaces/ISygFactory.sol\";\nimport {PausableSygToken} from \"./PausableSygToken.sol\";\nimport {FundRecoveryCore} from \"libs/FundRecovery/FundRecoveryCore.sol\";\n\n/**\n * @title SygToken\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Tokenization contract for creating and managing digital assets with role-based permissions\n * @dev This contract combines ERC20 functionality with permission management for controlled tokenization.\n *      It supports features like minting, burning, and transfer restrictions based on user roles.\n *      Uses UUPSTimelockUpgradeable for secure, delayed upgrades.\n */\n // TODO: Inherit from ISygToken\n/**\n * @custom:security-contact blockchain@sygnum.com\n */\ncontract SygToken is Initializable, ERC20SygToken, UUPSTimelockUpgradeable, ChainlinkDataFeed, PausableSygToken, FundRecoveryCore {\n    /* ======== ERRORS ======== */\n\n    error ContractNotInitializedAfterUpgrade();\n    error UnauthorizedUpgrade(address caller, address expectedPermissionManager);\n    error SameTokenURI(string _tokenURI);\n\n    /* ======== EVENTS ======== */\n\n    event TokenURIUpdated(string previousTokenURI, string newTokenURI);\n    event ForcedTransfer(address indexed from, address indexed to, uint256 amount);\n\n    /* ======== INITIALIZER ======== */\n\n    /**\n     * @notice Initializes the SygToken contract\n     * @param _name The name of the token\n     * @param _symbol The symbol of the token\n     * @param _decimals The number of decimals for the token\n     * @param _tokenURI The URI for the token metadata\n     * @param _permissionManagerAddress Address of the permission manager contract\n     * @param _timelockDelaySeconds The delay in seconds before upgrades can be executed\n     */\n    function initialize(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals,\n        string memory _tokenURI,\n        address _permissionManagerAddress,\n        uint256 _timelockDelaySeconds\n    ) public onlyProxy initializer {\n        _erc20_init(_name, _symbol, _decimals);\n        _permissioned_init(_permissionManagerAddress);\n        _UUPSTimelock_init(_timelockDelaySeconds);\n        if (bytes(getTokenURI).length == 0) {\n            getTokenURI = _tokenURI;\n        }\n    }\n\n    /* ======== EXTERNAL/PUBLIC STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice Forcefully transfers tokens from any account to a whitelisted receiver\n     * @param _from The sender address\n     * @param _to The recipient address (must be TOKEN_USER)\n     * @param _amount The amount to transfer\n     */\n    function forcedTransfer(address _from, address _to, uint256 _amount) external onlyTokenUser(_to) requiresAuth whenNotPaused {\n        _transfer(_from, _to, _amount);\n        emit ForcedTransfer(_from, _to, _amount);\n    }\n\n    /**\n     * @notice Updates the token URI\n     * @param _newTokenURI The new token URI\n     */\n    function updateTokenURI(string memory _newTokenURI) external requiresAuth whenNotPaused {\n        string memory _previousTokenURI = getTokenURI;\n        if (keccak256(bytes(_previousTokenURI)) == keccak256(bytes(_newTokenURI))) {\n            revert SameTokenURI(_newTokenURI);\n        }\n        getTokenURI = _newTokenURI;\n        emit TokenURIUpdated(_previousTokenURI, _newTokenURI);\n    }\n\n    /**\n     * @notice Recovers funds from the contract\n     * @dev If _token is address(0), recovers native token (ETH), else recovers ERC20 tokens\n     * For ERC-20 tokens, the emitted amounts include both the requested amount and the actual amount received,\n     * which may differ for fee-on-transfer tokens.\n     * @param _token The token address (zero for native)\n     * @param _to The recipient address\n     * @param _amount The amount to recover (in wei for native ETH, in token's smallest unit for ERC-20)\n     */\n    function recoverFunds(address _token, address payable _to, uint256 _amount) external requiresAuth whenNotPaused {\n        _recoverFunds(_token, _to, _amount);\n    }\n\n    /* ======== VIEW FUNCTIONS ======== */\n\n    /**\n     * @notice Marker function to identify SygToken implementations\n     * @dev This function provides a reliable way to check if a contract is a SygToken implementation\n     *      without relying on functions that may revert in certain states (like getPriceFeedDecimals\n     *      when oracle is not configured). This is used by SygTokenChecker for safe interface detection.\n     * @return True, indicating this is a SygToken implementation\n     */\n    function isSygTokenImplementation() external pure returns (bool) {\n        return true;\n    }\n\n    /* ======== UUPS UPGRADE HOOKS ======== */\n\n    /**\n     * @notice Authorizes upgrade to a new implementation\n     * @dev Only callable by the permission manager (TokenManager/SygFactory)\n     */\n    function _authorizeUpgrade(\n        address,\n        bytes memory\n    ) internal view virtual override {\n        if (msg.sender != getPermissionManagerAddress()) {\n            revert UnauthorizedUpgrade(msg.sender, getPermissionManagerAddress());\n        }\n    }\n\n    /**\n     * @notice Hook that is called before an upgrade is executed\n     * @dev Resets the initialized state only if upgrade data is provided (indicating re-initialization is needed)\n     */\n    function _preUpgradeToAndCallUUPS(address, bytes memory _data) internal virtual override {\n        if (_data.length > 0) {\n            _resetInitialized();\n        }\n    }\n\n    /**\n     * @notice Hook that is called after an upgrade is executed\n     * @dev Enforces that initialization must happen after upgrade when data is provided\n     */\n    function _postUpgradeToAndCallUUPS(\n        address,\n        bytes memory _data\n    ) internal view virtual override {\n        if (_data.length > 0 && !isInitialized()) {\n            revert ContractNotInitializedAfterUpgrade();\n        }\n    }\n}\n","deployed_bytecode":"0x608060405234801561000f575f5ffd5b5060043610610325575f3560e01c806364dad32f116101a85780639fc1d0e7116100f3578063c9c16fbd1161009e578063dd62ed3e11610079578063dd62ed3e1461066c578063ef3e8f221461067f578063f2e23d2214610692578063f8fa842b1461069a575f5ffd5b8063c9c16fbd1461063e578063d4a1911614610651578063d505accf14610659575f5ffd5b8063b187bd26116100ce578063b187bd2614610619578063bf4dc4b614610621578063c1491c5814610628575f5ffd5b80639fc1d0e7146105eb578063a9059cbb146105fe578063aaf10f4214610611575f5ffd5b80638456cb591161015357806398d2082f1161012e57806398d2082f1461059857806398d5fdca146105bb5780639dc29fac146105d8575f5ffd5b80638456cb591461057557806395d89b411461057d57806398cd615314610585575f5ffd5b80637ab8bf5a116101835780637ab8bf5a146105475780637e8962141461055a5780637ecebe0014610562575f5ffd5b806364dad32f1461050e5780636d70f7ae1461052157806370a0823114610534575f5ffd5b80633f4ba83a116102735780634f1ef2861161021e5780635845394b116101f95780635845394b146104aa5780635965959e146104d55780635ca13f04146104e85780635d3590d5146104fb575f5ffd5b80634f1ef2861461048757806352d1902d1461049a57806355f29166146104a2575f5ffd5b8063426796831161024e578063426796831461044e578063440fde4e1461046157806346fbf68e14610474575f5ffd5b80633f4ba83a1461041e57806340c10f1914610426578063422f8c0a14610439575f5ffd5b80632d524393116102d357806334cdcf26116102ae57806334cdcf26146103fb5780633644e5151461040e578063392e53cd14610416575f5ffd5b80632d524393146103bb578063313ce567146103ce57806333999fa6146103e8575f5ffd5b806318160ddd1161030357806318160ddd1461037f57806323b872dd14610395578063257e224c146103a8575f5ffd5b806306fdde031461032957806307e2a26014610347578063095ea7b31461035c575b5f5ffd5b6103316106a2565b60405161033e91906137ba565b60405180910390f35b61035a6103553660046137ed565b6106b1565b005b61036f61036a366004613824565b6107ad565b604051901515815260200161033e565b610387610807565b60405190815260200161033e565b61036f6103a336600461384e565b610830565b61035a6103b636600461395f565b6109b0565b61036f6103c9366004613a1c565b610a33565b6103d6610ad3565b60405160ff909116815260200161033e565b61035a6103f6366004613a3e565b610aff565b61036f610409366004613a1c565b610b0d565b610387610b2b565b61036f610b34565b61035a610b4a565b61035a610434366004613824565b610b69565b610441610c4d565b60405161033e9190613a9e565b61036f61045c366004613a1c565b610dc0565b61035a61046f366004613a1c565b610dde565b61036f610482366004613a1c565b610e7e565b61035a610495366004613a3e565b610e9c565b610387610eae565b61035a610ebf565b6001546104bd906001600160a01b031681565b6040516001600160a01b03909116815260200161033e565b61035a6104e33660046137ed565b610ef3565b61035a6104f63660046137ed565b610fe3565b61035a61050936600461384e565b6110d3565b61036f61051c366004613a1c565b611123565b61036f61052f366004613a1c565b611141565b610387610542366004613a1c565b61115f565b61036f610555366004613a1c565b61119b565b61035a6111b9565b610387610570366004613a1c565b6111ed565b61035a611229565b610331611246565b61035a610593366004613ae3565b611250565b6105ab6105a6366004613b15565b611399565b60405161033e9493929190613b2c565b6105c36113b6565b6040805192835260208301919091520161033e565b61035a6105e6366004613824565b6114d0565b61035a6105f936600461384e565b6115af565b61036f61060c366004613824565b6116e3565b6104bd6117cc565b61036f6117e2565b600161036f565b6106306117fb565b60405161033e929190613b60565b61035a61064c3660046137ed565b61192f565b610331611a1e565b61035a610667366004613b81565b611aa9565b61038761067a366004613bed565b611b97565b61035a61068d366004613a1c565b611be2565b6104bd611c03565b610331611c22565b60606106ac611cc5565b905090565b6106c6335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156106f65760405163ab35696f60e01b815260040160405180910390fd5b6106fe611c03565b604051636bcd157760e11b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063d79a2aee906064015f604051808303815f87803b15801561074e575f5ffd5b505af1158015610760573d5f5f3e3d5ffd5b50505050816001600160a01b03167fd4145d5d40015b9d77048466bbe3ff2411630f7b70f80f9d79c273b6311aba74826040516107a1911515815260200190565b60405180910390a25050565b5f6107c3335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156107f35760405163ab35696f60e01b815260040160405180910390fd5b6107fe338484611e69565b90505b92915050565b5f6106ac7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385035490565b5f610846335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0385166004820152849030906364dad32f90602401602060405180830381865afa15801561088a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ae9190613c19565b6108db576040516326865f9b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b6040516364dad32f60e01b81526001600160a01b0385166004820152849030906364dad32f90602401602060405180830381865afa15801561091f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109439190613c19565b61096b576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff161561099b5760405163ab35696f60e01b815260040160405180910390fd5b6109a6868686611f3c565b9695505050505050565b6109b8611fd0565b5f5160206141bc5f395f51905f5254156109e55760405163f92ee8a960e01b815260040160405180910390fd5b6109ed61206b565b6109f88686866120a6565b610a0182612122565b610a0a81612148565b5f8054610a1690613c34565b90505f03610a2b575f610a298482613cb7565b505b505050505050565b5f610a3c611c03565b6001600160a01b031663970f8482835f5b604051908082528060200260200182016040528015610a76578160200160208202803683370190505b506040518363ffffffff1660e01b8152600401610a94929190613d72565b602060405180830381865afa158015610aaf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108019190613c19565b5f6106ac7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385025460ff1690565b610b098282612188565b5050565b5f610b16611c03565b6001600160a01b031663f5fe5787835f610a4d565b5f6106ac6121dd565b5f6106ac5f5160206141bc5f395f51905f525490565b610b5f335f356001600160e01b031916611d66565b610b6761222c565b565b610b7e335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0383166004820152829030906364dad32f90602401602060405180830381865afa158015610bc2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be69190613c19565b610c0e576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff1615610c3e5760405163ab35696f60e01b815260040160405180910390fd5b610c48838361229c565b505050565b6001546060906001600160a01b0316610c7b57604051631f93601760e01b81525f60048201526024016108d2565b600154610c90906001600160a01b0316612339565b15610d0b5760015f9054906101000a90046001600160a01b03166001600160a01b0316639d91348d6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610ce4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106ac9190810190613dcc565b6040805160018082528183019092525f916020808301908036833750506001546040805163313ce56760e01b815290519394506001600160a01b039091169263313ce567925060048083019260209291908290030181865afa158015610d73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d979190613e80565b815f81518110610da957610da9613e9b565b60ff90921660209283029190910190910152919050565b5f610dc9611c03565b6001600160a01b031663ffb2f26f835f610a4d565b610df3335f356001600160e01b031916611d66565b6001546001600160a01b039081169082168103610e2e57604051631eeb14f160e01b81526001600160a01b03831660048201526024016108d2565b600180546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fd76fb624f0e2e090c9f82772a08d122c79250c90c7a896b1ed0de8bbe3e9e2e4905f90a35050565b5f610e87611c03565b6001600160a01b0316636f06fa43835f610a4d565b610ea4611fd0565b610b0982826123b0565b5f610eb76123cc565b6106ac612415565b5f51602061421c5f395f51905f5254610eeb57604051630604a9ff60e01b815260040160405180910390fd5b610b67612430565b610f08335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff1615610f385760405163ab35696f60e01b815260040160405180910390fd5b610f40611c03565b604051632b73cd6360e21b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063adcf358c906064015f604051808303815f87803b158015610f90575f5ffd5b505af1158015610fa2573d5f5f3e3d5ffd5b50505050816001600160a01b03167fc71e52f779c12ade7cbf75a51deb27377b5addd6a3945e0b356bff858ffad7fb826040516107a1911515815260200190565b610ff8335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156110285760405163ab35696f60e01b815260040160405180910390fd5b611030611c03565b60405163361fa22b60e01b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063361fa22b906064015f604051808303815f87803b158015611080575f5ffd5b505af1158015611092573d5f5f3e3d5ffd5b50505050816001600160a01b03167f6b410344a541a2ad2ffec50ea1cafabe58c50db82f72ae4f46a4bd2419155b15826040516107a1911515815260200190565b6110e8335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156111185760405163ab35696f60e01b815260040160405180910390fd5b610c4883838361247b565b5f61112c611c03565b6001600160a01b031663f2563ef3835f610a4d565b5f61114a611c03565b6001600160a01b031663394340e8835f610a4d565b6001600160a01b0381165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385046020526040812054610801565b5f6111a4611c03565b6001600160a01b03166378143d56835f610a4d565b5f51602061421c5f395f51905f52546111e557604051630604a9ff60e01b815260040160405180910390fd5b610b67612730565b6001600160a01b0381165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385086020526040812054610801565b61123e335f356001600160e01b031916611d66565b610b67612771565b60606106ac6127e5565b611265335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156112955760405163ab35696f60e01b815260040160405180910390fd5b5f5f80546112a290613c34565b80601f01602080910402602001604051908101604052809291908181526020018280546112ce90613c34565b80156113195780601f106112f057610100808354040283529160200191611319565b820191905f5260205f20905b8154815290600101906020018083116112fc57829003601f168201915b5050505050905081805190602001208180519060200120036113505781604051638651f2a560e01b81526004016108d291906137ba565b5f61135b8382613cb7565b507ffd07e2c2d6dc82f4d6b1b46f25e49eb888aba92d238fb40945856412cce2f2dd818360405161138d929190613eaf565b60405180910390a15050565b5f60605f5f6113a785612823565b93509350935093509193509193565b6001545f9081906001600160a01b031615806113e257506001546113e2906001600160a01b0316612339565b1561140f57600154604051631f93601760e01b81526001600160a01b0390911660048201526024016108d2565b60015f9054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561145f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114839190613ef5565b5091945090925050505f8190036114ad57604051638ad52bdd60e01b815260040160405180910390fd5b5f82136114cc5760405162bfc92160e01b815260040160405180910390fd5b9091565b6114e5335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0383166004820152829030906364dad32f90602401602060405180830381865afa158015611529573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061154d9190613c19565b611575576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff16156115a55760405163ab35696f60e01b815260040160405180910390fd5b610c48838361294f565b6040516364dad32f60e01b81526001600160a01b0383166004820152829030906364dad32f90602401602060405180830381865afa1580156115f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116179190613c19565b61163f576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b611654335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156116845760405163ab35696f60e01b815260040160405180910390fd5b61168f8484846129f1565b50826001600160a01b0316846001600160a01b03167f7b3ce50c216d2ccf9919c6b9f1bfb33f0350a33010f188750b4af38e00448138846040516116d591815260200190565b60405180910390a350505050565b5f6116f9335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0384166004820152839030906364dad32f90602401602060405180830381865afa15801561173d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117619190613c19565b611789576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff16156117b95760405163ab35696f60e01b815260040160405180910390fd5b6117c43385856129f1565b949350505050565b5f6106ac5f5160206141dc5f395f51905f525490565b5f6106ac5f5160206141fc5f395f51905f525460ff1690565b6001546060905f906001600160a01b0316158061182a5750600154611828906001600160a01b0316612339565b155b1561185757600154604051631f93601760e01b81526001600160a01b0390911660048201526024016108d2565b600154604080516328f5843360e21b815290516001600160a01b0390921691829163a3d610cc9160048083019260209291908290030181865afa1580156118a0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118c49190613f43565b9150806001600160a01b0316639198274f6040518163ffffffff1660e01b81526004015f60405180830381865afa158015611901573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526119289190810190613fae565b9250509091565b611944335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156119745760405163ab35696f60e01b815260040160405180910390fd5b61197c611c03565b604051624ff82360e21b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063013fe08c906064015f604051808303815f87803b1580156119cb575f5ffd5b505af11580156119dd573d5f5f3e3d5ffd5b50505050816001600160a01b03167f5e20cf47b2259b331d4b7c60c19f771fc77bd7b207cb6438d0d217ea67755b57826040516107a1911515815260200190565b5f8054611a2a90613c34565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5690613c34565b8015611aa15780601f10611a7857610100808354040283529160200191611aa1565b820191905f5260205f20905b815481529060010190602001808311611a8457829003601f168201915b505050505081565b611abe335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0388166004820152879030906364dad32f90602401602060405180830381865afa158015611b02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b269190613c19565b611b4e576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff1615611b7e5760405163ab35696f60e01b815260040160405180910390fd5b611b8d88888888888888612ade565b5050505050505050565b6001600160a01b038083165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838505602090815260408083209385168352929052908120546107fe565b611bf7335f356001600160e01b031916611d66565b611c0081612d08565b50565b5f6106ac5f51602061423c5f395f51905f52546001600160a01b031690565b6001546060906001600160a01b0316611c5057604051631f93601760e01b81525f60048201526024016108d2565b60015460408051633942720b60e11b815290516001600160a01b03909216918291637284e416916004808301925f9291908290030181865afa158015611c98573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cbf9190810190613fe0565b91505090565b5f51602061425c5f395f51905f528054606091908190611ce490613c34565b80601f0160208091040260200160405190810160405280929190818152602001828054611d1090613c34565b8015611d5b5780601f10611d3257610100808354040283529160200191611d5b565b820191905f5260205f20905b815481529060010190602001808311611d3e57829003601f168201915b505050505091505090565b5f5f611d865f51602061423c5f395f51905f52546001600160a01b031690565b6040516001600160a01b0386811660248301526001600160e01b031986166044830152919091169060640160408051601f198184030181529181526020820180516001600160e01b0316630435f69f60e51b17905251611de69190614025565b5f60405180830381855afa9150503d805f8114611e1e576040519150601f19603f3d011682016040523d82523d5f602084013e611e23565b606091505b5091509150811580611e46575080806020019051810190611e449190613c19565b155b15611e63576040516282b42960e81b815260040160405180910390fd5b50505050565b5f6001600160a01b0384161580611e8757506001600160a01b038316155b15611ea55760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038481165f8181527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838505602090815260408083209488168084529482529182902086905590518581525f51602061425c5f395f51905f529392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3506001949350505050565b6001600160a01b0383165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838505602090815260408083203384529091528120545f51602061425c5f395f51905f52905f198114611fc557611f9f848261404f565b6001600160a01b0387165f90815260058401602090815260408083203384529091529020555b6109a68686866129f1565b306001600160a01b037f0000000000000000000000007030fe438be6ed196b8886616bbf5a245c26733916148061204d57507f0000000000000000000000007030fe438be6ed196b8886616bbf5a245c2673396001600160a01b03166120415f5160206141dc5f395f51905f525490565b6001600160a01b031614155b15610b675760405163703e46dd60e11b815260040160405180910390fd5b60015f5160206141bc5f395f51905f52556040517f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c8905f90a1565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838506545f51602061425c5f395f51905f52905f03611e6357806120e88582613cb7565b50600181016120f78482613cb7565b5060028101805460ff191660ff8416179055466006820155612117612d36565b600782015550505050565b5f51602061423c5f395f51905f5280546001600160a01b0316610b0957610b0982612d08565b7f2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c824401545f51602061421c5f395f51905f52905f03610b0957610b0982612de0565b604051309033907f16f2354671bbabcb07367cc01a78931a00a812ee080430be4e8f1a76ab58212b905f90a33330146121d35760405162e6155960e41b815260040160405180910390fd5b610b098282612e24565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838506545f905f51602061425c5f395f51905f529046146122235761221e612d36565b611cbf565b60070154919050565b5f5160206141fc5f395f51905f525460ff1661225b5760405163dcdde9dd60e01b815260040160405180910390fd5b5f5160206141fc5f395f51905f52805460ff191681556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a150565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d83850380545f51602061425c5f395f51905f529183915f906122dd908490614062565b90915550506001600160a01b0383165f8181526004830160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a3505050565b5f816001600160a01b0316639d91348d6040518163ffffffff1660e01b81526004015f60405180830381865afa92505050801561239757506040513d5f823e601f3d908101601f191682016040526123949190810190613dcc565b60015b6123a257505f919050565b50600192915050565b919050565b6123b8611fd0565b6123c28282612e42565b610b098282612e97565b306001600160a01b037f0000000000000000000000007030fe438be6ed196b8886616bbf5a245c2673391614610b675760405163703e46dd60e11b815260040160405180910390fd5b5f61241e6123cc565b505f5160206141dc5f395f51905f5290565b5f51602061421c5f395f51905f5280545f61244a82611399565b50509150505f5f61245a83612ea1565b915091506124688282612e42565b61247184612ef4565b50505f9092555050565b5f806001600160a01b038516612501576040516001600160a01b0385169084905f81818185875af1925050503d805f81146124d1576040519150601f19603f3d011682016040523d82523d5f602084013e6124d6565b606091505b505080925050816124fa576040516312171d8360e31b815260040160405180910390fd5b50816126d3565b6040516370a0823160e01b81526001600160a01b03858116600483015286915f918316906370a0823190602401602060405180830381865afa158015612549573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061256d9190613f43565b604080516001600160a01b03898116602483015260448083018a905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151929350606092918a16916125ca9190614025565b5f604051808303815f865af19150503d805f8114612603576040519150601f19603f3d011682016040523d82523d5f602084013e612608565b606091505b50909550905084158061263757505f81511180156126375750808060200190518101906126359190613c19565b155b15612655576040516312171d8360e31b815260040160405180910390fd5b6040516370a0823160e01b81526001600160a01b0388811660048301525f91908516906370a0823190602401602060405180830381865afa15801561269c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c09190613f43565b90506126cc838261404f565b9450505050505b836001600160a01b0316856001600160a01b03167f7a43eea7e0e6937c4baa97b10dabb89519feb249fe9ddcb442415b029148520d8584604051612721929190918252602082015260400190565b60405180910390a35050505050565b5f51602061421c5f395f51905f5280545f61274a82611399565b50509150505f5f61275a83612ea1565b915091506127688282612e42565b61247184612faf565b5f5160206141fc5f395f51905f525460ff16156127a15760405163ab35696f60e01b815260040160405180910390fd5b5f5160206141fc5f395f51905f52805460ff191660011781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a150565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d83850180546060915f51602061425c5f395f51905f5291611ce490613c34565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70260209081526040808320815160808101835281546001600160a01b03168152600182015493810193909352600281018054606094869485945f51602061419c5f395f51905f52948694919284019161289f90613c34565b80601f01602080910402602001604051908101604052809291908181526020018280546128cb90613c34565b80156129165780601f106128ed57610100808354040283529160200191612916565b820191905f5260205f20905b8154815290600101906020018083116128f957829003601f168201915b505050505081526020016003820154815250509050805f0151816040015182602001518360600151955095509550955050509193509193565b6001600160a01b0382165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385046020526040812080545f51602061425c5f395f51905f52928492916129a490849061404f565b909155505060038101805483900390556040518281525f906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161232c565b5f6001600160a01b0384161580612a0f57506001600160a01b038316155b15612a2d5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0384165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385046020526040812080545f51602061425c5f395f51905f5292859291612a8290849061404f565b90915550506001600160a01b038085165f818152600484016020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611f299087815260200190565b42841015612aff576040516305787bdf60e01b815260040160405180910390fd5b6001600160a01b0387165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d83850860205260408120805460018082019092555f51602061425c5f395f51905f52929091612b586121dd565b604080517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960208201526001600160a01b03808f1692820192909252908c166060820152608081018b905260a0810185905260c081018a905260e00160405160208183030381529060405280519060200120604051602001612bf192919061190160f01b81526002810192909252602282015260420190565b60408051601f1981840301815282825280516020918201205f84529083018083525260ff891690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015612c4c573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b0381161580612c815750896001600160a01b0316816001600160a01b031614155b15612c9f57604051632057875960e21b815260040160405180910390fd5b50506001600160a01b038881165f8181526005840160209081526040808320948c16808452948252918290208a905590518981527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050505050505050565b5f51602061423c5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b6040515f905f51602061425c5f395f51905f52907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90612d77908390614075565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c0016040516020818303038152906040528051906020012091505090565b805f03612e00576040516327df2edd60e11b815260040160405180910390fd5b7f2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c82440155565b612e2e8282613202565b612e38828261321e565b610b098282613273565b612e4a611c03565b6001600160a01b0316336001600160a01b031614610b095733612e6b611c03565b60405163fe6cd27560e01b81526001600160a01b039283166004820152911660248201526044016108d2565b610b0982826132a6565b5f6060606483511015612ec75760405163fc69850b60e01b815260040160405180910390fd5b8251612ed7908490600490613363565b806020019051810190612eea91906140e6565b9094909350915050565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70160205260409020545f51602061419c5f395f51905f529015610b09575f8281526001808301602090815260408084208490556002808601909252832080546001600160a01b0319168155918201839055909190612f7890830182613742565b505f60039190910181905560405183917f134fdd648feeaf30251f0157f9624ef8608ff9a042aad6d13e73f35d21d3f88d91a25050565b612fb8816133e2565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70260209081526040808320815160808101835281546001600160a01b031681526001820154938101939093526002810180545f51602061419c5f395f51905f529594938401919061302c90613c34565b80601f016020809104026020016040519081016040528092919081815260200182805461305890613c34565b80156130a35780601f1061307a576101008083540402835291602001916130a3565b820191905f5260205f20905b81548152906001019060200180831161308657829003601f168201915b50505091835250506003919091015460209182015281519082015160408301519293509091478211156130f15760405162fae2d560e21b8152600481018390524760248201526044016108d2565b5f8681526001808701602090815260408084208490556002808a01909252832080546001600160a01b031916815591820183905590919061313490830182613742565b600382015f905550505f836001600160a01b031683836040516131579190614025565b5f6040518083038185875af1925050503d805f8114613191576040519150601f19603f3d011682016040523d82523d5f602084013e613196565b606091505b50509050806131bb5760405163165a1d4160e01b8152600481018890526024016108d2565b867fbc76564aec85e3f50672da2d1ddca0390851fecefe61cd19d89dea91a8267829858585426040516131f1949392919061412a565b60405180910390a250505050505050565b805115610b0957610b095f5f5160206141bc5f395f51905f5255565b6132278261345f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561326b57610c488282613479565b610b09613505565b5f81511180156132885750613286610b34565b155b15610b095760405163b3a31bfd60e01b815260040160405180910390fd5b5f51602061421c5f395f51905f5254156132d35760405163e741fd4560e01b815260040160405180910390fd5b7f2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c824401545f51602061421c5f395f51905f52905f906133109042614062565b90505f61335a30868660405160240161332a929190614162565b60408051601f198184030181529190526020810180516001600160e01b03166319cccfd360e11b17905284613524565b90925550505050565b606061337082855161363e565b915061337c838361363e565b9250613388838361404f565b67ffffffffffffffff8111156133a0576133a061388c565b6040519080825280601f01601f1916602001820160405280156133ca576020820181803683370190505b509050828203836020860101602083015e9392505050565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70160205260408120545f51602061419c5f395f51905f529181900361343e57604051634b9aaa0960e11b815260040160405180910390fd5b80421015610c4857604051630f0b32ff60e11b815260040160405180910390fd5b61346881613653565b5f5160206141dc5f395f51905f5255565b60605f5f846001600160a01b0316846040516134959190614025565b5f60405180830381855af49150503d805f81146134cd576040519150601f19603f3d011682016040523d82523d5f602084013e6134d2565b606091505b5091509150816117c4578051156134ec5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b3415610b675760405163b398979f60e01b815260040160405180910390fd5b5f8142106135455760405163b7d0949760e01b815260040160405180910390fd5b5f51602061419c5f395f51905f5280543490825f61356283614183565b909155505081545f81815260018085016020908152604080842089905580516080810182526001600160a01b038c811682528184018881528284018d8152606084018d90528888526002808c0190965293909620825181546001600160a01b0319169216919091178155945193850193909355519396509092908201906135e99082613cb7565b5060608201518160030155905050827f8d6fedd41517ab865c3658696c50923b3493c8a93ffd016d919a599f03c7531b8783888860405161362d949392919061412a565b60405180910390a250509392505050565b5f81831061364c57816107fe565b5090919050565b806001600160a01b03163b5f0361368857604051634c9c8ce360e01b81526001600160a01b03821660048201526024016108d2565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156136e2575060408051601f3d908101601f191682019092526136df91810190613f43565b60015b61370a57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016108d2565b5f5160206141dc5f395f51905f528114610b0957604051634c9c8ce360e01b81526001600160a01b03831660048201526024016108d2565b50805461374e90613c34565b5f825580601f1061375d575050565b601f0160209004905f5260205f2090810190611c0091905b80821115613788575f8155600101613775565b5090565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6107fe602083018461378c565b6001600160a01b0381168114611c00575f5ffd5b8015158114611c00575f5ffd5b5f5f604083850312156137fe575f5ffd5b8235613809816137cc565b91506020830135613819816137e0565b809150509250929050565b5f5f60408385031215613835575f5ffd5b8235613840816137cc565b946020939093013593505050565b5f5f5f60608486031215613860575f5ffd5b833561386b816137cc565b9250602084013561387b816137cc565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156138c9576138c961388c565b604052919050565b5f67ffffffffffffffff8211156138ea576138ea61388c565b50601f01601f191660200190565b5f61390a613905846138d1565b6138a0565b905082815283838301111561391d575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112613942575f5ffd5b6107fe838335602085016138f8565b60ff81168114611c00575f5ffd5b5f5f5f5f5f5f60c08789031215613974575f5ffd5b863567ffffffffffffffff81111561398a575f5ffd5b61399689828a01613933565b965050602087013567ffffffffffffffff8111156139b2575f5ffd5b6139be89828a01613933565b95505060408701356139cf81613951565b9350606087013567ffffffffffffffff8111156139ea575f5ffd5b6139f689828a01613933565b9350506080870135613a07816137cc565b9598949750929591949360a090920135925050565b5f60208284031215613a2c575f5ffd5b8135613a37816137cc565b9392505050565b5f5f60408385031215613a4f575f5ffd5b8235613a5a816137cc565b9150602083013567ffffffffffffffff811115613a75575f5ffd5b8301601f81018513613a85575f5ffd5b613a94858235602084016138f8565b9150509250929050565b602080825282518282018190525f918401906040840190835b81811015613ad857835160ff16835260209384019390920191600101613ab7565b509095945050505050565b5f60208284031215613af3575f5ffd5b813567ffffffffffffffff811115613b09575f5ffd5b6117c484828501613933565b5f60208284031215613b25575f5ffd5b5035919050565b6001600160a01b0385168152608060208201525f613b4d608083018661378c565b6040830194909452506060015292915050565b604081525f613b72604083018561378c565b90508260208301529392505050565b5f5f5f5f5f5f5f60e0888a031215613b97575f5ffd5b8735613ba2816137cc565b96506020880135613bb2816137cc565b955060408801359450606088013593506080880135613bd081613951565b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215613bfe575f5ffd5b8235613c09816137cc565b91506020830135613819816137cc565b5f60208284031215613c29575f5ffd5b8151613a37816137e0565b600181811c90821680613c4857607f821691505b602082108103613c6657634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115610c4857805f5260205f20601f840160051c81016020851015613c915750805b601f840160051c820191505b81811015613cb0575f8155600101613c9d565b5050505050565b815167ffffffffffffffff811115613cd157613cd161388c565b613ce581613cdf8454613c34565b84613c6c565b6020601f821160018114613d17575f8315613d005750848201515b5f19600385901b1c1916600184901b178455613cb0565b5f84815260208120601f198516915b82811015613d465787850151825560209485019460019092019101613d26565b5084821015613d6357868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f604082016001600160a01b0385168352604060208401528084518083526060850191506020860192505f5b81811015613dc057835161ffff16835260209384019390920191600101613d9e565b50909695505050505050565b5f60208284031215613ddc575f5ffd5b815167ffffffffffffffff811115613df2575f5ffd5b8201601f81018413613e02575f5ffd5b805167ffffffffffffffff811115613e1c57613e1c61388c565b8060051b613e2c602082016138a0565b91825260208184018101929081019087841115613e47575f5ffd5b6020850194505b83851015613e755784519250613e6383613951565b82825260209485019490910190613e4e565b979650505050505050565b5f60208284031215613e90575f5ffd5b8151613a3781613951565b634e487b7160e01b5f52603260045260245ffd5b604081525f613ec1604083018561378c565b8281036020840152613ed3818561378c565b95945050505050565b805169ffffffffffffffffffff811681146123ab575f5ffd5b5f5f5f5f5f60a08688031215613f09575f5ffd5b613f1286613edc565b60208701516040880151606089015192975090955093509150613f3760808701613edc565b90509295509295909350565b5f60208284031215613f53575f5ffd5b5051919050565b5f613f67613905846138d1565b9050828152838383011115613f7a575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112613f9f575f5ffd5b6107fe83835160208501613f5a565b5f60208284031215613fbe575f5ffd5b815167ffffffffffffffff811115613fd4575f5ffd5b6117c484828501613f90565b5f60208284031215613ff0575f5ffd5b815167ffffffffffffffff811115614006575f5ffd5b8201601f81018413614016575f5ffd5b6117c484825160208401613f5a565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156108015761080161403b565b808201808211156108015761080161403b565b5f5f835461408281613c34565b60018216801561409957600181146140ae576140db565b60ff19831686528115158202860193506140db565b865f5260205f205f5b838110156140d3578154888201526001909101906020016140b7565b505081860193505b509195945050505050565b5f5f604083850312156140f7575f5ffd5b8251614102816137cc565b602084015190925067ffffffffffffffff81111561411e575f5ffd5b613a9485828601613f90565b6001600160a01b0385168152836020820152608060408201525f614151608083018561378c565b905082606083015295945050505050565b6001600160a01b0383168152604060208201525f6117c4604083018461378c565b5f600182016141945761419461403b565b506001019056fe1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a700112dd7b7d700a9bfd03edf4d4ce6f92b1f5f1a2fd81fde871f4db11384aa0b00360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcfedd7b171e5aaf71411eb61c81513b977191128c387240284b4edb396fcbdb002c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c8244001fa5656f3245be71aa51744436d19e5d46b909e499930c5c32c93901cab5290067df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838500a264697066735822122035e0410d4d866dbce71da568bdb6a948e20748cc7ea05eb3930bbfd8a939035964736f6c634300081e0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"prague","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":300},"remappings":[":@chainlink-contracts-1.3.0/=dependencies/@chainlink-contracts-1.3.0/",":@gnosis-pm-safe-contracts-1.3.0/=dependencies/@gnosis-pm-safe-contracts-1.3.0/",":forge-std-1.9.4/=dependencies/forge-std-1.9.4/src/",":forge-std/=dependencies/forge-std-1.9.4/src/",":safe-global-safe-smart-account-1.4.1-3/=dependencies/safe-global-safe-smart-account-1.4.1-3/",":solmate-6.8.0/=dependencies/solmate-6.8.0/"]},"optimization_runs":300,"sourcify_repo_url":null,"decoded_constructor_args":null,"compiler_version":"0.8.30+commit.73712a01","is_verified_via_verifier_alliance":true,"verified_at":"2026-06-10T15:16:18.106067Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60a0604052306080523480156012575f5ffd5b506080516142b16100395f395f8181611fdb0152818161200401526123d701526142b15ff3fe608060405234801561000f575f5ffd5b5060043610610325575f3560e01c806364dad32f116101a85780639fc1d0e7116100f3578063c9c16fbd1161009e578063dd62ed3e11610079578063dd62ed3e1461066c578063ef3e8f221461067f578063f2e23d2214610692578063f8fa842b1461069a575f5ffd5b8063c9c16fbd1461063e578063d4a1911614610651578063d505accf14610659575f5ffd5b8063b187bd26116100ce578063b187bd2614610619578063bf4dc4b614610621578063c1491c5814610628575f5ffd5b80639fc1d0e7146105eb578063a9059cbb146105fe578063aaf10f4214610611575f5ffd5b80638456cb591161015357806398d2082f1161012e57806398d2082f1461059857806398d5fdca146105bb5780639dc29fac146105d8575f5ffd5b80638456cb591461057557806395d89b411461057d57806398cd615314610585575f5ffd5b80637ab8bf5a116101835780637ab8bf5a146105475780637e8962141461055a5780637ecebe0014610562575f5ffd5b806364dad32f1461050e5780636d70f7ae1461052157806370a0823114610534575f5ffd5b80633f4ba83a116102735780634f1ef2861161021e5780635845394b116101f95780635845394b146104aa5780635965959e146104d55780635ca13f04146104e85780635d3590d5146104fb575f5ffd5b80634f1ef2861461048757806352d1902d1461049a57806355f29166146104a2575f5ffd5b8063426796831161024e578063426796831461044e578063440fde4e1461046157806346fbf68e14610474575f5ffd5b80633f4ba83a1461041e57806340c10f1914610426578063422f8c0a14610439575f5ffd5b80632d524393116102d357806334cdcf26116102ae57806334cdcf26146103fb5780633644e5151461040e578063392e53cd14610416575f5ffd5b80632d524393146103bb578063313ce567146103ce57806333999fa6146103e8575f5ffd5b806318160ddd1161030357806318160ddd1461037f57806323b872dd14610395578063257e224c146103a8575f5ffd5b806306fdde031461032957806307e2a26014610347578063095ea7b31461035c575b5f5ffd5b6103316106a2565b60405161033e91906137ba565b60405180910390f35b61035a6103553660046137ed565b6106b1565b005b61036f61036a366004613824565b6107ad565b604051901515815260200161033e565b610387610807565b60405190815260200161033e565b61036f6103a336600461384e565b610830565b61035a6103b636600461395f565b6109b0565b61036f6103c9366004613a1c565b610a33565b6103d6610ad3565b60405160ff909116815260200161033e565b61035a6103f6366004613a3e565b610aff565b61036f610409366004613a1c565b610b0d565b610387610b2b565b61036f610b34565b61035a610b4a565b61035a610434366004613824565b610b69565b610441610c4d565b60405161033e9190613a9e565b61036f61045c366004613a1c565b610dc0565b61035a61046f366004613a1c565b610dde565b61036f610482366004613a1c565b610e7e565b61035a610495366004613a3e565b610e9c565b610387610eae565b61035a610ebf565b6001546104bd906001600160a01b031681565b6040516001600160a01b03909116815260200161033e565b61035a6104e33660046137ed565b610ef3565b61035a6104f63660046137ed565b610fe3565b61035a61050936600461384e565b6110d3565b61036f61051c366004613a1c565b611123565b61036f61052f366004613a1c565b611141565b610387610542366004613a1c565b61115f565b61036f610555366004613a1c565b61119b565b61035a6111b9565b610387610570366004613a1c565b6111ed565b61035a611229565b610331611246565b61035a610593366004613ae3565b611250565b6105ab6105a6366004613b15565b611399565b60405161033e9493929190613b2c565b6105c36113b6565b6040805192835260208301919091520161033e565b61035a6105e6366004613824565b6114d0565b61035a6105f936600461384e565b6115af565b61036f61060c366004613824565b6116e3565b6104bd6117cc565b61036f6117e2565b600161036f565b6106306117fb565b60405161033e929190613b60565b61035a61064c3660046137ed565b61192f565b610331611a1e565b61035a610667366004613b81565b611aa9565b61038761067a366004613bed565b611b97565b61035a61068d366004613a1c565b611be2565b6104bd611c03565b610331611c22565b60606106ac611cc5565b905090565b6106c6335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156106f65760405163ab35696f60e01b815260040160405180910390fd5b6106fe611c03565b604051636bcd157760e11b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063d79a2aee906064015f604051808303815f87803b15801561074e575f5ffd5b505af1158015610760573d5f5f3e3d5ffd5b50505050816001600160a01b03167fd4145d5d40015b9d77048466bbe3ff2411630f7b70f80f9d79c273b6311aba74826040516107a1911515815260200190565b60405180910390a25050565b5f6107c3335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156107f35760405163ab35696f60e01b815260040160405180910390fd5b6107fe338484611e69565b90505b92915050565b5f6106ac7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385035490565b5f610846335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0385166004820152849030906364dad32f90602401602060405180830381865afa15801561088a573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ae9190613c19565b6108db576040516326865f9b60e21b81526001600160a01b03821660048201526024015b60405180910390fd5b6040516364dad32f60e01b81526001600160a01b0385166004820152849030906364dad32f90602401602060405180830381865afa15801561091f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109439190613c19565b61096b576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff161561099b5760405163ab35696f60e01b815260040160405180910390fd5b6109a6868686611f3c565b9695505050505050565b6109b8611fd0565b5f5160206141bc5f395f51905f5254156109e55760405163f92ee8a960e01b815260040160405180910390fd5b6109ed61206b565b6109f88686866120a6565b610a0182612122565b610a0a81612148565b5f8054610a1690613c34565b90505f03610a2b575f610a298482613cb7565b505b505050505050565b5f610a3c611c03565b6001600160a01b031663970f8482835f5b604051908082528060200260200182016040528015610a76578160200160208202803683370190505b506040518363ffffffff1660e01b8152600401610a94929190613d72565b602060405180830381865afa158015610aaf573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108019190613c19565b5f6106ac7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385025460ff1690565b610b098282612188565b5050565b5f610b16611c03565b6001600160a01b031663f5fe5787835f610a4d565b5f6106ac6121dd565b5f6106ac5f5160206141bc5f395f51905f525490565b610b5f335f356001600160e01b031916611d66565b610b6761222c565b565b610b7e335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0383166004820152829030906364dad32f90602401602060405180830381865afa158015610bc2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610be69190613c19565b610c0e576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff1615610c3e5760405163ab35696f60e01b815260040160405180910390fd5b610c48838361229c565b505050565b6001546060906001600160a01b0316610c7b57604051631f93601760e01b81525f60048201526024016108d2565b600154610c90906001600160a01b0316612339565b15610d0b5760015f9054906101000a90046001600160a01b03166001600160a01b0316639d91348d6040518163ffffffff1660e01b81526004015f60405180830381865afa158015610ce4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106ac9190810190613dcc565b6040805160018082528183019092525f916020808301908036833750506001546040805163313ce56760e01b815290519394506001600160a01b039091169263313ce567925060048083019260209291908290030181865afa158015610d73573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d979190613e80565b815f81518110610da957610da9613e9b565b60ff90921660209283029190910190910152919050565b5f610dc9611c03565b6001600160a01b031663ffb2f26f835f610a4d565b610df3335f356001600160e01b031916611d66565b6001546001600160a01b039081169082168103610e2e57604051631eeb14f160e01b81526001600160a01b03831660048201526024016108d2565b600180546001600160a01b0319166001600160a01b0384811691821790925560405190918316907fd76fb624f0e2e090c9f82772a08d122c79250c90c7a896b1ed0de8bbe3e9e2e4905f90a35050565b5f610e87611c03565b6001600160a01b0316636f06fa43835f610a4d565b610ea4611fd0565b610b0982826123b0565b5f610eb76123cc565b6106ac612415565b5f51602061421c5f395f51905f5254610eeb57604051630604a9ff60e01b815260040160405180910390fd5b610b67612430565b610f08335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff1615610f385760405163ab35696f60e01b815260040160405180910390fd5b610f40611c03565b604051632b73cd6360e21b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063adcf358c906064015f604051808303815f87803b158015610f90575f5ffd5b505af1158015610fa2573d5f5f3e3d5ffd5b50505050816001600160a01b03167fc71e52f779c12ade7cbf75a51deb27377b5addd6a3945e0b356bff858ffad7fb826040516107a1911515815260200190565b610ff8335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156110285760405163ab35696f60e01b815260040160405180910390fd5b611030611c03565b60405163361fa22b60e01b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063361fa22b906064015f604051808303815f87803b158015611080575f5ffd5b505af1158015611092573d5f5f3e3d5ffd5b50505050816001600160a01b03167f6b410344a541a2ad2ffec50ea1cafabe58c50db82f72ae4f46a4bd2419155b15826040516107a1911515815260200190565b6110e8335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156111185760405163ab35696f60e01b815260040160405180910390fd5b610c4883838361247b565b5f61112c611c03565b6001600160a01b031663f2563ef3835f610a4d565b5f61114a611c03565b6001600160a01b031663394340e8835f610a4d565b6001600160a01b0381165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385046020526040812054610801565b5f6111a4611c03565b6001600160a01b03166378143d56835f610a4d565b5f51602061421c5f395f51905f52546111e557604051630604a9ff60e01b815260040160405180910390fd5b610b67612730565b6001600160a01b0381165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385086020526040812054610801565b61123e335f356001600160e01b031916611d66565b610b67612771565b60606106ac6127e5565b611265335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156112955760405163ab35696f60e01b815260040160405180910390fd5b5f5f80546112a290613c34565b80601f01602080910402602001604051908101604052809291908181526020018280546112ce90613c34565b80156113195780601f106112f057610100808354040283529160200191611319565b820191905f5260205f20905b8154815290600101906020018083116112fc57829003601f168201915b5050505050905081805190602001208180519060200120036113505781604051638651f2a560e01b81526004016108d291906137ba565b5f61135b8382613cb7565b507ffd07e2c2d6dc82f4d6b1b46f25e49eb888aba92d238fb40945856412cce2f2dd818360405161138d929190613eaf565b60405180910390a15050565b5f60605f5f6113a785612823565b93509350935093509193509193565b6001545f9081906001600160a01b031615806113e257506001546113e2906001600160a01b0316612339565b1561140f57600154604051631f93601760e01b81526001600160a01b0390911660048201526024016108d2565b60015f9054906101000a90046001600160a01b03166001600160a01b031663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561145f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114839190613ef5565b5091945090925050505f8190036114ad57604051638ad52bdd60e01b815260040160405180910390fd5b5f82136114cc5760405162bfc92160e01b815260040160405180910390fd5b9091565b6114e5335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0383166004820152829030906364dad32f90602401602060405180830381865afa158015611529573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061154d9190613c19565b611575576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff16156115a55760405163ab35696f60e01b815260040160405180910390fd5b610c48838361294f565b6040516364dad32f60e01b81526001600160a01b0383166004820152829030906364dad32f90602401602060405180830381865afa1580156115f3573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116179190613c19565b61163f576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b611654335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156116845760405163ab35696f60e01b815260040160405180910390fd5b61168f8484846129f1565b50826001600160a01b0316846001600160a01b03167f7b3ce50c216d2ccf9919c6b9f1bfb33f0350a33010f188750b4af38e00448138846040516116d591815260200190565b60405180910390a350505050565b5f6116f9335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0384166004820152839030906364dad32f90602401602060405180830381865afa15801561173d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117619190613c19565b611789576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff16156117b95760405163ab35696f60e01b815260040160405180910390fd5b6117c43385856129f1565b949350505050565b5f6106ac5f5160206141dc5f395f51905f525490565b5f6106ac5f5160206141fc5f395f51905f525460ff1690565b6001546060905f906001600160a01b0316158061182a5750600154611828906001600160a01b0316612339565b155b1561185757600154604051631f93601760e01b81526001600160a01b0390911660048201526024016108d2565b600154604080516328f5843360e21b815290516001600160a01b0390921691829163a3d610cc9160048083019260209291908290030181865afa1580156118a0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118c49190613f43565b9150806001600160a01b0316639198274f6040518163ffffffff1660e01b81526004015f60405180830381865afa158015611901573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526119289190810190613fae565b9250509091565b611944335f356001600160e01b031916611d66565b5f5160206141fc5f395f51905f525460ff16156119745760405163ab35696f60e01b815260040160405180910390fd5b61197c611c03565b604051624ff82360e21b81525f60048201526001600160a01b0384811660248301528315156044830152919091169063013fe08c906064015f604051808303815f87803b1580156119cb575f5ffd5b505af11580156119dd573d5f5f3e3d5ffd5b50505050816001600160a01b03167f5e20cf47b2259b331d4b7c60c19f771fc77bd7b207cb6438d0d217ea67755b57826040516107a1911515815260200190565b5f8054611a2a90613c34565b80601f0160208091040260200160405190810160405280929190818152602001828054611a5690613c34565b8015611aa15780601f10611a7857610100808354040283529160200191611aa1565b820191905f5260205f20905b815481529060010190602001808311611a8457829003601f168201915b505050505081565b611abe335f356001600160e01b031916611d66565b6040516364dad32f60e01b81526001600160a01b0388166004820152879030906364dad32f90602401602060405180830381865afa158015611b02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611b269190613c19565b611b4e576040516326865f9b60e21b81526001600160a01b03821660048201526024016108d2565b5f5160206141fc5f395f51905f525460ff1615611b7e5760405163ab35696f60e01b815260040160405180910390fd5b611b8d88888888888888612ade565b5050505050505050565b6001600160a01b038083165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838505602090815260408083209385168352929052908120546107fe565b611bf7335f356001600160e01b031916611d66565b611c0081612d08565b50565b5f6106ac5f51602061423c5f395f51905f52546001600160a01b031690565b6001546060906001600160a01b0316611c5057604051631f93601760e01b81525f60048201526024016108d2565b60015460408051633942720b60e11b815290516001600160a01b03909216918291637284e416916004808301925f9291908290030181865afa158015611c98573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cbf9190810190613fe0565b91505090565b5f51602061425c5f395f51905f528054606091908190611ce490613c34565b80601f0160208091040260200160405190810160405280929190818152602001828054611d1090613c34565b8015611d5b5780601f10611d3257610100808354040283529160200191611d5b565b820191905f5260205f20905b815481529060010190602001808311611d3e57829003601f168201915b505050505091505090565b5f5f611d865f51602061423c5f395f51905f52546001600160a01b031690565b6040516001600160a01b0386811660248301526001600160e01b031986166044830152919091169060640160408051601f198184030181529181526020820180516001600160e01b0316630435f69f60e51b17905251611de69190614025565b5f60405180830381855afa9150503d805f8114611e1e576040519150601f19603f3d011682016040523d82523d5f602084013e611e23565b606091505b5091509150811580611e46575080806020019051810190611e449190613c19565b155b15611e63576040516282b42960e81b815260040160405180910390fd5b50505050565b5f6001600160a01b0384161580611e8757506001600160a01b038316155b15611ea55760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b038481165f8181527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838505602090815260408083209488168084529482529182902086905590518581525f51602061425c5f395f51905f529392917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3506001949350505050565b6001600160a01b0383165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838505602090815260408083203384529091528120545f51602061425c5f395f51905f52905f198114611fc557611f9f848261404f565b6001600160a01b0387165f90815260058401602090815260408083203384529091529020555b6109a68686866129f1565b306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016148061204d57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166120415f5160206141dc5f395f51905f525490565b6001600160a01b031614155b15610b675760405163703e46dd60e11b815260040160405180910390fd5b60015f5160206141bc5f395f51905f52556040517f5daa87a0e9463431830481fd4b6e3403442dfb9a12b9c07597e9f61d50b633c8905f90a1565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838506545f51602061425c5f395f51905f52905f03611e6357806120e88582613cb7565b50600181016120f78482613cb7565b5060028101805460ff191660ff8416179055466006820155612117612d36565b600782015550505050565b5f51602061423c5f395f51905f5280546001600160a01b0316610b0957610b0982612d08565b7f2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c824401545f51602061421c5f395f51905f52905f03610b0957610b0982612de0565b604051309033907f16f2354671bbabcb07367cc01a78931a00a812ee080430be4e8f1a76ab58212b905f90a33330146121d35760405162e6155960e41b815260040160405180910390fd5b610b098282612e24565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838506545f905f51602061425c5f395f51905f529046146122235761221e612d36565b611cbf565b60070154919050565b5f5160206141fc5f395f51905f525460ff1661225b5760405163dcdde9dd60e01b815260040160405180910390fd5b5f5160206141fc5f395f51905f52805460ff191681556040517fa45f47fdea8a1efdd9029a5691c7f759c32b7c698632b563573e155625d16933905f90a150565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d83850380545f51602061425c5f395f51905f529183915f906122dd908490614062565b90915550506001600160a01b0383165f8181526004830160209081526040808320805487019055518581527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a3505050565b5f816001600160a01b0316639d91348d6040518163ffffffff1660e01b81526004015f60405180830381865afa92505050801561239757506040513d5f823e601f3d908101601f191682016040526123949190810190613dcc565b60015b6123a257505f919050565b50600192915050565b919050565b6123b8611fd0565b6123c28282612e42565b610b098282612e97565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610b675760405163703e46dd60e11b815260040160405180910390fd5b5f61241e6123cc565b505f5160206141dc5f395f51905f5290565b5f51602061421c5f395f51905f5280545f61244a82611399565b50509150505f5f61245a83612ea1565b915091506124688282612e42565b61247184612ef4565b50505f9092555050565b5f806001600160a01b038516612501576040516001600160a01b0385169084905f81818185875af1925050503d805f81146124d1576040519150601f19603f3d011682016040523d82523d5f602084013e6124d6565b606091505b505080925050816124fa576040516312171d8360e31b815260040160405180910390fd5b50816126d3565b6040516370a0823160e01b81526001600160a01b03858116600483015286915f918316906370a0823190602401602060405180830381865afa158015612549573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061256d9190613f43565b604080516001600160a01b03898116602483015260448083018a905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b1790529151929350606092918a16916125ca9190614025565b5f604051808303815f865af19150503d805f8114612603576040519150601f19603f3d011682016040523d82523d5f602084013e612608565b606091505b50909550905084158061263757505f81511180156126375750808060200190518101906126359190613c19565b155b15612655576040516312171d8360e31b815260040160405180910390fd5b6040516370a0823160e01b81526001600160a01b0388811660048301525f91908516906370a0823190602401602060405180830381865afa15801561269c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126c09190613f43565b90506126cc838261404f565b9450505050505b836001600160a01b0316856001600160a01b03167f7a43eea7e0e6937c4baa97b10dabb89519feb249fe9ddcb442415b029148520d8584604051612721929190918252602082015260400190565b60405180910390a35050505050565b5f51602061421c5f395f51905f5280545f61274a82611399565b50509150505f5f61275a83612ea1565b915091506127688282612e42565b61247184612faf565b5f5160206141fc5f395f51905f525460ff16156127a15760405163ab35696f60e01b815260040160405180910390fd5b5f5160206141fc5f395f51905f52805460ff191660011781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e752905f90a150565b7f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d83850180546060915f51602061425c5f395f51905f5291611ce490613c34565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70260209081526040808320815160808101835281546001600160a01b03168152600182015493810193909352600281018054606094869485945f51602061419c5f395f51905f52948694919284019161289f90613c34565b80601f01602080910402602001604051908101604052809291908181526020018280546128cb90613c34565b80156129165780601f106128ed57610100808354040283529160200191612916565b820191905f5260205f20905b8154815290600101906020018083116128f957829003601f168201915b505050505081526020016003820154815250509050805f0151816040015182602001518360600151955095509550955050509193509193565b6001600160a01b0382165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385046020526040812080545f51602061425c5f395f51905f52928492916129a490849061404f565b909155505060038101805483900390556040518281525f906001600160a01b038516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200161232c565b5f6001600160a01b0384161580612a0f57506001600160a01b038316155b15612a2d5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0384165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d8385046020526040812080545f51602061425c5f395f51905f5292859291612a8290849061404f565b90915550506001600160a01b038085165f818152600484016020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611f299087815260200190565b42841015612aff576040516305787bdf60e01b815260040160405180910390fd5b6001600160a01b0387165f9081527f67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d83850860205260408120805460018082019092555f51602061425c5f395f51905f52929091612b586121dd565b604080517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c960208201526001600160a01b03808f1692820192909252908c166060820152608081018b905260a0810185905260c081018a905260e00160405160208183030381529060405280519060200120604051602001612bf192919061190160f01b81526002810192909252602282015260420190565b60408051601f1981840301815282825280516020918201205f84529083018083525260ff891690820152606081018790526080810186905260a0016020604051602081039080840390855afa158015612c4c573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b0381161580612c815750896001600160a01b0316816001600160a01b031614155b15612c9f57604051632057875960e21b815260040160405180910390fd5b50506001600160a01b038881165f8181526005840160209081526040808320948c16808452948252918290208a905590518981527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a35050505050505050565b5f51602061423c5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b6040515f905f51602061425c5f395f51905f52907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f90612d77908390614075565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c0016040516020818303038152906040528051906020012091505090565b805f03612e00576040516327df2edd60e11b815260040160405180910390fd5b7f2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c82440155565b612e2e8282613202565b612e38828261321e565b610b098282613273565b612e4a611c03565b6001600160a01b0316336001600160a01b031614610b095733612e6b611c03565b60405163fe6cd27560e01b81526001600160a01b039283166004820152911660248201526044016108d2565b610b0982826132a6565b5f6060606483511015612ec75760405163fc69850b60e01b815260040160405180910390fd5b8251612ed7908490600490613363565b806020019051810190612eea91906140e6565b9094909350915050565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70160205260409020545f51602061419c5f395f51905f529015610b09575f8281526001808301602090815260408084208490556002808601909252832080546001600160a01b0319168155918201839055909190612f7890830182613742565b505f60039190910181905560405183917f134fdd648feeaf30251f0157f9624ef8608ff9a042aad6d13e73f35d21d3f88d91a25050565b612fb8816133e2565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70260209081526040808320815160808101835281546001600160a01b031681526001820154938101939093526002810180545f51602061419c5f395f51905f529594938401919061302c90613c34565b80601f016020809104026020016040519081016040528092919081815260200182805461305890613c34565b80156130a35780601f1061307a576101008083540402835291602001916130a3565b820191905f5260205f20905b81548152906001019060200180831161308657829003601f168201915b50505091835250506003919091015460209182015281519082015160408301519293509091478211156130f15760405162fae2d560e21b8152600481018390524760248201526044016108d2565b5f8681526001808701602090815260408084208490556002808a01909252832080546001600160a01b031916815591820183905590919061313490830182613742565b600382015f905550505f836001600160a01b031683836040516131579190614025565b5f6040518083038185875af1925050503d805f8114613191576040519150601f19603f3d011682016040523d82523d5f602084013e613196565b606091505b50509050806131bb5760405163165a1d4160e01b8152600481018890526024016108d2565b867fbc76564aec85e3f50672da2d1ddca0390851fecefe61cd19d89dea91a8267829858585426040516131f1949392919061412a565b60405180910390a250505050505050565b805115610b0957610b095f5f5160206141bc5f395f51905f5255565b6132278261345f565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561326b57610c488282613479565b610b09613505565b5f81511180156132885750613286610b34565b155b15610b095760405163b3a31bfd60e01b815260040160405180910390fd5b5f51602061421c5f395f51905f5254156132d35760405163e741fd4560e01b815260040160405180910390fd5b7f2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c824401545f51602061421c5f395f51905f52905f906133109042614062565b90505f61335a30868660405160240161332a929190614162565b60408051601f198184030181529190526020810180516001600160e01b03166319cccfd360e11b17905284613524565b90925550505050565b606061337082855161363e565b915061337c838361363e565b9250613388838361404f565b67ffffffffffffffff8111156133a0576133a061388c565b6040519080825280601f01601f1916602001820160405280156133ca576020820181803683370190505b509050828203836020860101602083015e9392505050565b5f8181527f1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a70160205260408120545f51602061419c5f395f51905f529181900361343e57604051634b9aaa0960e11b815260040160405180910390fd5b80421015610c4857604051630f0b32ff60e11b815260040160405180910390fd5b61346881613653565b5f5160206141dc5f395f51905f5255565b60605f5f846001600160a01b0316846040516134959190614025565b5f60405180830381855af49150503d805f81146134cd576040519150601f19603f3d011682016040523d82523d5f602084013e6134d2565b606091505b5091509150816117c4578051156134ec5780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b3415610b675760405163b398979f60e01b815260040160405180910390fd5b5f8142106135455760405163b7d0949760e01b815260040160405180910390fd5b5f51602061419c5f395f51905f5280543490825f61356283614183565b909155505081545f81815260018085016020908152604080842089905580516080810182526001600160a01b038c811682528184018881528284018d8152606084018d90528888526002808c0190965293909620825181546001600160a01b0319169216919091178155945193850193909355519396509092908201906135e99082613cb7565b5060608201518160030155905050827f8d6fedd41517ab865c3658696c50923b3493c8a93ffd016d919a599f03c7531b8783888860405161362d949392919061412a565b60405180910390a250509392505050565b5f81831061364c57816107fe565b5090919050565b806001600160a01b03163b5f0361368857604051634c9c8ce360e01b81526001600160a01b03821660048201526024016108d2565b806001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156136e2575060408051601f3d908101601f191682019092526136df91810190613f43565b60015b61370a57604051634c9c8ce360e01b81526001600160a01b03821660048201526024016108d2565b5f5160206141dc5f395f51905f528114610b0957604051634c9c8ce360e01b81526001600160a01b03831660048201526024016108d2565b50805461374e90613c34565b5f825580601f1061375d575050565b601f0160209004905f5260205f2090810190611c0091905b80821115613788575f8155600101613775565b5090565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f6107fe602083018461378c565b6001600160a01b0381168114611c00575f5ffd5b8015158114611c00575f5ffd5b5f5f604083850312156137fe575f5ffd5b8235613809816137cc565b91506020830135613819816137e0565b809150509250929050565b5f5f60408385031215613835575f5ffd5b8235613840816137cc565b946020939093013593505050565b5f5f5f60608486031215613860575f5ffd5b833561386b816137cc565b9250602084013561387b816137cc565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156138c9576138c961388c565b604052919050565b5f67ffffffffffffffff8211156138ea576138ea61388c565b50601f01601f191660200190565b5f61390a613905846138d1565b6138a0565b905082815283838301111561391d575f5ffd5b828260208301375f602084830101529392505050565b5f82601f830112613942575f5ffd5b6107fe838335602085016138f8565b60ff81168114611c00575f5ffd5b5f5f5f5f5f5f60c08789031215613974575f5ffd5b863567ffffffffffffffff81111561398a575f5ffd5b61399689828a01613933565b965050602087013567ffffffffffffffff8111156139b2575f5ffd5b6139be89828a01613933565b95505060408701356139cf81613951565b9350606087013567ffffffffffffffff8111156139ea575f5ffd5b6139f689828a01613933565b9350506080870135613a07816137cc565b9598949750929591949360a090920135925050565b5f60208284031215613a2c575f5ffd5b8135613a37816137cc565b9392505050565b5f5f60408385031215613a4f575f5ffd5b8235613a5a816137cc565b9150602083013567ffffffffffffffff811115613a75575f5ffd5b8301601f81018513613a85575f5ffd5b613a94858235602084016138f8565b9150509250929050565b602080825282518282018190525f918401906040840190835b81811015613ad857835160ff16835260209384019390920191600101613ab7565b509095945050505050565b5f60208284031215613af3575f5ffd5b813567ffffffffffffffff811115613b09575f5ffd5b6117c484828501613933565b5f60208284031215613b25575f5ffd5b5035919050565b6001600160a01b0385168152608060208201525f613b4d608083018661378c565b6040830194909452506060015292915050565b604081525f613b72604083018561378c565b90508260208301529392505050565b5f5f5f5f5f5f5f60e0888a031215613b97575f5ffd5b8735613ba2816137cc565b96506020880135613bb2816137cc565b955060408801359450606088013593506080880135613bd081613951565b9699959850939692959460a0840135945060c09093013592915050565b5f5f60408385031215613bfe575f5ffd5b8235613c09816137cc565b91506020830135613819816137cc565b5f60208284031215613c29575f5ffd5b8151613a37816137e0565b600181811c90821680613c4857607f821691505b602082108103613c6657634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115610c4857805f5260205f20601f840160051c81016020851015613c915750805b601f840160051c820191505b81811015613cb0575f8155600101613c9d565b5050505050565b815167ffffffffffffffff811115613cd157613cd161388c565b613ce581613cdf8454613c34565b84613c6c565b6020601f821160018114613d17575f8315613d005750848201515b5f19600385901b1c1916600184901b178455613cb0565b5f84815260208120601f198516915b82811015613d465787850151825560209485019460019092019101613d26565b5084821015613d6357868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b5f604082016001600160a01b0385168352604060208401528084518083526060850191506020860192505f5b81811015613dc057835161ffff16835260209384019390920191600101613d9e565b50909695505050505050565b5f60208284031215613ddc575f5ffd5b815167ffffffffffffffff811115613df2575f5ffd5b8201601f81018413613e02575f5ffd5b805167ffffffffffffffff811115613e1c57613e1c61388c565b8060051b613e2c602082016138a0565b91825260208184018101929081019087841115613e47575f5ffd5b6020850194505b83851015613e755784519250613e6383613951565b82825260209485019490910190613e4e565b979650505050505050565b5f60208284031215613e90575f5ffd5b8151613a3781613951565b634e487b7160e01b5f52603260045260245ffd5b604081525f613ec1604083018561378c565b8281036020840152613ed3818561378c565b95945050505050565b805169ffffffffffffffffffff811681146123ab575f5ffd5b5f5f5f5f5f60a08688031215613f09575f5ffd5b613f1286613edc565b60208701516040880151606089015192975090955093509150613f3760808701613edc565b90509295509295909350565b5f60208284031215613f53575f5ffd5b5051919050565b5f613f67613905846138d1565b9050828152838383011115613f7a575f5ffd5b8282602083015e5f602084830101529392505050565b5f82601f830112613f9f575f5ffd5b6107fe83835160208501613f5a565b5f60208284031215613fbe575f5ffd5b815167ffffffffffffffff811115613fd4575f5ffd5b6117c484828501613f90565b5f60208284031215613ff0575f5ffd5b815167ffffffffffffffff811115614006575f5ffd5b8201601f81018413614016575f5ffd5b6117c484825160208401613f5a565b5f82518060208501845e5f920191825250919050565b634e487b7160e01b5f52601160045260245ffd5b818103818111156108015761080161403b565b808201808211156108015761080161403b565b5f5f835461408281613c34565b60018216801561409957600181146140ae576140db565b60ff19831686528115158202860193506140db565b865f5260205f205f5b838110156140d3578154888201526001909101906020016140b7565b505081860193505b509195945050505050565b5f5f604083850312156140f7575f5ffd5b8251614102816137cc565b602084015190925067ffffffffffffffff81111561411e575f5ffd5b613a9485828601613f90565b6001600160a01b0385168152836020820152608060408201525f614151608083018561378c565b905082606083015295945050505050565b6001600160a01b0383168152604060208201525f6117c4604083018461378c565b5f600182016141945761419461403b565b506001019056fe1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a700112dd7b7d700a9bfd03edf4d4ce6f92b1f5f1a2fd81fde871f4db11384aa0b00360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbcfedd7b171e5aaf71411eb61c81513b977191128c387240284b4edb396fcbdb002c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c8244001fa5656f3245be71aa51744436d19e5d46b909e499930c5c32c93901cab5290067df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838500a264697066735822122035e0410d4d866dbce71da568bdb6a948e20748cc7ea05eb3930bbfd8a939035964736f6c634300081e0033","name":"SygToken","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"prague","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"libs/ERC20/ERC20View.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20Core} from \"libs/ERC20/ERC20Core.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title ERC20View\n * @author SYGNUM AG - Blockchain team 3301\n * @notice View-only ERC20 implementation that exposes only view functions\n * @dev This contract provides read-only access to ERC20 token state without\n *      state-changing functions. It's designed for contracts that need to query\n *      token information but should not modify state directly.\n */\nabstract contract ERC20View is ERC20Core {\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL/PUBLIC VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns the name of the token\n     * @return The name of the token\n     */\n    function name() public view returns (string memory) {\n        return _name();\n    }\n\n    /**\n     * @notice Returns the symbol of the token\n     * @return The symbol of the token\n     */\n    function symbol() public view returns (string memory) {\n        return _symbol();\n    }\n\n    /**\n     * @notice Returns the number of decimals used to get its user representation\n     * @return The number of decimals\n     */\n    function decimals() public view returns (uint8) {\n        return _decimals();\n    }\n\n    /**\n     * @notice Returns the amount of tokens in existence\n     * @return The total supply of tokens\n     */\n    function totalSupply() public view returns (uint256) {\n        return _totalSupply();\n    }\n\n    /**\n     * @notice Returns the amount of tokens owned by account\n     * @param _account The address to query the balance of\n     * @return The balance of the specified address\n     */\n    function balanceOf(address _account) public view returns (uint256) {\n        return _balanceOf(_account);\n    }\n\n    /**\n     * @notice Returns the remaining number of tokens that spender will be allowed to spend on behalf of owner\n     * @param _owner The address of the token owner\n     * @param _spender The address of the spender\n     * @return The allowance amount\n     */\n    function allowance(address _owner, address _spender) public view returns (uint256) {\n        return _allowance(_owner, _spender);\n    }\n\n    /**\n     * @notice Returns the current nonce for owner (EIP-2612)\n     * @param _account The address to query the nonce of\n     * @return The nonce of the specified address\n     */\n    function nonces(address _account) public view returns (uint256) {\n        return _nonces(_account);\n    }\n\n    /**\n     * @notice Returns the domain separator used in the encoding of the signature for permits (EIP-2612)\n     * @return The domain separator hash\n     */\n    function DOMAIN_SEPARATOR() public view returns (bytes32) {\n        return _DOMAIN_SEPARATOR();\n    }\n}\n"},{"file_path":"libs/UUPS/UUPSTimelockUpgradeableView.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {UUPSTimelockUpgradeableCore} from './UUPSTimelockUpgradeableCore.sol';\nimport {UUPSUtils} from './UUPSUtils.sol';\nimport {IUUPSAsynchronousUpgradeable} from './interface/IUUPSAsynchronousUpgradeable.sol';\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title UUPSTimelockUpgradeableView\n * @author SYGNUM AG - Blockchain team 3301\n * @notice View-only UUPS Timelock upgrade implementation that exposes view functions\n * @dev This contract provides read-only access to UUPS Timelock upgrade state without\n *      allowing upgrade modifications. It's designed for contracts that need to query\n *      upgrade and timelock information but should not perform upgrades directly.\n *      Note: This implementation is independent of UUPSUpgradeableView due to Core\n *      layer inheritance differences (UUPSTimelockUpgradeableCore inherits from both\n *      UUPSUpgradeableCore and Timelock).\n */\nabstract contract UUPSTimelockUpgradeableView is UUPSTimelockUpgradeableCore, IUUPSAsynchronousUpgradeable {\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL/PUBLIC VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns the storage slot used by the implementation\n     * @dev Reverts if called through a proxy to prevent bricking\n     * @return The storage slot used by the implementation\n     */\n    function proxiableUUID() external view notDelegated returns (bytes32) {\n        return _proxiableUUID();\n    }\n\n    /**\n     * @notice Returns the current implementation address\n     * @dev Returns the address stored in the ERC-1967 implementation slot\n     * @return The address of the current implementation contract\n     */\n    function getImplementation() external view returns (address) {\n        return UUPSUtils.getImplementation();\n    }\n}\n"},{"file_path":"libs/external/chainlink-local/src/data-feeds/interfaces/AggregatorV3Interface.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title AggregatorV3Interface\n/// @notice Interface for accessing detailed data from an aggregator contract, including round data and metadata.\n/// @dev Provides methods to get the latest data, historical data for specific rounds, and metadata such as decimals and description.\ninterface AggregatorV3Interface {\n    /**\n     * @notice Gets the number of decimals used by the aggregator.\n     * @return uint8 - The number of decimals.\n     */\n    function decimals() external view returns (uint8);\n\n    /**\n     * @notice Gets the description of the aggregator.\n     * @return string memory - The description of the aggregator.\n     */\n    function description() external view returns (string memory);\n\n    /**\n     * @notice Gets the version of the aggregator.\n     * @return uint256 - The version of the aggregator.\n     */\n    function version() external view returns (uint256);\n\n    /**\n     * @notice Gets the round data for a specific round ID.\n     * @param _roundId - The round ID to get the data for.\n     * @return roundId - The round ID.\n     * @return answer - The answer for the round.\n     * @return startedAt - The timestamp when the round started.\n     * @return updatedAt - The timestamp when the round was updated.\n     * @return answeredInRound - The round ID in which the answer was computed.\n     * @dev This function should raise \"No data present\" if no data is available for the given round ID.\n     */\n    function getRoundData(uint80 _roundId)\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    /**\n     * @notice Gets the latest round data.\n     * @return roundId - The latest round ID.\n     * @return answer - The latest answer.\n     * @return startedAt - The timestamp when the latest round started.\n     * @return updatedAt - The timestamp when the latest round was updated.\n     * @return answeredInRound - The round ID in which the latest answer was computed.\n     * @dev This function should raise \"No data present\" if no data is available.\n     */\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n}"},{"file_path":"apps/tokenization/SygToken/contracts/ChainlinkDataFeed.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport {AggregatorV3Interface} from \"libs/external/chainlink-local/src/data-feeds/interfaces/AggregatorV3Interface.sol\";\nimport {IBundleAggregatorProxy} from\n    \"libs/external/chainlink-evm/contracts/src/v0.8/data-feeds/interfaces/IBundleAggregatorProxy.sol\";\nimport {PausableCore} from \"libs/Pausable/PausableCore.sol\";\nimport {PermissionedCore} from \"libs/Permissioned/PermissionedCore.sol\";\nimport {StorageLayout} from \"./storage/StorageLayout.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title ChainlinkDataFeed\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Contract for interacting with Chainlink price feed oracles\n * @dev Provides type-safe functions to fetch price data from AggregatorV3Interface or bundle data from\n *      IBundleAggregatorProxy. Consumers must call the correct function for the configured oracle type.\n */\nabstract contract ChainlinkDataFeed is StorageLayout, PausableCore, PermissionedCore {\n    /* ======== ERRORS ======== */\n\n    error InvalidOracle(address _oracleAddress);\n    error IncompleteRound();\n    error InvalidPrice();\n    error SameOracleAddress(address _oracleAddress);\n\n    /* ======== EVENTS ======== */\n\n    event PriceFeedOracleUpdated(address indexed previousOracle, address indexed newOracle);\n\n    /* ======== EXTERNAL/PUBLIC STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice Updates the price feed oracle address\n     * @dev Can be set to zero to disable price feed.\n     * @param _newPriceFeedOracleAddress The new oracle address (can be zero)\n     */\n    function updatePricefeedOracleAddress(address _newPriceFeedOracleAddress) external requiresAuth {\n        address _previousOracle = getPriceFeedOracleAddress;\n        if (_previousOracle == _newPriceFeedOracleAddress) {\n            revert SameOracleAddress(_newPriceFeedOracleAddress);\n        }\n        getPriceFeedOracleAddress = _newPriceFeedOracleAddress;\n        emit PriceFeedOracleUpdated(_previousOracle, _newPriceFeedOracleAddress);\n    }\n\n    /* ======== EXTERNAL/PUBLIC VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Gets the latest asset price from an AggregatorV3Interface oracle\n     * @dev Only works when the configured oracle is an AggregatorV3Interface (not a bundle feed).\n     *      Reverts with InvalidOracle if oracle is not set or is a bundle aggregator.\n     * @return _price The latest price as int256 (guaranteed positive)\n     * @return _updatedAt The timestamp of the last price update\n     */\n    function getPrice() external view returns (int256 _price, uint256 _updatedAt) {\n        if (getPriceFeedOracleAddress == address(0) || _isBundleAggregator(getPriceFeedOracleAddress)) {\n            revert InvalidOracle(getPriceFeedOracleAddress);\n        }\n\n        (, _price,, _updatedAt,) = AggregatorV3Interface(getPriceFeedOracleAddress).latestRoundData();\n\n        if (_updatedAt == 0) {\n            revert IncompleteRound();\n        }\n\n        if (_price <= 0) {\n            revert InvalidPrice();\n        }\n    }\n\n    /**\n     * @notice Gets the latest bundle data from an IBundleAggregatorProxy oracle\n     * @dev Only works when the configured oracle is an IBundleAggregatorProxy (not a V3 price feed).\n     *      Reverts with InvalidOracle if oracle is not set or is an AggregatorV3Interface.\n     *      The returned bytes are an opaque payload whose schema depends on the specific feed being queried.\n     *      The caller is responsible for decoding the payload according to that feed's documentation.\n     * @return _bundleData The raw bundle data bytes\n     * @return _updatedAt The timestamp of the last bundle update\n     */\n    function getBundleData() external view returns (bytes memory _bundleData, uint256 _updatedAt) {\n        if (getPriceFeedOracleAddress == address(0) || !_isBundleAggregator(getPriceFeedOracleAddress)) {\n            revert InvalidOracle(getPriceFeedOracleAddress);\n        }\n\n        IBundleAggregatorProxy _bundleFeed = IBundleAggregatorProxy(getPriceFeedOracleAddress);\n        _updatedAt = _bundleFeed.latestBundleTimestamp();\n        _bundleData = _bundleFeed.latestBundle();\n    }\n\n    /**\n     * @notice Gets the number of decimals for the price feed\n     * @dev Automatically detects if the oracle is an AggregatorV3Interface or IBundleAggregatorProxy\n     * @dev For AggregatorV3Interface, returns a single-element array\n     * @dev For IBundleAggregatorProxy, returns the bundleDecimals() array as-is\n     * @dev Reverts if oracle address is zero\n     * @return _decimals The decimals array\n     */\n    function getPriceFeedDecimals() external view returns (uint8[] memory) {\n        if (getPriceFeedOracleAddress == address(0)) {\n            revert InvalidOracle(address(0));\n        }\n\n        if (_isBundleAggregator(getPriceFeedOracleAddress)) {\n            return IBundleAggregatorProxy(getPriceFeedOracleAddress).bundleDecimals();\n        }\n\n        uint8[] memory _decimals = new uint8[](1);\n        _decimals[0] = AggregatorV3Interface(getPriceFeedOracleAddress).decimals();\n        return _decimals;\n    }\n\n    /**\n     * @notice Gets the description of the price feed\n     * @dev Works with both AggregatorV3Interface and IBundleAggregatorProxy (both have description())\n     * @dev Reverts if oracle address is zero\n     * @return The description string\n     */\n    function getPriceFeedDescription() external view returns (string memory) {\n        if (getPriceFeedOracleAddress == address(0)) {\n            revert InvalidOracle(address(0));\n        }\n\n        AggregatorV3Interface _priceFeed = AggregatorV3Interface(getPriceFeedOracleAddress);\n        return _priceFeed.description();\n    }\n\n    /* ======== PRIVATE VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Checks if the oracle address implements IBundleAggregatorProxy\n     * @dev Uses try/catch on bundleDecimals() to detect bundle interface\n     * @param _oracleAddress The oracle address to check\n     * @return True if the oracle implements IBundleAggregatorProxy\n     */\n    function _isBundleAggregator(address _oracleAddress) private view returns (bool) {\n        try IBundleAggregatorProxy(_oracleAddress).bundleDecimals() returns (uint8[] memory) {\n            return true;\n        } catch {\n            return false;\n        }\n    }\n}\n"},{"file_path":"libs/UUPS/UUPSUpgradeableCore.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {IERC1822Proxiable} from './interface/IERC1822.sol';\nimport {UUPSUtils} from './UUPSUtils.sol';\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title UUPSUpgradeableCore\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Core UUPS upgradeability implementation with only internal functions\n * @dev Provides upgradeability logic for UUPS proxies, including initialization and upgrade authorization.\n * Combines initialization and UUPS upgrade logic for use behind an ERC1967Proxy.\n * UUPS (Universal Upgradeable Proxy Standard) is a proxy pattern where the upgrade logic resides in the implementation contract itself,\n * rather than in the proxy. This contract provides the base functionality for UUPS upgradeability, including checks to ensure\n * that upgrades are authorized and that the implementation contract is valid.\n */\nabstract contract UUPSUpgradeableCore is IERC1822Proxiable {\n    /* ======== State Variables ======== */\n    /**\n     * @dev `__self` is an immutable state variable that stores the address of the contract instance.\n     * It is used to differentiate between direct calls to the implementation contract and calls through the proxy.\n     * This is crucial for security checks to prevent unauthorized access to upgrade functions.\n     * By storing the contract's own address, we can determine if a call is being made directly to the implementation\n     * or through the proxy, which is essential for enforcing access control and preventing unauthorized upgrades.\n     */\n    address private immutable __self = address(this);\n\n    /* ======== Modifiers ======== */\n    /**\n     * @dev Restricts function to only be called through a proxy.\n     * @notice This modifier checks that the function is being called via a delegate call through a proxy contract.\n     * It prevents direct calls to the implementation contract, ensuring that all calls go through the proxy.\n     */\n    modifier onlyProxy() {\n        _checkProxy();\n        _;\n    }\n\n    /**\n     * @dev Restricts function to only be called directly, not via delegatecall.\n     * @notice This modifier ensures that the function is called directly on the implementation contract,\n     * not through a delegate call. This is used to protect functions that should only be called by the implementation itself.\n     */\n    modifier notDelegated() {\n        _checkNotDelegated();\n        _;\n    }\n\n    /* ======== Custom Errors ======== */\n    error UUPSUnauthorizedCallContext();\n\n    /* ======== Internal View/Pure Functions ======== */\n\n    /**\n     * @notice Returns the storage slot used by the implementation.\n     * @dev Internal version for core functionality.\n     * @return bytes32 The storage slot used by the implementation.\n     */\n    function _proxiableUUID() internal view returns (bytes32) {\n        _checkNotDelegated();\n        return UUPSUtils.IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Ensures the function is called through a proxy with the correct implementation.\n     * @notice This function checks that the contract is being called via a delegate call through a proxy contract\n     * and that the implementation address matches the current contract address.\n     * It reverts with `UUPSUnauthorizedCallContext` if the conditions are not met.\n     */\n    function _checkProxy() internal view {\n        // If the address of `this` is equal to `__self`, it means the contract is being called directly, not through a proxy.\n        // Additionally, it verifies that the implementation address stored in the UUPSUtils matches the current contract address.\n        if (\n            address(this) == __self || UUPSUtils.getImplementation() != __self\n        ) {\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /**\n     * @dev Ensures the function is not called through delegatecall.\n     * @notice This function checks that the contract is being called directly and not through a delegate call.\n     * It reverts with `UUPSUnauthorizedCallContext` if the contract is being called through a delegate call.\n     */\n    function _checkNotDelegated() internal view {\n        // If the address of `this` is not equal to `__self`, it means the contract is being called through a delegate call.\n        if (address(this) != __self) {\n            revert UUPSUnauthorizedCallContext();\n        }\n    }\n\n    /* ======== Internal State-Changing Functions ======== */\n\n    /**\n     * @notice Upgrades the implementation and optionally executes a function call.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional memory to execute after the upgrade.\n     */\n    function _upgradeToAndCall(\n        address _newImplementation,\n        bytes memory _data\n    ) internal {\n        _checkProxy();\n        _authorizeUpgrade(_newImplementation, _data);\n        _triggerUpgrade(_newImplementation, _data);\n    }\n\n    /**\n     * @notice Must be overridden to include access restriction to the upgrade mechanism.\n     * validates the _newImplementation address and _data to perform any necessary checks on the input data\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional memory to execute after the upgrade.\n     */\n    function _authorizeUpgrade(address _newImplementation,bytes memory _data) internal view virtual;\n\n    /**\n     * @dev Executes the upgrade.\n     * @notice This function is responsible for performing the actual upgrade of the contract.\n     * It calls the `_upgradeToAndCallUUPS` function to switch to the new implementation.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data The _data to be passed to the new implementation contract.\n     */\n    function _triggerUpgrade(\n        address _newImplementation,\n        bytes memory _data\n    ) internal virtual {\n        _upgradeToAndCallUUPS(_newImplementation, _data);\n    }\n\n    /**\n     * @dev Performs an implementation upgrade with a security check for UUPS proxies and optional setup call.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional memory to execute after the upgrade.\n     */\n    function _upgradeToAndCallUUPS(\n        address _newImplementation,\n        bytes memory _data\n    ) internal {\n        _preUpgradeToAndCallUUPS(_newImplementation, _data);\n        UUPSUtils.upgradeToAndCall(_newImplementation, _data);\n        _postUpgradeToAndCallUUPS(_newImplementation, _data);\n    }\n\n    /**\n     * @notice Hook that is called before an upgrade is executed.\n     * @dev Can be overridden by derived contracts to implement custom logic before the upgrade is executed.\n     *      If the contract inherits from Initializable. Override this method to calls _resetInitialized().\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data The data that was passed during the upgrade.\n     */\n    function _preUpgradeToAndCallUUPS(address _newImplementation, bytes memory _data) internal virtual {}\n\n    /**\n     * @notice Hook that is called after an upgrade is executed.\n     * @dev Can be overridden by derived contracts to implement custom logic after the upgrade is executed.\n     *      For example, to check that the contract is properly initialized after the upgrade.\n     *      If the contract inherits from Initializable, this can be used to verify that isInitialized() returns true\n     *      when initialization data is required.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data The data that was passed during the upgrade.\n     */\n    function _postUpgradeToAndCallUUPS(address _newImplementation, bytes memory _data) internal virtual {}\n}\n"},{"file_path":"libs/UUPS/UUPSTimelockUpgradeableCore.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {UUPSUpgradeableCore} from './UUPSUpgradeableCore.sol';\nimport {Timelock} from 'libs/Timelock/Timelock.sol';\nimport {BytesLib} from 'libs/utils/bytes/BytesLib.sol';\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title UUPSTimelockUpgradeableCore\n * @author Sygnum\n * @notice Core implementation that combines UUPS upgradeability with Timelock functionality for secure, delayed upgrades.\n *         Contains only internal functions for use by derived contracts.\n *         Enables governance mechanisms where upgrades are executed only after a specified delay,\n *         providing a safety window for stakeholders.\n *         Inherits from both `UUPSUpgradeableCore` for upgradeability and `Timelock` for delayed execution.\n */\nabstract contract UUPSTimelockUpgradeableCore is UUPSUpgradeableCore, Timelock {\n    using BytesLib for bytes;\n\n    /* ======== Custom Errors ======== */\n    error AlreadyUpgrading();\n    error NoUpgradeScheduled();\n    error UnAuthorizedCall();\n    error InvalidDelay();\n    error InvalidUpgradeCalldata();\n\n    event Callers(address indexed caller, address indexed context);\n\n    /* ======== State Variables ======== */\n    /**\n     * @dev Storage slot for tracking the upgrade operation state.\n     *      Prevents re-entrancy during the upgrade process.\n     *      keccak256(abi.encode(uint256(keccak256(\"UUPSTimelockUpgradeableCore.TimelockUpgradeableStorage\")) - 1)) & ~bytes32(uint256(0xff))\n     */\n    bytes32 private constant UUPS_TIMELOCK_UPGRADEABLE_CORE_STORAGE_SLOT =\n        0x2c9356b94ada349e65b0a691cd15e24beddfc13e05a26de25d9c64509c824400;\n\n    /// @custom:storage-location erc7201:UUPSTimelockUpgradeableCore.TimelockUpgradeableStorage\n    struct TimelockUpgradeableStorage {\n        /// @notice The hash of the currently scheduled upgrade operation, or zero if none.\n        bytes32 operationId;\n        /// @notice The delay in seconds before a queued operation can be executed.\n        uint256 delay;\n    }\n\n    /* ======== Modifiers ======== */\n\n    /// @notice Ensures the contract is not currently upgrading.\n    modifier isNotUpgrading() {\n        if (_isUpgrading()) {\n            revert AlreadyUpgrading();\n        }\n        _;\n    }\n\n    /// @notice Ensures the contract is currently upgrading.\n    modifier isUpgrading() {\n        if (!_isUpgrading()) {\n            revert NoUpgradeScheduled();\n        }\n        _;\n    }\n\n    /// @notice Restricts function to internal calls only.\n    modifier isInternalCall() {\n        emit Callers(msg.sender, address(this));\n        if (msg.sender != address(this)) revert UnAuthorizedCall();\n        _;\n    }\n\n    /* ======== Internal Initializer ======== */\n\n    /**\n     * @notice Initializes the UUPSTimelock with a specified delay.\n     * @dev Idempotent: Only initializes if delay is not already set (default value is 0).\n     *      This preserves existing delay during upgrades - new init data will not override existing delay.\n     * @param _delay The delay in seconds before a queued operation can be executed.\n     */\n    function _UUPSTimelock_init(uint256 _delay) internal {\n        TimelockUpgradeableStorage storage $ = _getTimelockUpgradeableStorage();\n        if ($.delay == 0) {\n            _setDelay(_delay);\n        }\n    }\n\n    /* ======== Internal State-Changing Functions ======== */\n\n    /**\n     * @notice Executes the scheduled upgrade operation after the timelock delay has elapsed.\n     * @dev Finalizes the upgrade by executing the operation previously scheduled via `queueUpgrade`.\n     *      Checks that the upgrade is authorized and the timelock conditions are met before proceeding.\n     *      Decodes the scheduled calldata to extract the new implementation address and initialization data,\n     *      then invokes _authorizeUpgrade before executing the operation.\n     *      Upon successful execution, the upgrade operation is cleared from storage.\n     * @custom:reverts NoUpgradeScheduled if there is no upgrade operation in progress.\n     * @custom:reverts TimelockDoesNotExist if the scheduled operation does not exist.\n     * @custom:reverts TimelockNotReached if the timelock delay has not yet elapsed.\n     * @custom:reverts InvalidUpgradeCalldata if the scheduled calldata is invalid.\n     */\n    function _executeUpgrade() internal {\n        TimelockUpgradeableStorage storage $ = _getTimelockUpgradeableStorage();\n        bytes32 _operationId = $.operationId;\n        (, bytes memory _data, , ) = getScheduledOperationDetails(_operationId);\n\n        // Decode the scheduled calldata to extract newImplementation and initData\n        (address _newImplementation, bytes memory _initData) = _decodeUpgradeCalldata(_data);\n\n        // Authorize the upgrade with the correct parameters\n        _authorizeUpgrade(_newImplementation, _initData);\n\n        _executeScheduledOperation(_operationId);\n        delete $.operationId;\n    }\n\n    /**\n     * @notice Cancels a scheduled upgrade operation.\n     * @dev Allows cancellation of a previously scheduled upgrade operation at any time before it is finalized.\n     *      Decodes the scheduled calldata to extract the new implementation address and initialization data,\n     *      then invokes _authorizeUpgrade before canceling the operation.\n     *      Removes the scheduled operation from storage, preventing it from being executed in the future.\n     *      If no upgrade is currently scheduled, this function has no effect.\n     * @custom:emits Canceled(bytes32 operationId) when the operation is successfully canceled.\n     * @custom:reverts InvalidUpgradeCalldata if the scheduled calldata is invalid.\n     */\n    function _cancelUpgrade() internal {\n        TimelockUpgradeableStorage storage $ = _getTimelockUpgradeableStorage();\n        bytes32 _operationId = $.operationId;\n        (, bytes memory _data, , ) = getScheduledOperationDetails(_operationId);\n\n        // Decode the scheduled calldata to extract newImplementation and initData\n        (address _newImplementation, bytes memory _initData) = _decodeUpgradeCalldata(_data);\n\n        // Authorize the upgrade cancellation with the correct parameters\n        _authorizeUpgrade(_newImplementation, _initData);\n\n        _cancelScheduledOperation(_operationId);\n        delete $.operationId;\n    }\n\n    /**\n     * @notice Executes the upgrade to a new implementation with optional initialization data.\n     * @dev Intended to be called internally by the contract itself as part of the timelock upgrade flow.\n     *      Performs the upgrade to the specified implementation and optionally executes additional setup logic.\n     *      Access is restricted to internal calls only via the `isInternalCall` modifier.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional initialization calldata to execute on the new implementation after the upgrade.\n     */\n    function _callUpgradeToAndCallUUPS(\n        address _newImplementation,\n        bytes memory _data\n    ) internal isInternalCall {\n        _upgradeToAndCallUUPS(_newImplementation, _data);\n    }\n\n    /**\n     * @notice Schedules the upgrade operation with the timelock.\n     * This is a overrideable function to be overridden by derived contracts to implement custom validations.\n     * @dev Schedules the upgrade operation to be executed after the timelock delay.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data The data to be passed to the `callUpgradeToAndCallUUPS` function.\n     */\n    function _triggerUpgrade(\n        address _newImplementation,\n        bytes memory _data\n    ) internal virtual override {\n        _scheduleUpgrade(_newImplementation, _data);\n    }\n\n    /**\n     * @notice Schedules the upgrade operation with the timelock.\n     * @dev Encodes the upgrade operation and schedules it for execution after the delay.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data The data to be passed to the `callUpgradeToAndCallUUPS` function.\n     */\n    function _scheduleUpgrade(\n        address _newImplementation,\n        bytes memory _data\n    ) internal isNotUpgrading {\n        TimelockUpgradeableStorage storage $ = _getTimelockUpgradeableStorage();\n        // Add the delay to the current block timestamp to get the scheduled execution time ahead of the current block.\n        // solhint-disable-next-line not-rely-on-time\n        uint256 _executionTimestamp = block.timestamp + $.delay;\n\n        bytes32 _operationId = _scheduleOperation(\n            address(this),\n            abi.encodeWithSignature(\n                \"callUpgradeToAndCallUUPS(address,bytes)\",\n                _newImplementation,\n                _data\n            ),\n            _executionTimestamp\n        );\n\n        $.operationId = _operationId;\n    }\n\n    /* ======== Private State-Changing Functions ======== */\n\n    /**\n     * @notice Sets the delay for the timelock.\n     * @dev Sets the delay in seconds before a queued operation can be executed.\n     * @param _delay The delay in seconds.\n     */\n    function _setDelay(uint256 _delay) private {\n        if (_delay == 0) revert InvalidDelay();\n        TimelockUpgradeableStorage storage $ = _getTimelockUpgradeableStorage();\n        $.delay = _delay;\n    }\n\n    /* ======== Private View/Pure Functions ======== */\n\n    /**\n     * @notice Decodes and validates scheduled upgrade calldata.\n     * @dev Extracts the new implementation address and initialization data from the scheduled operation calldata.\n     *      Validates that the function selector matches `callUpgradeToAndCallUUPS(address,bytes)`.\n     * @param _data The encoded calldata from the scheduled operation.\n     * @return _newImplementation The address of the new implementation contract.\n     * @return _initData The initialization calldata to be executed on the new implementation.\n     * @custom:reverts InvalidUpgradeCalldata if the function selector does not match or decoding fails.\n     */\n    function _decodeUpgradeCalldata(\n        bytes memory _data\n    ) private pure returns (address _newImplementation, bytes memory _initData) {\n        // Validate minimum length for callUpgradeToAndCallUUPS(address,bytes):\n        // - 4 bytes:  function selector\n        // - 32 bytes: address parameter (newImplementation)\n        // - 32 bytes: offset to dynamic bytes data (required by ABI encoding, points to byte 64)\n        // - 32 bytes: length of bytes array (can be 0 for empty initData)\n        // Total: 100 bytes minimum (data itself can be empty)\n        if (_data.length < 100) {\n            revert InvalidUpgradeCalldata();\n        }\n\n        // Decode the parameters\n        // Skip the first 4 bytes (selector) and decode (address, bytes)\n        (_newImplementation, _initData) = abi.decode(\n            _data.slice(4, _data.length),\n            (address, bytes)\n        );\n    }\n\n    /**\n     * @notice Checks if the contract is currently in the upgrading state.\n     * @return value `true` if the contract is upgrading, `false` otherwise.\n     */\n    function _isUpgrading() private view returns (bool) {\n        TimelockUpgradeableStorage storage $ = _getTimelockUpgradeableStorage();\n        return $.operationId != bytes32(0);\n    }\n\n    /**\n     * @dev Returns the TimelockUpgradeableStorage struct.\n     */\n    function _getTimelockUpgradeableStorage()\n        private\n        pure\n        returns (TimelockUpgradeableStorage storage $)\n    {\n        // Use assembly to simply slot the storage location into a variable\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := UUPS_TIMELOCK_UPGRADEABLE_CORE_STORAGE_SLOT\n        }\n    }\n}\n"},{"file_path":"libs/Timelock/TimelockCore.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title TimelockCore\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Core timelock implementation with slot storage pattern\n * @dev This abstract contract provides the core timelock functionality with only internal functions.\n * It uses the slot storage pattern for better encapsulation and storage conflict avoidance.\n */\nabstract contract TimelockCore {\n    /* ======== State variables ======== */\n    /** @notice TIMELOCK_CORE_STORAGE_SLOT is a constant used to locate the TimelockStorage struct in storage.\n     * This ensures a unique storage slot, minimizing collision risks with other storage variables in the contract.\n     * It's calculated as keccak256(abi.encode(uint256(keccak256(\"TimelockCore.TimelockStorage\")) - 1)) & ~bytes32(uint256(0xff)).\n     */\n    bytes32 private constant TIMELOCK_CORE_STORAGE_SLOT =\n        0x1626844f871e5080d673ecb96ea8a32c7bdf671ea137282b2886cd9d0fd9a700;\n\n    struct Operation {\n        address target;\n        uint256 value;\n        bytes data;\n        uint256 eta;\n    }\n\n    /// @custom:storage-location erc7201:TimelockCore.TimelockStorage\n    struct TimelockStorage {\n        // @notice operationCounter is incremented for each new operation to ensure unique IDs\n        uint256 operationCounter;\n        // @notice timelock maps the operation ID to the timestamp when it can be executed.\n        mapping(bytes32 operationId => uint256 eta) timelock;\n        mapping(bytes32 operationId => Operation operation) scheduledOperations;\n    }\n\n    /* ======== Custom Errors ======== */\n    error InvalidTimestamp();\n    error TimelockNotReached();\n    error TimelockDoesNotExist();\n    error TimeLockAlreadyExist();\n    error InsufficientFunds(uint256 given, uint256 expected);\n    error OperationExecutionFailed(bytes32 operationId);\n\n    /* ======== Events ======== */\n    /**\n     * @notice Emitted when an operation is scheduled.\n     * @param operationId The unique ID of the operation.\n     * @param target The address of the contract to call.\n     * @param value The amount of Ether (in wei) to send with the call.\n     * @param data The data to send with the call (ABI-encoded function arguments).\n     * @param eta The timestamp (in seconds since Unix epoch) after which the operation can be executed.\n     */\n    event Queued(\n        bytes32 indexed operationId,\n        address target,\n        uint256 value,\n        bytes data,\n        uint256 eta\n    );\n\n    /**\n     * @notice Emitted when an operation is executed.\n     * @param operationId The unique ID of the operation.\n     * @param target The address of the contract that was called.\n     * @param value The amount of Ether (in wei) that was sent with the call.\n     * @param data The data that was sent with the call.\n     * @param timestamp The timestamp (in seconds since Unix epoch) when the operation is executed.\n     */\n    event Executed(\n        bytes32 indexed operationId,\n        address target,\n        uint256 value,\n        bytes data,\n        uint256 timestamp\n    );\n\n    /**\n     * @notice Emitted when an operation is cancelled.\n     * @param operationId The unique ID of the operation.\n     */\n    event Canceled(bytes32 indexed operationId);\n\n    /* ======== Internal View/Pure Functions ======== */\n\n    /**\n     * @notice Returns the details of a scheduled timelock operation.\n     * @dev Retrieves the target address, calldata, value, and ETA for a given operation ID.\n     *      This function allows internal callers to inspect the parameters of a scheduled operation\n     *      before it is executed or cancelled.\n     * @param _operationId The unique ID of the scheduled operation.\n     * @return target The address of the contract to be called.\n     * @return data The calldata to be sent with the call.\n     * @return value The amount of Ether (in wei) to be sent with the call.\n     * @return eta The earliest timestamp at which the operation can be executed.\n     */\n    function _getScheduledOperationDetails(\n        bytes32 _operationId\n    )\n        internal\n        view\n        returns (address target, bytes memory data, uint256 value, uint256 eta)\n    {\n        TimelockStorage storage $ = _getTimelockStorage();\n        Operation memory _op = $.scheduledOperations[_operationId];\n        return (_op.target, _op.data, _op.value, _op.eta);\n    }\n\n    /**\n     * @notice Checks if a timelock operation is valid and ready for execution.\n     * @dev Reverts if the operation does not exist or if the required timelock delay has not yet passed.\n     * @param _operationId The unique ID of the operation to validate.\n     * @custom:reverts TimelockDoesNotExist if the operation is not scheduled.\n     * @custom:reverts TimelockNotReached if the timelock delay has not yet elapsed.\n     */\n    function _isExecutableOperation(bytes32 _operationId) internal view {\n        TimelockStorage storage $ = _getTimelockStorage();\n        uint256 _eta = $.timelock[_operationId];\n        if (_eta == 0) revert TimelockDoesNotExist();\n        if (_getBlockTimestamp() < _eta) revert TimelockNotReached();\n    }\n\n    /* ======== Internal State-Changing Functions ======== */\n    /**\n     * @notice Executes a timelock operation.\n     * @param _operationId The unique ID of the operation to execute.\n     */\n    function _executeScheduledOperation(bytes32 _operationId) internal {\n        _isExecutableOperation(_operationId);\n        TimelockStorage storage $ = _getTimelockStorage();\n\n        Operation memory _op = $.scheduledOperations[_operationId];\n        address _target = _op.target;\n        uint256 _value = _op.value;\n        bytes memory _data = _op.data;\n\n        if (address(this).balance < _value) {\n            revert InsufficientFunds(_value, address(this).balance);\n        }\n\n        // Remove the operation details and timelock details from storage BEFORE the external call\n        // to prevent reentrancy attacks (Checks-Effects-Interactions pattern)\n        delete $.timelock[_operationId];\n        delete $.scheduledOperations[_operationId];\n\n        // Call the target contract and handle the return value\n        // Note: You cannot call internal functions of other contracts using .call, delegatecall, or similar low-level calls.\n        // Internal functions are not part of the contract's ABI and are only accessible within the contract itself or its derived contracts.\n        // The following line can only call public or external functions:\n        (bool _success, ) = _target.call{value: _value}(_data);\n\n        if (!_success) {\n            revert OperationExecutionFailed(_operationId);\n        }\n\n        emit Executed(\n            _operationId,\n            _target,\n            _value,\n            _data,\n            _getBlockTimestamp()\n        );\n    }\n\n    /**\n     * @notice Schedules an operation to be executed after a delay.\n     * @param _target The address of the contract to call.\n     * @param _data The _data to send with the call (ABI-encoded function arguments).\n     * @param _eta The timestamp (in seconds since Unix epoch) after which the operation can be executed.\n     * @return operationId The unique ID of the timelock operation.\n     */\n    function _scheduleOperation(\n        address _target,\n        bytes memory _data,\n        uint256 _eta\n    ) internal returns (bytes32 operationId) {\n        if (_getBlockTimestamp() >= _eta) {\n            revert InvalidTimestamp();\n        }\n        TimelockStorage storage $ = _getTimelockStorage();\n        uint256 _value = msg.value;\n\n        // Generate unique operation ID from counter (starts at 1 to avoid bytes32(0))\n        $.operationCounter++;\n        operationId = bytes32($.operationCounter);\n\n        $.timelock[operationId] = _eta;\n        $.scheduledOperations[operationId] = Operation({\n            target: _target,\n            value: _value,\n            data: _data,\n            eta: _eta\n        });\n\n        // Emit the Queued event with the operation details\n        emit Queued(\n            operationId,\n            _target,\n            _value,\n            _data,\n            _eta\n        );\n    }\n\n    /**\n     * @notice Cancels a timelock operation.\n     * @param _operationId The unique ID of the operation to cancel.\n     */\n    function _cancelScheduledOperation(bytes32 _operationId) internal {\n        TimelockStorage storage $ = _getTimelockStorage();\n        if ($.timelock[_operationId] != 0) {\n            // Remove the scheduled time\n            delete $.timelock[_operationId];\n            // Remove the operation details\n            delete $.scheduledOperations[_operationId];\n\n            emit Canceled(_operationId);\n        }\n    }\n\n    /* ======== Private View/Pure Functions ======== */\n    /**\n     * @notice Retrieves the TimelockStorage struct from the storage slot.\n     * @dev Returns the TimelockStorage struct.\n     */\n    function _getTimelockStorage()\n        private\n        pure\n        returns (TimelockStorage storage $)\n    {\n        // Use assembly to simply slot the storage location into a variable\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := TIMELOCK_CORE_STORAGE_SLOT\n        }\n    }\n\n    /**\n     * Used to avoid multiple lines of solhint directives in a single line for better readability.\n     * @dev Returns the current block timestamp.\n     */\n    function _getBlockTimestamp() private view returns (uint256) {\n        // solhint-disable-next-line not-rely-on-time\n        return block.timestamp;\n    }\n}\n"},{"file_path":"apps/tokenization/SygToken/contracts/ERC20SygToken.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport {ERC20} from \"libs/ERC20/ERC20.sol\";\nimport {RolesManager} from \"./RolesManager.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title ERC20SygToken\n * @author SYGNUM AG - Blockchain team 3301\n * @notice ERC20 implementation with role-based access control and whitelist restrictions\n * @dev This contract extends ERC20 to add TOKEN_USER checks for transfers and approvals,\n *      and provides mint/burn functions restricted to authorized roles.\n *      All transfer operations respect the paused state.\n */\nabstract contract ERC20SygToken is ERC20, RolesManager {\n    /* ======== ERRORS ======== */\n\n    error NotTokenUser(address account);\n\n    /* ======== MODIFIERS ======== */\n\n    /**\n     * @notice Modifier to check if an address is a whitelisted token user\n     * @param _account The address to check\n     */\n    modifier onlyTokenUser(address _account) {\n        if (!this.isTokenUser(_account)) {\n            revert NotTokenUser(_account);\n        }\n        _;\n    }\n\n    /* ======== EXTERNAL/PUBLIC VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Transfers tokens from caller to recipient\n     * @dev Overrides ERC20 transfer to add TOKEN_USER whitelist checks and pause protection\n     * @param _to The recipient address\n     * @param _amount The amount to transfer\n     * @return True if transfer succeeded\n     */\n    function transfer(\n        address _to,\n        uint256 _amount\n    ) public virtual override requiresAuth onlyTokenUser(_to) whenNotPaused returns (bool) {\n        return _transfer(msg.sender, _to, _amount);\n    }\n\n    /**\n     * @notice Transfers tokens from one address to another using allowance\n     * @dev Overrides ERC20 transferFrom to add TOKEN_USER whitelist checks and pause protection\n     * @param _from The sender address\n     * @param _to The recipient address\n     * @param _amount The amount to transfer\n     * @return True if transfer succeeded\n     */\n    function transferFrom(\n        address _from,\n        address _to,\n        uint256 _amount\n    ) public override requiresAuth onlyTokenUser(_from) onlyTokenUser(_to) whenNotPaused returns (bool) {\n        return _transferFrom(_from, _to, _amount);\n    }\n\n    /**\n     * @notice Approves a spender to transfer tokens on behalf of caller\n     * @dev Overrides ERC20 approve to add pause protection\n     * @param _spender The address allowed to spend tokens\n     * @param _amount The amount of tokens the spender is allowed to spend\n     * @return True if approval succeeded\n     */\n    function approve(\n        address _spender,\n        uint256 _amount\n    ) public virtual override requiresAuth whenNotPaused returns (bool) {\n        return _approve(msg.sender, _spender, _amount);\n    }\n\n    /* ======== EXTERNAL/PUBLIC STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice EIP-2612 permit function to approve spending via signed message\n     * @dev Overrides ERC20 permit to add TOKEN_USER check for owner and pause protection\n     * @param _owner The token owner's address\n     * @param _spender The spender's address\n     * @param _value The amount of tokens to approve\n     * @param _deadline The timestamp after which the signature is no longer valid\n     * @param _v The recovery byte of the signature\n     * @param _r The first 32 bytes of the signature\n     * @param _s The second 32 bytes of the signature\n     */\n    function permit(\n        address _owner,\n        address _spender,\n        uint256 _value,\n        uint256 _deadline,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) public override requiresAuth onlyTokenUser(_owner) whenNotPaused {\n        _permit(_owner, _spender, _value, _deadline, _v, _r, _s);\n    }\n\n    /**\n     * @notice Mints new tokens to a specified address\n     * @param _to The address to mint tokens to (must be TOKEN_USER)\n     * @param _amount The amount of tokens to mint\n     */\n    function mint(address _to, uint256 _amount) external requiresAuth onlyTokenUser(_to) whenNotPaused {\n        _mint(_to, _amount);\n    }\n\n    /**\n     * @notice Burns tokens from a specified address\n     * @param _from The address to burn tokens from\n     * @param _amount The amount of tokens to burn\n     */\n    function burn(address _from, uint256 _amount) external requiresAuth onlyTokenUser(_from) whenNotPaused {\n        _burn(_from, _amount);\n    }\n}\n"},{"file_path":"apps/tokenization/SygToken/contracts/RolesManager.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport {PausableCore} from \"libs/Pausable/PausableCore.sol\";\nimport {Permissioned} from \"libs/Permissioned/Permissioned.sol\";\nimport {ISygFactory} from \"apps/tokenization/SygFactory/interfaces/ISygFactory.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title RolesManager\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Manages role checking and user management by delegating to SygFactory\n * @dev This contract provides role-based access control functions that delegate to the permission manager (SygFactory).\n *      SygFactory automatically determines the applicable groups based on msg.sender (this token contract).\n */\nabstract contract RolesManager is PausableCore, Permissioned {\n    /* ======== EVENTS ======== */\n\n    event MinterBurnerUpdated(address indexed account, bool minterBurner);\n    event TokenUserManagerUpdated(address indexed account, bool tokenUserManager);\n    event TokenUserUpdated(address indexed account, bool tokenUser);\n    event TokenUserBlacklisted(address indexed account, bool blacklist);\n\n    /* ======== EXTERNAL/PUBLIC VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Checks if an account is a role manager\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is a role manager\n     */\n    function isRoleManager(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isRoleManager(_account, new uint16[](0));\n    }\n\n    /**\n     * @notice Checks if an account is an operator\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is an operator\n     */\n    function isOperator(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isOperator(_account, new uint16[](0));\n    }\n\n    /**\n     * @notice Checks if an account is a system account\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is a system account\n     */\n    function isSystem(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isSystem(_account, new uint16[](0));\n    }\n\n    /**\n     * @notice Checks if an account is a pauser\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is a pauser\n     */\n    function isPauser(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isPauser(_account, new uint16[](0));\n    }\n\n    /**\n     * @notice Checks if an account is a minter/burner\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is a minter/burner\n     */\n    function isMinterBurner(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isMinterBurner(_account, new uint16[](0));\n    }\n\n    /**\n     * @notice Checks if an account is a token user manager\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is a token user manager\n     */\n    function isTokenUserManager(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isTokenUserManager(_account, new uint16[](0));\n    }\n\n    /**\n     * @notice Checks if an account is a token user\n     * @dev Groups are automatically determined by SygFactory based on this token's address.\n     *      Returns true only if the account is whitelisted in at least one group AND not blacklisted\n     *      in any group (blacklist supersedes whitelist).\n     * @param _account The account address to check\n     * @return True if the account is a token user\n     */\n    function isTokenUser(address _account) external view returns (bool) {\n        return ISygFactory(getPermissionManagerAddress()).isTokenUser(_account, new uint16[](0));\n    }\n\n    /* ======== EXTERNAL/PUBLIC STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice Updates the minter/burner status for a given account by calling SygFactory\n     * @param _account The address of the account to update\n     * @param _minterBurner True to give minter/burner role to the account, false to remove minter/burner role\n     */\n    function updateMinterBurner(address _account, bool _minterBurner) external requiresAuth whenNotPaused {\n        ISygFactory(getPermissionManagerAddress()).updateMinterBurner(0, _account, _minterBurner);\n        emit MinterBurnerUpdated(_account, _minterBurner);\n    }\n\n    /**\n     * @notice Updates the token user manager status for a given account by calling SygFactory\n     * @param _account The address of the account to update\n     * @param _tokenUserManager True to give token user manager role to the account, false to remove token user manager role\n     */\n    function updateTokenUserManager(address _account, bool _tokenUserManager) external requiresAuth whenNotPaused {\n        ISygFactory(getPermissionManagerAddress()).updateTokenUserManager(0, _account, _tokenUserManager);\n        emit TokenUserManagerUpdated(_account, _tokenUserManager);\n    }\n\n    /**\n     * @notice Updates the token user status for a given account by calling SygFactory\n     * @dev Requires custom group ID to be enabled (customGroupId != 0)\n     * @param _account The address of the account to update\n     * @param _tokenUser True to give token user role to the account, false to remove token user role\n     */\n    function updateTokenUser(address _account, bool _tokenUser) external requiresAuth whenNotPaused {\n        ISygFactory(getPermissionManagerAddress()).updateTokenUser(0, _account, _tokenUser);\n        emit TokenUserUpdated(_account, _tokenUser);\n    }\n\n    /**\n     * @notice Blacklist a user from the token user role for a given account by calling SygFactory\n     * @dev Requires custom group ID to be enabled (customGroupId != 0)\n     * @param _account The address of the account to update\n     * @param _blacklist True to blacklist the user from the token user role, false to unblacklist the user from the token user role\n     */\n    function blacklistTokenUser(address _account, bool _blacklist) external requiresAuth whenNotPaused {\n        ISygFactory(getPermissionManagerAddress()).blacklistTokenUser(0, _account, _blacklist);\n        emit TokenUserBlacklisted(_account, _blacklist);\n    }\n}\n"},{"file_path":"libs/ERC20/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.8.0;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title IERC20\n * @author SYGNUM AG - Blockchain team 3301\n * @dev Interface of the ERC-20 standard as defined in the ERC with extensions:\n *   1. EIP-2612 permit functionality for gasless approvals\n *   2. Standard metadata functions (name, symbol, decimals)\n *\n * This interface matches the implementation in ERC20.sol\n */\ninterface IERC20 {\n    /* ========== EVENTS ========== */\n\n    /**\n     * @dev Emitted when `amount` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `amount` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `amount` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n    /* ========== STATE VARIABLES ========== */\n\n    /**\n     * @dev Returns the name of the token.\n     * Part of the ERC20 optional metadata extension.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     * Part of the ERC20 optional metadata extension.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     * Part of the ERC20 optional metadata extension.\n     */\n    function decimals() external view returns (uint8);\n\n    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address _account) external view returns (uint256);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address _owner, address _spender) external view returns (uint256);\n\n    /**\n     * @dev Returns the current nonce for `owner`.\n     * This value is used in EIP-2612 permit function and must be\n     * included whenever a signature is generated.\n     *\n     * Every successful call to {permit} increases the owner's nonce by one,\n     * preventing signature reuse.\n     */\n    function nonces(address _owner) external view returns (uint256);\n    \n    /* ========== FUNCTIONS ========== */\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address _to, uint256 _value) external returns (bool);\n\n    /**\n     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the\n     * caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address _spender, uint256 _value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);\n\n    /**\n     * @dev EIP-2612 permit function to approve token spending with a signature\n     * instead of msg.sender calling approve directly.\n     *\n     * Sets `value` as the allowance of `spender` over `owner`'s tokens,\n     * given `owner`'s signed approval.\n     *\n     * Requirements:\n     * - `deadline` must not have expired\n     * - `v`, `r` and `s` must form a valid secp256k1 signature from `owner`\n     * - The signature must use the current nonce of `owner` (see {nonces})\n     *\n     * Emits an {Approval} event.\n     */\n    function permit(\n        address _owner,\n        address _spender,\n        uint256 _value,\n        uint256 _deadline,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) external;\n}"},{"file_path":"libs/Pausable/interfaces/IPausable.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title IPausable\n * @notice Interface for pausable functionality\n * @dev Defines the external interface for contracts that can be paused and unpaused\n */\ninterface IPausable {\n    /* ======== VIEW FUNCTIONS ======== */\n\n    /**\n     * @notice Returns whether the contract is paused\n     * @return True if the contract is paused, false otherwise\n     */\n    function isPaused() external view returns (bool);\n\n    /* ======== STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice Pauses the contract\n     * @dev Only callable by authorized accounts (e.g., pausers)\n     */\n    function pause() external;\n\n    /**\n     * @notice Unpauses the contract\n     * @dev Only callable by authorized accounts (e.g., pausers)\n     */\n    function unpause() external;\n}"},{"file_path":"libs/external/chainlink-evm/contracts/src/v0.8/data-feeds/interfaces/IBundleBaseAggregator.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface IBundleBaseAggregator {\n  function latestBundle() external view returns (bytes memory bundle);\n\n  function bundleDecimals() external view returns (uint8[] memory);\n\n  function latestBundleTimestamp() external view returns (uint256);\n}"},{"file_path":"libs/Timelock/Timelock.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {TimelockView} from \"./TimelockView.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title Timelock\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Standard Timelock implementation that extends TimelockView\n * and exposes the basic timelock interface functions.\n * @dev Abstract contract that provides a mechanism to delay the execution of transactions.\n */\nabstract contract Timelock is TimelockView {\n}\n"},{"file_path":"libs/external/chainlink-evm/contracts/src/v0.8/data-feeds/interfaces/IBundleAggregatorProxy.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\nimport {IBundleBaseAggregator} from \"./IBundleBaseAggregator.sol\";\nimport {ICommonAggregator} from \"./ICommonAggregator.sol\";\n\ninterface IBundleAggregatorProxy is IBundleBaseAggregator, ICommonAggregator {\n  function proposedAggregator() external view returns (address);\n\n  function confirmAggregator(\n    address aggregatorAddress\n  ) external;\n\n  function aggregator() external view returns (address);\n}"},{"file_path":"libs/Initializable/Initializable.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {InitializableView} from \"libs/Initializable/InitializableView.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title Initializable\n * @notice Standard Initializable implementation that extends InitializableView\n * and exposes the public interface functions.\n * @dev This contract introduces an `initializer` modifier to prevent re-initialization of contracts,\n * ensuring that critical setup logic is executed only once, which is especially important in upgradeable contracts.\n */\nabstract contract Initializable is InitializableView {\n}\n"},{"file_path":"libs/FundRecovery/FundRecoveryCore.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport {IERC20} from \"libs/ERC20/interfaces/IERC20.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title FundRecoveryCore\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Core fund recovery implementation for recovering native tokens and ERC20 tokens\n * @dev This library provides the core logic for recovering funds from contracts.\n *      It handles both native tokens (ETH) and ERC20 tokens, including fee-on-transfer tokens.\n *      Contracts inheriting from this can call the internal _recoverFunds function.\n */\nabstract contract FundRecoveryCore {\n    /* ======== ERRORS ======== */\n\n    error TransferFailed();\n\n    /* ======== EVENTS ======== */\n\n    event FundsRecovered(address indexed token, address indexed to, uint256 requestedAmount, uint256 actualAmountReceived);\n\n    /* ======== INTERNAL STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice Recovers funds from the contract\n     * @dev If _token is address(0), recovers native token (ETH), else recovers ERC20 tokens\n     * For ERC-20 tokens, the emitted amounts include both the requested amount and the actual amount received,\n     * which may differ for fee-on-transfer tokens.\n     * @param _token The token address (zero for native)\n     * @param _to The recipient address\n     * @param _amount The amount to recover (in wei for native ETH, in token's smallest unit for ERC-20)\n     */\n    function _recoverFunds(address _token, address payable _to, uint256 _amount) internal {\n        bool _success;\n        uint256 _actualAmountReceived;\n\n        if (_token == address(0)) {\n            // Recover native token (ETH)\n            (_success,) = _to.call{value: _amount}(\"\");\n            if (!_success) {\n                revert TransferFailed();\n            }\n            _actualAmountReceived = _amount;\n        } else {\n            // Recover ERC20 token\n            // Measure actual amount received for fee-on-transfer tokens\n            IERC20 _tokenContract = IERC20(_token);\n            uint256 _balanceBefore = _tokenContract.balanceOf(_to);\n\n            // Use low-level call to handle all token types:\n            // - Tokens that revert\n            // - Tokens that return false\n            // - Non-standard tokens that don't return a value (like USDT)\n            bytes memory _returndata;\n            // solhint-disable-next-line avoid-low-level-calls\n            (_success, _returndata) = _token.call(\n                abi.encodeWithSelector(IERC20.transfer.selector, _to, _amount)\n            );\n            // Check if call succeeded and validate return data\n            // Success means: call succeeded AND (no return data OR return data decodes to true)\n            if (!_success || (_returndata.length > 0 && !abi.decode(_returndata, (bool)))) {\n                revert TransferFailed();\n            }\n\n            uint256 _balanceAfter = _tokenContract.balanceOf(_to);\n\n            _actualAmountReceived = _balanceAfter - _balanceBefore;\n        }\n\n        emit FundsRecovered(_token, _to, _amount, _actualAmountReceived);\n    }\n}\n"},{"file_path":"libs/ERC20/ERC20Core.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\n/*//////////////////////////////////////////////////////////////\n                            CUSTOM ERRORS\n//////////////////////////////////////////////////////////////*/\n\nerror PermitDeadlineExpired();\nerror InvalidSigner();\nerror ZeroAddress();\n\n/**\n * @title ERC20Core\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Core ERC20 implementation with slot storage pattern\n * @dev This contract is a copy of the ERC20 contract from Solmate with a few twist:\n *   1. The variables use slot storage pattern for better encapsulation\n *   2. The contract has been made upgradeable\n *   3. Require statements have been replaced with custom errors\n */\n\n/** Solmate notes: */\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\n/**\n * @custom:security-contact blockchain@sygnum.com\n */\nabstract contract ERC20Core {\n    /* ======== STATE VARIABLES ======== */\n    \n    /**\n     * @dev ERC20_STORAGE_SLOT is a constant used to locate the ERC20Storage struct in storage.\n     * This ensures a unique storage slot, minimizing collision risks with other storage variables in the contract.\n     * It's calculated as keccak256(abi.encode(uint256(keccak256(\"ERC20Core.ERC20Storage\")) - 1)) & ~bytes32(uint256(0xff)).\n     */\n    bytes32 private constant ERC20_CORE_STORAGE_SLOT =\n        0x67df8e602072ae967fe4567cec1273e29da0bd7a5a1af20d9b5c8d3f0d838500;\n\n    /// @custom:storage-location erc7201:ERC20Core.ERC20Storage\n    struct ERC20Storage {\n        // METADATA STORAGE\n        string name;\n        string symbol;\n        uint8 decimals;\n        // ERC20 STORAGE\n        uint256 totalSupply;\n        mapping(address account => uint256 balance) balanceOf;\n        mapping(address owner => mapping(address spender => uint256 amount)) allowance;\n        // EIP-2612 STORAGE\n        uint256 INITIAL_CHAIN_ID;\n        bytes32 INITIAL_DOMAIN_SEPARATOR;\n        mapping(address account => uint256 nonce) nonces;\n    }\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    event Approval(\n        address indexed owner,\n        address indexed spender,\n        uint256 amount\n    );\n\n    /*//////////////////////////////////////////////////////////////\n                            VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns the name of the token\n     * @return The name of the token\n     */\n    function _name() internal view returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.name;\n    }\n\n    /**\n     * @notice Returns the symbol of the token\n     * @return The symbol of the token\n     */\n    function _symbol() internal view returns (string memory) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.symbol;\n    }\n\n    /**\n     * @notice Returns the decimals of the token\n     * @return The decimals of the token\n     */\n    function _decimals() internal view returns (uint8) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.decimals;\n    }\n\n    /**\n     * @notice Returns the total supply of the token\n     * @return The total supply of the token\n     */\n    function _totalSupply() internal view returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.totalSupply;\n    }\n\n    /**\n     * @notice Returns the balance of the specified address\n     * @param _account The address to query the balance of\n     * @return The balance of the specified address\n     */\n    function _balanceOf(address _account) internal view returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.balanceOf[_account];\n    }\n\n    /**\n     * @notice Returns the allowance of the spender for the owner\n     * @param _owner The address of the token owner\n     * @param _spender The address of the spender\n     * @return The allowance amount\n     */\n    function _allowance(address _owner, address _spender) internal view returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.allowance[_owner][_spender];\n    }\n\n    /**\n     * @notice Returns the nonce for the specified address (EIP-2612)\n     * @param _account The address to query the nonce of\n     * @return The nonce of the specified address\n     */\n    function _nonces(address _account) internal view returns (uint256) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return $.nonces[_account];\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               INITIALIZER\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Initializes the ERC20 token with name, symbol and decimals\n     * @dev Idempotent: Only initializes if INITIAL_CHAIN_ID is not already set (default value is 0).\n     *      This preserves existing state during upgrades - new init data will not override existing values.\n     * @param _tokenName The name of the token\n     * @param _tokenSymbol The symbol of the token\n     * @param _tokenDecimals The number of decimals for the token\n     */\n    function _erc20_init(\n        string memory _tokenName,\n        string memory _tokenSymbol,\n        uint8 _tokenDecimals\n    ) internal {\n        ERC20Storage storage $ = _getERC20Storage();\n        if ($.INITIAL_CHAIN_ID == 0) {\n            $.name = _tokenName;\n            $.symbol = _tokenSymbol;\n            $.decimals = _tokenDecimals;\n\n            $.INITIAL_CHAIN_ID = block.chainid;\n            $.INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator();\n        }\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                               ERC20 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Internal function to approve spending allowance\n     * @param _owner The address of the token owner\n     * @param _spender The address to approve for spending\n     * @param _amount The amount to approve\n     * @return True if approval was successful\n     */\n    function _approve(address _owner, address _spender, uint256 _amount) internal returns (bool) {\n        if (_owner == address(0) || _spender == address(0)) revert ZeroAddress();\n\n        ERC20Storage storage $ = _getERC20Storage();\n        $.allowance[_owner][_spender] = _amount;\n\n        emit Approval(_owner, _spender, _amount);\n\n        return true;\n    }\n\n    /**\n     * @notice Internal function to transfer tokens between addresses\n     * @param _from The address to transfer from\n     * @param _to The address to transfer to\n     * @param _amount The amount to transfer\n     * @return True if transfer was successful\n     */\n    function _transfer(address _from, address _to, uint256 _amount) internal returns (bool) {\n        if (_from == address(0) || _to == address(0)) revert ZeroAddress();\n\n        ERC20Storage storage $ = _getERC20Storage();\n        $.balanceOf[_from] -= _amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            $.balanceOf[_to] += _amount;\n        }\n\n        emit Transfer(_from, _to, _amount);\n\n        return true;\n    }\n\n    /**\n     * @notice Internal function to transfer tokens from one address to another using allowance\n     * @param _from The address to transfer from\n     * @param _to The address to transfer to\n     * @param _amount The amount to transfer\n     * @return True if transfer was successful\n     */\n    function _transferFrom(\n        address _from,\n        address _to,\n        uint256 _amount\n    ) internal returns (bool) {\n        ERC20Storage storage $ = _getERC20Storage();\n        uint256 _allowed = $.allowance[_from][msg.sender]; // Saves gas for limited approvals.\n\n        if (_allowed != type(uint256).max) $.allowance[_from][msg.sender] = _allowed - _amount;\n\n        return _transfer(_from, _to, _amount);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             EIP-2612 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Internal function to handle permit signatures for gasless approvals\n     * @param _owner The address of the token owner\n     * @param _spender The address to approve for spending\n     * @param _value The amount to approve\n     * @param _deadline The deadline for the permit\n     * @param _v The recovery id of the signature\n     * @param _r The r component of the signature\n     * @param _s The s component of the signature\n     */\n    function _permit(\n        address _owner,\n        address _spender,\n        uint256 _value,\n        uint256 _deadline,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) internal {\n        // solhint-disable-next-line not-rely-on-time\n        if (_deadline < block.timestamp) revert PermitDeadlineExpired();\n\n        ERC20Storage storage $ = _getERC20Storage();\n\n        // Unchecked because the only math done is incrementing\n        // the owner's nonce which cannot realistically overflow.\n        unchecked {\n            uint256 _currentNonce = $.nonces[_owner];\n            $.nonces[_owner] = _currentNonce + 1;\n            \n            address _recoveredAddress = ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        _DOMAIN_SEPARATOR(),\n                        keccak256(\n                            abi.encode(\n                                keccak256(\n                                    \"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"\n                                ),\n                                _owner,\n                                _spender,\n                                _value,\n                                _currentNonce,\n                                _deadline\n                            )\n                        )\n                    )\n                ),\n                _v,\n                _r,\n                _s\n            );\n\n            if (_recoveredAddress == address(0) || _recoveredAddress != _owner) revert InvalidSigner();\n\n            $.allowance[_owner][_spender] = _value;\n        }\n\n        emit Approval(_owner, _spender, _value);\n    }\n\n    /**\n     * @notice Returns the domain separator for EIP-712 signatures\n     * @return The domain separator hash\n     */\n    function _DOMAIN_SEPARATOR() internal view returns (bytes32) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return\n            block.chainid == $.INITIAL_CHAIN_ID\n                ? $.INITIAL_DOMAIN_SEPARATOR\n                : _computeDomainSeparator();\n    }\n\n    /**\n     * @notice Computes the domain separator for EIP-712 signatures\n     * @return The computed domain separator hash\n     */\n    function _computeDomainSeparator() internal view returns (bytes32) {\n        ERC20Storage storage $ = _getERC20Storage();\n        return\n            keccak256(\n                abi.encode(\n                    keccak256(\n                        \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                    ),\n                    keccak256(bytes($.name)),\n                    keccak256(\"1\"),\n                    block.chainid,\n                    address(this)\n                )\n            );\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Internal function to mint tokens to an address\n     * @param _to The address to mint tokens to\n     * @param _amount The amount of tokens to mint\n     */\n    function _mint(address _to, uint256 _amount) internal {\n        ERC20Storage storage $ = _getERC20Storage();\n        $.totalSupply += _amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            $.balanceOf[_to] += _amount;\n        }\n\n        emit Transfer(address(0), _to, _amount);\n    }\n\n    /**\n     * @notice Internal function to burn tokens from an address\n     * @param _from The address to burn tokens from\n     * @param _amount The amount of tokens to burn\n     */\n    function _burn(address _from, uint256 _amount) internal {\n        ERC20Storage storage $ = _getERC20Storage();\n        $.balanceOf[_from] -= _amount;\n\n        // Cannot underflow because a user's balance\n        // will never be larger than the total supply.\n        unchecked {\n            $.totalSupply -= _amount;\n        }\n\n        emit Transfer(_from, address(0), _amount);\n    }\n\n    /* ======== PRIVATE VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Retrieves the ERC20Storage struct from the storage slot\n     * @return $ The ERC20Storage struct reference\n     */\n    function _getERC20Storage()\n        private\n        pure\n        returns (ERC20Storage storage $)\n    {\n        // Use assembly to simply slot the storage location into a variable\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := ERC20_CORE_STORAGE_SLOT\n        }\n    }\n}\n"},{"file_path":"apps/tokenization/SygFactory/interfaces/ISygFactory.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title ISygFactory\n * @notice Interface for SygFactory contract\n * @dev Defines all public and external SygFactory functions\n */\ninterface ISygFactory {\n    /* ======== INITIALIZATION FUNCTIONS ======== */\n\n    /**\n     * @notice Initializes the SygFactory contract\n     * @param _initialImplementation The initial implementation address\n     * @param _destroyedImplementation The destroyed implementation address for SygTokenDestroyed\n     * @param _platformAdmin The address to be assigned the PLATFORM_ADMIN role\n     * @param _roleManager The address to be assigned the ROLE_MANAGER role\n     * @param _timelockDelaySeconds The delay in seconds before upgrades can be executed\n     */\n    function initialize(\n        address _initialImplementation,\n        address _destroyedImplementation,\n        address _platformAdmin,\n        address _roleManager,\n        uint256 _timelockDelaySeconds\n    ) external;\n\n    /* ======== ROLE CHECKING FUNCTIONS (from RolesManager) ======== */\n\n    /**\n     * @notice Checks if an account has role manager role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has role manager role within any of the specified groups\n     */\n    function isRoleManager(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has operator role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has operator role within any of the specified groups\n     */\n    function isOperator(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has system role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has system role within any of the specified groups\n     */\n    function isSystem(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has pauser role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has pauser role within any of the specified groups\n     */\n    function isPauser(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has minter/burner role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has minter/burner role within any of the specified groups\n     */\n    function isMinterBurner(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has token user manager role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has token user manager role within any of the specified groups\n     */\n    function isTokenUserManager(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has token role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has token role within any of the specified groups\n     */\n    function isToken(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /**\n     * @notice Checks if an account has token user role within any of the specified groups\n     * @param _account The account address to check\n     * @param _groupIds The group IDs to check against\n     * @return True if the account has token user role within any of the specified groups\n     */\n    function isTokenUser(address _account, uint16[] memory _groupIds) external view returns (bool);\n\n    /* ======== USER MANAGEMENT FUNCTIONS (from RolesManager) ======== */\n\n    /**\n     * @notice Updates role manager role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _roleManager Whether to grant (true) or revoke (false) role manager role\n     */\n    function updateRoleManager(uint16 _groupId, address _account, bool _roleManager) external;\n\n    /**\n     * @notice Updates operator role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _operator Whether to grant (true) or revoke (false) operator role\n     */\n    function updateOperator(uint16 _groupId, address _account, bool _operator) external;\n\n    /**\n     * @notice Updates system role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _system Whether to grant (true) or revoke (false) system role\n     */\n    function updateSystem(uint16 _groupId, address _account, bool _system) external;\n\n    /**\n     * @notice Updates pauser role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _pauser Whether to grant (true) or revoke (false) pauser role\n     */\n    function updatePauser(uint16 _groupId, address _account, bool _pauser) external;\n\n    /**\n     * @notice Updates minter/burner role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _minterBurner Whether to grant (true) or revoke (false) minter/burner role\n     */\n    function updateMinterBurner(uint16 _groupId, address _account, bool _minterBurner) external;\n\n    /**\n     * @notice Updates token user manager role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _tokenUserManager Whether to grant (true) or revoke (false) token user manager role\n     */\n    function updateTokenUserManager(uint16 _groupId, address _account, bool _tokenUserManager) external;\n\n    /**\n     * @notice Updates token user role for an account within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to update\n     * @param _tokenUser Whether to grant (true) or revoke (false) token user role\n     */\n    function updateTokenUser(uint16 _groupId, address _account, bool _tokenUser) external;\n\n    /**\n     * @notice Blacklist a user from the token user role within a specific group\n     * @param _groupId The group ID for the account\n     * @param _account The account address to blacklist / unblacklist\n     * @param _blacklistTokenUser Whether to blacklist (true) or revoke the blacklist (false)\n     */\n    function blacklistTokenUser(uint16 _groupId, address _account, bool _blacklistTokenUser) external;\n\n    /* ======== TOKEN MANAGEMENT FUNCTIONS (from TokenManager) ======== */\n\n    /**\n     * @notice Gets the current SygToken implementation address\n     * @return implementationAddress The implementation address\n     */\n    function getSygTokenImplementation() external view returns (address implementationAddress);\n\n    /**\n     * @notice Updates the SygToken implementation address\n     * @param _newImplementation The new implementation address\n     */\n    function updateSygTokenImplementation(address _newImplementation) external;\n\n    /**\n     * @notice Deploys a new token with specified token configuration and group IDs\n     * @param _name The name of the token\n     * @param _symbol The symbol of the token\n     * @param _decimals The number of decimals for the token\n     * @param _tokenURI The URI for token metadata\n     * @param _groupIds The manual group IDs for the token (must be in range 0-1000), maximum 15 IDs\n     * @return _token The deployed token address\n     */\n    function deployToken(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals,\n        string memory _tokenURI,\n        uint16[] memory _groupIds\n    ) external returns (address _token);\n\n    /**\n     * @notice Updates group IDs for a token\n     * @param _token The token address\n     * @param _groupIds The new group IDs for the token, maximum 15 IDs\n     */\n    function updateTokenGroupIds(address _token, uint16[] memory _groupIds) external;\n\n    /**\n     * @notice Enables a custom group ID for a token\n     * @param _token The token address\n     */\n    function enableCustomGroupId(address _token) external;\n\n    /**\n     * @notice Upgrades a token to the latest implementation\n     * @param _token The token address to upgrade\n     * @param _data The data to call on upgrade\n     */\n    function upgradeToken(address _token, bytes memory _data) external;\n\n    /**\n     * @notice Executes a scheduled token upgrade after the timelock delay\n     * @param _token The token address to complete the upgrade for\n     */\n    function executeTokenUpgrade(address _token) external;\n\n    /**\n     * @notice Cancels a scheduled token upgrade\n     * @param _token The token address to cancel the upgrade for\n     */\n    function cancelTokenUpgrade(address _token) external;\n\n    /**\n     * @notice Destroys a token by upgrading it to the destroyed implementation\n     * @dev For asynchronous upgrades, use executeTokenUpgrade to complete the destruction\n     * @param _token The token address to destroy\n     */\n    function destroyToken(address _token) external;\n\n    /**\n     * @notice Gets token information with properly formatted group IDs\n     * @param _tokenAddress The address of the token\n     * @return tokenAddress The token address\n     * @return groupIds Dynamic array containing only the actual group IDs\n     * @return implementationAddress The implementation address\n     * @return customGroupId The custom group ID (0 if not enabled)\n     */\n    function getTokenInfo(address _tokenAddress) external view returns (\n        address tokenAddress,\n        uint16[] memory groupIds,\n        address implementationAddress,\n        uint16 customGroupId\n    );\n\n    /**\n     * @notice Gets the destroyed implementation address for SygToken\n     * @return The address of the SygTokenDestroyed implementation\n     */\n    function getSygTokenDestroyedImplementation() external view returns (address);\n}\n"},{"file_path":"libs/utils/bytes/BytesLib.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title BytesLib\n * @author Sygnum\n * @notice Library for efficient bytes manipulation operations.\n * @dev Provides utility functions for working with bytes arrays.\n */\nlibrary BytesLib {\n    /**\n     * @notice Slices a bytes array from start to end position.\n     * @dev Sanitizes input by clamping end to buffer length and start to end.\n     *      Uses mcopy for efficient memory copying.\n     * @param _data The bytes array to slice.\n     * @param _start The starting position (inclusive).\n     * @param _end The ending position (exclusive).\n     * @return _result The sliced bytes array.\n     */\n    function slice(\n        bytes memory _data,\n        uint256 _start,\n        uint256 _end\n    ) internal pure returns (bytes memory _result) {\n        // Sanitize inputs\n        _end = _min(_end, _data.length);\n        _start = _min(_start, _end);\n\n        // Allocate and copy\n        _result = new bytes(_end - _start);\n        // solhint-disable-next-line no-inline-assembly\n        assembly (\"memory-safe\") {\n            mcopy(add(_result, 0x20), add(add(_data, 0x20), _start), sub(_end, _start))\n        }\n    }\n\n    /**\n     * @notice Returns the minimum of two numbers.\n     * @dev Internal helper function for sanitizing slice bounds.\n     * @param _a First number.\n     * @param _b Second number.\n     * @return The smaller of the two numbers.\n     */\n    function _min(uint256 _a, uint256 _b) private pure returns (uint256) {\n        return _a < _b ? _a : _b;\n    }\n}\n"},{"file_path":"libs/external/chainlink-evm/contracts/src/v0.8/data-feeds/interfaces/ICommonAggregator.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.4;\n\ninterface ICommonAggregator {\n  function description() external view returns (string memory);\n\n  function version() external view returns (uint256);\n}"},{"file_path":"libs/Initializable/InitializableCore.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title InitializableCore\n * @notice Core implementation of initialization functionality with slot storage pattern\n * @dev This contract provides the core initialization logic without exposing public functions.\n * It uses a storage slot to track initialization status, minimizing gas costs and avoiding storage collisions.\n * This is the core implementation that should be inherited by contracts that need custom initialization logic.\n */\nabstract contract InitializableCore {\n    /* ======== Custom Errors ======== */\n    error InvalidInitialization();\n\n    /* ======== Events ======== */\n    event Initialized();\n\n    /* ======== State variables ======== */\n    /**\n     * @dev INITIALIZED_CORE_STORAGE_SLOT is a constant used to locate the initialization status in storage for InitializableCore.\n     * This ensures a unique storage slot for the initialized flag, minimizing collision risks with other storage variables in the contract.\n     * The value is calculated as keccak256(abi.encode(uint256(keccak256(\"InitializableCore.InitializedStorage\")) - 1)) & ~bytes32(uint256(0xff)).\n     * @custom:storage-location erc7201:InitializableCore.InitializedStorage\n     */\n    bytes32 private constant INITIALIZED_CORE_STORAGE_SLOT =\n        0x112dd7b7d700a9bfd03edf4d4ce6f92b1f5f1a2fd81fde871f4db11384aa0b00;\n\n    /* ======== Modifiers ======== */\n    /// @notice Ensures the initializer function can only be called once.\n    modifier initializer() {\n        if (_isInitialized()) {\n            revert InvalidInitialization();\n        }\n        _setInitialized();\n        _;\n    }\n\n    /* ======== Internal Pure/View Functions ======== */\n    /// @notice Checks if the contract has been initialized.\n    /// @return value True if the contract has been initialized, false otherwise.\n    function _isInitialized() internal view returns (bool value) {\n        // solhint-disable-next-line no-inline-assembly\n        assembly ('memory-safe') {\n            value := sload(INITIALIZED_CORE_STORAGE_SLOT)\n        }\n    }\n\n    /* ======== Internal/Private Storage Manipulation Functions ======== */\n    /// @notice Sets the initialized state of the contract.\n    /// @dev Uses assembly for gas efficiency when writing to the storage slot.\n    function _setInitialized() internal {\n        // solhint-disable-next-line no-inline-assembly\n        assembly ('memory-safe') {\n            sstore(INITIALIZED_CORE_STORAGE_SLOT, 1)\n        }\n        emit Initialized();\n    }\n\n    /// @notice Resets the initialized state of the contract.\n    function _resetInitialized() internal {\n        // solhint-disable-next-line no-inline-assembly\n        assembly ('memory-safe') {\n            sstore(INITIALIZED_CORE_STORAGE_SLOT, 0)\n        }\n    }\n}\n"},{"file_path":"libs/Timelock/TimelockView.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {TimelockCore} from \"libs/Timelock/TimelockCore.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title TimelockView\n * @author SYGNUM AG - Blockchain team 3301\n * @notice View-only Timelock implementation that exposes operation details\n * @dev This contract provides read-only access to timelock operations without\n *      allowing modification. It's designed for contracts that need to query\n *      operation details but should not modify them directly.\n */\nabstract contract TimelockView is TimelockCore {\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL/PUBLIC VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns the details of a scheduled timelock operation\n     * @param _operationId The unique ID of the scheduled operation\n     * @return target The address of the contract to be called\n     * @return data The calldata to be sent with the call\n     * @return value The amount of Ether (in wei) to be sent with the call\n     * @return eta The earliest timestamp at which the operation can be executed\n     */\n    function getScheduledOperationDetails(\n        bytes32 _operationId\n    ) public view returns (address target, bytes memory data, uint256 value, uint256 eta) {\n        return _getScheduledOperationDetails(_operationId);\n    }\n}\n"},{"file_path":"libs/UUPS/UUPSTimelockUpgradeable.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {UUPSTimelockUpgradeableView} from './UUPSTimelockUpgradeableView.sol';\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title UUPSTimelockUpgradeable\n * @author Sygnum\n * @notice Standard UUPS Timelock implementation that extends UUPSTimelockUpgradeableView\n *         and exposes the public interface functions.\n *         Combines UUPS upgradeability with Timelock functionality for secure, delayed upgrades.\n *         Enables governance mechanisms where upgrades are executed only after a specified delay,\n *         providing a safety window for stakeholders.\n */\nabstract contract UUPSTimelockUpgradeable is UUPSTimelockUpgradeableView {\n\n    /* ======== External/Public State-Changing Functions ======== */\n\n    /**\n     * @notice Upgrades the implementation and optionally executes a function call.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional memory to execute after the upgrade.\n     */\n    function upgradeToAndCall(\n        address _newImplementation,\n        bytes memory _data\n    ) public onlyProxy {\n        _upgradeToAndCall(_newImplementation, _data);\n    }\n\n    /**\n     * @notice Executes the scheduled upgrade operation after the timelock delay has elapsed.\n     * @dev Finalizes the upgrade by executing the operation previously scheduled via `queueUpgrade`.\n     *      Checks that the upgrade is authorized and the timelock conditions are met before proceeding.\n     *      Upon successful execution, the upgrade operation is cleared from storage.\n     * @custom:reverts NoUpgradeScheduled if there is no upgrade operation in progress.\n     * @custom:reverts TimelockDoesNotExist if the scheduled operation does not exist.\n     * @custom:reverts TimelockNotReached if the timelock delay has not yet elapsed.\n     */\n    function executeUpgrade() public isUpgrading {\n        _executeUpgrade();\n    }\n\n    /**\n     * @notice Cancels a scheduled upgrade operation.\n     * @dev Allows cancellation of a previously scheduled upgrade operation at any time before it is finalized.\n     *      Removes the scheduled operation from storage, preventing it from being executed in the future.\n     *      If no upgrade is currently scheduled, this function has no effect.\n     * @custom:emits Canceled(bytes32 operationId) when the operation is successfully canceled.\n     */\n    function cancelUpgrade() public isUpgrading {\n        _cancelUpgrade();\n    }\n\n    /**\n     * @notice Executes the upgrade to a new implementation with optional initialization data.\n     * @dev Intended to be called internally by the contract itself as part of the timelock upgrade flow.\n     *      Performs the upgrade to the specified implementation and optionally executes additional setup logic.\n     *      Access control is enforced within the internal _callUpgradeToAndCallUUPS function via the `isInternalCall` modifier.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional initialization calldata to execute on the new implementation after the upgrade.\n     */\n    function callUpgradeToAndCallUUPS(\n        address _newImplementation,\n        bytes memory _data\n    ) public {\n        _callUpgradeToAndCallUUPS(_newImplementation, _data);\n    }\n}\n"},{"file_path":"libs/Permissioned/PermissionedView.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {PermissionedCore} from \"libs/Permissioned/PermissionedCore.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title PermissionedView\n * @author SYGNUM AG - Blockchain team 3301\n * @notice View-only Permissioned implementation that exposes permission manager address\n * @dev This contract provides read-only access to permission manager state without\n *      allowing modification. It's designed for contracts that need to query the\n *      permission manager but should not modify it directly.\n */\nabstract contract PermissionedView is PermissionedCore {\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL/PUBLIC VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns the address of the permission manager contract\n     * @return The address of the permission manager, or zero address if not set\n     */\n    function getPermissionManagerAddress() public view returns (address) {\n        return _getPermissionManagerAddress();\n    }\n}\n"},{"file_path":"libs/ERC20/ERC20.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity >=0.8.0;\n\nimport {ERC20View} from \"libs/ERC20/ERC20View.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title ERC20\n * @author SYGNUM AG - Blockchain team 3301\n * @dev Standard ERC20 implementation that extends ERC20View\n * and exposes the basic ERC20 interface functions.\n */\ncontract ERC20 is ERC20View {\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL/PUBLIC FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Approves the spender to spend tokens on behalf of the caller.\n     * @param _spender The address allowed to spend tokens\n     * @param _amount The amount of tokens the spender is allowed to spend\n     * @return A boolean indicating whether the operation succeeded\n     */\n    function approve(address _spender, uint256 _amount) public virtual returns (bool) {\n        return _approve(msg.sender, _spender, _amount);\n    }\n\n    /**\n     * @dev Transfers tokens from the caller to the recipient.\n     * @param _to The address to transfer tokens to\n     * @param _amount The amount of tokens to transfer\n     * @return A boolean indicating whether the operation succeeded\n     */\n    function transfer(address _to, uint256 _amount) public virtual returns (bool) {\n        return _transfer(msg.sender, _to, _amount);\n    }\n\n    /**\n     * @dev Transfers tokens from one address to another using the allowance mechanism.\n     * @param _from The address to transfer tokens from\n     * @param _to The address to transfer tokens to\n     * @param _amount The amount of tokens to transfer\n     * @return A boolean indicating whether the operation succeeded\n     */\n    function transferFrom(\n        address _from,\n        address _to,\n        uint256 _amount\n    ) public virtual returns (bool) {\n        return _transferFrom(_from, _to, _amount);\n    }\n\n    /**\n     * @dev EIP-2612 permit function to approve spending via signed message.\n     * @param _owner The token owner's address\n     * @param _spender The spender's address\n     * @param _value The amount of tokens to approve\n     * @param _deadline The timestamp after which the signature is no longer valid\n     * @param _v The recovery byte of the signature\n     * @param _r The first 32 bytes of the signature\n     * @param _s The second 32 bytes of the signature\n     */\n    function permit(\n        address _owner,\n        address _spender,\n        uint256 _value,\n        uint256 _deadline,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) public virtual {\n        _permit(_owner, _spender, _value, _deadline, _v, _r, _s);\n    }\n}\n"},{"file_path":"libs/UUPS/interface/IERC1967.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title IERC1967\n * @dev Interface of ERC1967 events emitted by proxies.\n *\n * These events are emitted when the proxy's implementation, admin, or beacon are changed.\n */\ninterface IERC1967 {\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     * @param implementation The address of the new implementation.\n     */\n    event Upgraded(address indexed implementation);\n}\n"},{"file_path":"libs/Permissioned/Permissioned.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\nimport {PermissionedView} from \"libs/Permissioned/PermissionedView.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title Permissioned\n * @notice Standard Permissioned implementation that extends PermissionedView\n * and exposes the public interface functions.\n * @dev Contracts inheriting from this will be able to perform role-based access control checks\n * using the requiresAuth modifier\n */\nabstract contract Permissioned is PermissionedView {\n    /* ========== EXTERNAL/PUBLIC STATE-CHANGING FUNCTIONS ========== */\n\n    /**\n     * @notice Sets the permission manager address\n     * @param _permissionManagerAddress The new permission manager address\n     */\n    function setPermissionManagerAddress(address _permissionManagerAddress) public requiresAuth {\n        _setPermissionManagerAddress(_permissionManagerAddress);\n    }\n}\n"},{"file_path":"apps/tokenization/SygToken/contracts/storage/StorageLayoutV1.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title StorageLayoutV1\n * @notice Version 1 of storage layout for SygToken\n * @dev CRITICAL: Once deployed, NEVER modify this contract!\n */\nabstract contract StorageLayoutV1 {\n    /*/////     SygToken Storage     /////*/\n\n    // Token state management\n    string public getTokenURI;\n\n    // Price feed oracle integration\n    address public getPriceFeedOracleAddress;\n}\n"},{"file_path":"libs/Permissioned/PermissionedCore.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title PermissionedCore\n * @notice Core permission implementation with slot storage pattern\n * @dev This contract provides the core role-based access control logic without exposing public functions.\n * Contracts inheriting from this will be able to perform role-based access control checks\n * using the requiresAuth modifier. This is the core implementation that should be inherited by contracts\n * that need custom permission logic.\n */\nabstract contract PermissionedCore {\n    /* ======== STATE VARIABLES ======== */\n    \n    /**\n     * @dev PERMISSIONED_CORE_STORAGE_SLOT is a constant used to locate the PermissionedStorage struct in storage for PermissionedCore.\n     * This ensures a unique storage slot for the permission manager address, minimizing collision risks with other storage variables in the contract.\n     * The value is calculated as keccak256(abi.encode(uint256(keccak256(\"PermissionedCore.PermissionedStorage\")) - 1)) & ~bytes32(uint256(0xff)).\n     */\n    bytes32 private constant PERMISSIONED_CORE_STORAGE_SLOT =\n        0x1fa5656f3245be71aa51744436d19e5d46b909e499930c5c32c93901cab52900;\n\n    /// @custom:storage-location erc7201:PermissionedCore.PermissionedStorage\n    struct PermissionedStorage {\n        address permissionManagerAddress;\n    }\n\n    /* ========== ERRORS ========== */\n\n    error Unauthorized();\n\n    /* ========== MODIFIERS ========== */\n\n    /**\n     * @notice Authorization modifier that delegates to the PermissionManager\n     * @dev Calls _isAuthorized which makes a staticcall to the PermissionManager's canCall function\n     */\n    modifier requiresAuth() {\n        _isAuthorized(msg.sender, msg.sig);\n        _;\n    }\n\n    /* ========== INTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Returns the address of the permission manager\n     * @return The address of the permission manager\n     */\n    function _getPermissionManagerAddress() internal view returns (address) {\n        PermissionedStorage storage $ = _getPermissionedStorage();\n        return $.permissionManagerAddress;\n    }\n\n    /* ========== INTERNAL INITIALIZER ========== */\n\n    /**\n     * @notice Initializes the permission system with a permission manager\n     * @dev Idempotent: Only initializes if permissionManagerAddress is not already set (default value is address(0)).\n     *      This preserves existing permission manager during upgrades - new init data will not override existing value.\n     * @param _permissionManagerAddress The address of the permission manager contract\n     */\n    function _permissioned_init(address _permissionManagerAddress) internal {\n        PermissionedStorage storage $ = _getPermissionedStorage();\n        if ($.permissionManagerAddress == address(0)) {\n            _setPermissionManagerAddress(_permissionManagerAddress);\n        }\n    }\n\n    /* ========== INTERNAL FUNCTIONS ========== */\n    \n    /**\n     * @notice Sets the permission manager address\n     * @param _permissionManagerAddress The new permission manager address\n     */\n    function _setPermissionManagerAddress(address _permissionManagerAddress) internal {\n        PermissionedStorage storage $ = _getPermissionedStorage();\n        $.permissionManagerAddress = _permissionManagerAddress;\n    }\n    \n    /**\n     * @dev Internal function to check if the caller is authorized to call a function.\n     * Reverts with Unauthorized if the caller is not authorized.\n     * @param _caller The address of the caller\n     * @param _functionSig The function signature being called\n     */\n    function _isAuthorized(address _caller, bytes4 _functionSig) internal view {\n        // Call the canCall function on the permissionManagerAddress contract\n        (bool _success, bytes memory _result) = _getPermissionManagerAddress().staticcall(\n            abi.encodeWithSignature(\"canCall(address,bytes4)\", _caller, _functionSig)\n        );\n\n        if (!_success || !abi.decode(_result, (bool))) {\n            revert Unauthorized();\n        }\n    }\n\n    /* ======== PRIVATE VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Retrieves the PermissionedStorage struct from the storage slot\n     * @dev Returns the PermissionedStorage struct\n     */\n    function _getPermissionedStorage()\n        private\n        pure\n        returns (PermissionedStorage storage $)\n    {\n        // Use assembly to simply slot the storage location into a variable\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := PERMISSIONED_CORE_STORAGE_SLOT\n        }\n    }\n}\n"},{"file_path":"libs/Pausable/PausableCore.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.28;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title PausableCore\n * @notice Core pausing implementation with slot storage pattern\n * @dev This contract provides the core pausing logic without any authorization assumptions.\n * Contracts inheriting from this will be able to pause and unpause functionality\n * using the whenNotPaused and whenPaused modifiers. This is the core implementation\n * that should be inherited by contracts that need pausing functionality.\n */\nabstract contract PausableCore {\n    /* ======== STATE VARIABLES ======== */\n\n    /**\n     * @dev PAUSABLE_CORE_STORAGE_SLOT is a constant used to locate the PausableStorage struct in storage for PausableCore.\n     * This ensures a unique storage slot for the paused state, minimizing collision risks with other storage variables in the contract.\n     * The value is calculated as keccak256(abi.encode(uint256(keccak256(\"PausableCore.PausableStorage\")) - 1)) & ~bytes32(uint256(0xff)).\n     */\n    bytes32 private constant PAUSABLE_CORE_STORAGE_SLOT =\n        0xfedd7b171e5aaf71411eb61c81513b977191128c387240284b4edb396fcbdb00;\n\n    /// @custom:storage-location erc7201:PausableCore.PausableStorage\n    struct PausableStorage {\n        bool paused;\n    }\n\n    /* ========== ERRORS ========== */\n\n    error ContractPaused();\n    error ContractNotPaused();\n\n    /* ========== EVENTS ========== */\n\n    event Paused();\n    event Unpaused();\n\n    /* ========== INTERNAL VIEW FUNCTIONS ========== */\n\n    /**\n     * @notice Returns the current pause state\n     * @return True if the contract is paused, false otherwise\n     */\n    function _isPaused() internal view returns (bool) {\n        PausableStorage storage $ = _getPausableStorage();\n        return $.paused;\n    }\n\n    /* ========== MODIFIERS ========== */\n\n    /**\n     * @notice Modifier to make a function callable only when the contract is not paused\n     * @dev Reverts with ContractPaused if the contract is paused\n     */\n    modifier whenNotPaused() {\n        if (_isPaused()) {\n            revert ContractPaused();\n        }\n        _;\n    }\n\n    /**\n     * @notice Modifier to make a function callable only when the contract is paused\n     * @dev Reverts with ContractNotPaused if the contract is not paused\n     */\n    modifier whenPaused() {\n        if (!_isPaused()) {\n            revert ContractNotPaused();\n        }\n        _;\n    }\n\n    /* ========== INTERNAL STATE-CHANGING FUNCTIONS ========== */\n\n    /**\n     * @notice Pauses the contract\n     * @dev Sets the paused state to true and emits a Paused event\n     */\n    function _pause() internal whenNotPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $.paused = true;\n        emit Paused();\n    }\n\n    /**\n     * @notice Unpauses the contract\n     * @dev Sets the paused state to false and emits an Unpaused event\n     */\n    function _unpause() internal whenPaused {\n        PausableStorage storage $ = _getPausableStorage();\n        $.paused = false;\n        emit Unpaused();\n    }\n\n    /* ======== PRIVATE VIEW/PURE FUNCTIONS ======== */\n\n    /**\n     * @notice Retrieves the PausableStorage struct from the storage slot\n     * @dev Returns the PausableStorage struct\n     */\n    function _getPausableStorage()\n        private\n        pure\n        returns (PausableStorage storage $)\n    {\n        // Use assembly to simply slot the storage location into a variable\n        // solhint-disable-next-line no-inline-assembly\n        assembly {\n            $.slot := PAUSABLE_CORE_STORAGE_SLOT\n        }\n    }\n}\n"},{"file_path":"libs/UUPS/interface/IUUPSSynchronousUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title IUUPSSynchronousUpgradeable\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Interface for synchronous UUPS upgrades that complete immediately\n * @dev Contracts implementing this interface perform upgrades synchronously,\n *      meaning the implementation is changed immediately when upgradeToAndCall is called.\n *      This is the classic UUPS upgrade pattern without any delay mechanism.\n */\ninterface IUUPSSynchronousUpgradeable {\n    /**\n     * @notice Upgrades the implementation and optionally executes a function call\n     * @dev The upgrade happens immediately when this function is called\n     * @param _newImplementation The address of the new implementation contract\n     * @param _data Optional calldata to execute after the upgrade\n     */\n    function upgradeToAndCall(address _newImplementation, bytes memory _data) external;\n\n    /**\n     * @notice Returns the current implementation address\n     * @dev Returns the address stored in the ERC-1967 implementation slot\n     * @return The address of the current implementation contract\n     */\n    function getImplementation() external view returns (address);\n}\n"},{"file_path":"libs/UUPS/interface/IERC1822.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"},{"file_path":"libs/UUPS/interface/IUUPSAsynchronousUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport \"./IUUPSSynchronousUpgradeable.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title IUUPSAsynchronousUpgradeable\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Interface for asynchronous UUPS upgrades with timelock delay\n * @dev Contracts implementing this interface perform upgrades asynchronously,\n *      meaning the upgrade is scheduled when upgradeToAndCall is called and must be\n *      executed later via executeUpgrade after the timelock delay has elapsed.\n *      This provides a safety window for stakeholders to review pending upgrades.\n */\ninterface IUUPSAsynchronousUpgradeable is IUUPSSynchronousUpgradeable {\n    /**\n     * @notice Executes a previously scheduled upgrade after the timelock delay\n     * @dev Can only be called after the timelock delay has elapsed since scheduling\n     */\n    function executeUpgrade() external;\n\n    /**\n     * @notice Cancels a scheduled upgrade operation\n     * @dev Removes the scheduled upgrade before it is executed\n     */\n    function cancelUpgrade() external;\n}\n"},{"file_path":"libs/Initializable/InitializableView.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {InitializableCore} from \"libs/Initializable/InitializableCore.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title InitializableView\n * @author SYGNUM AG - Blockchain team 3301\n * @notice View-only Initializable implementation that exposes initialization status\n * @dev This contract provides read-only access to initialization state without\n *      allowing initialization modifications. It's designed for contracts that need\n *      to query initialization status but should not modify state directly.\n */\nabstract contract InitializableView is InitializableCore {\n    /*//////////////////////////////////////////////////////////////\n                        EXTERNAL/PUBLIC VIEW FUNCTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns the initialization status of the contract\n     * @return Whether the contract has been initialized\n     */\n    function isInitialized() public view returns (bool) {\n        return _isInitialized();\n    }\n}\n"},{"file_path":"libs/UUPS/UUPSUtils.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.30;\n\nimport {IERC1967} from './interface/IERC1967.sol';\nimport {IERC1822Proxiable} from './interface/IERC1822.sol';\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title UUPSUtils\n * @notice Provides utility functions for UUPS proxies, including implementation retrieval, upgrade execution, and safety checks.\n * @dev This library offers a collection of functions designed to simplify the implementation of UUPS (Universal Upgradeable Proxy Standard) proxies.\n */\nlibrary UUPSUtils {\n    /* ======== Custom Errors ======== */\n    error ERC1967InvalidImplementation(address implementation);\n    error ERC1967NonPayable();\n    error FailedCall();\n\n    /* ======== Constants ======== */\n    /** @dev Storage slot for the implementation address (EIP-1967 standard).   \n     * bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1)\n     */\n    bytes32 internal constant IMPLEMENTATION_SLOT =\n        0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /** @dev The address of the current implementation. */\n    function getImplementation()\n        internal\n        view\n        returns (address implementation)\n    {\n        // Load the implementation address from the ERC-1967 slot.\n        // solhint-disable-next-line no-inline-assembly\n        assembly ('memory-safe') {\n            implementation := sload(IMPLEMENTATION_SLOT)\n        }\n    }\n\n    /**\n     * @notice Upgrades the implementation and optionally performs a setup call.\n     * @param _newImplementation The address of the new implementation contract.\n     * @param _data Optional initialization calldata to delegatecall to the new implementation.\n     */\n    function upgradeToAndCall(\n        address _newImplementation,\n        bytes memory _data\n    ) internal {\n        _setImplementation(_newImplementation);\n        emit IERC1967.Upgraded(_newImplementation);\n\n        if (_data.length > 0) {\n            _safeFunctionDelegateCall(_newImplementation, _data);\n        } else {\n            _checkNonPayable();\n        }\n    }\n\n    /** @notice Reverts if msg.value is not zero. */\n    function _checkNonPayable() private {\n        if (msg.value > 0) {\n            revert ERC1967NonPayable();\n        }\n    }\n\n    /**\n     * @notice Stores a new address in the ERC-1967 implementation slot.\n     * @param _newImplementation The address to store as the new implementation.\n     */\n    function _setImplementation(address _newImplementation) private {\n        _checkValidImplementation(_newImplementation);\n\n        // solhint-disable-next-line no-inline-assembly\n        assembly ('memory-safe') {\n            sstore(IMPLEMENTATION_SLOT, _newImplementation)\n        }\n    }\n\n    /**\n     * @dev Ensures the function is not called through delegatecall.\n     * @notice This function checks that the provided address is a valid UUPS implementation contract by verifying its proxiableUUID.\n     * It reverts with `UUPSUtils.ERC1967InvalidImplementation` if the provided address is not a valid implementation.\n     * @param _newImplementation The address of the new implementation contract.\n     */\n    function _checkValidImplementation(address _newImplementation) private view {\n        // Implementation address must contain code (this also covers address(0))\n        if (_newImplementation.code.length == 0) {\n            revert ERC1967InvalidImplementation(_newImplementation);\n        }\n        // Check that the new implementation exposes the proxiableUUID function and that it returns the expected value.\n        try IERC1822Proxiable(_newImplementation).proxiableUUID() returns (\n            bytes32 slot\n        ) {\n            if (slot != IMPLEMENTATION_SLOT) {\n                revert ERC1967InvalidImplementation(_newImplementation);\n            }\n        } catch {\n            revert ERC1967InvalidImplementation(_newImplementation);\n        }\n    }\n\n    /**\n     * @notice Performs a delegatecall to the target address with the given data and verifies the result.\n     * @param _target The address to delegatecall to.\n     * @param _data The data to send with the delegatecall.\n     * @return _returndata The data returned by the delegatecall.\n     * @dev Bubbles up revert reasons or custom errors if the call fails.\n     */\n    function _safeFunctionDelegateCall(\n        address _target,\n        bytes memory _data\n    ) private returns (bytes memory) {\n        // low level call is validate to prevent low-level call reentrancy or other low-level call errors\n        // solhint-disable-next-line avoid-low-level-calls\n        (bool _success, bytes memory _returndata) = _target.delegatecall(_data);\n\n        if (!_success) {\n            if (_returndata.length > 0) {\n                // solhint-disable-next-line no-inline-assembly\n                assembly ('memory-safe') {\n                    let returndata_size := mload(_returndata)\n                    revert(add(32, _returndata), returndata_size)\n                }\n            }\n            revert FailedCall();\n        }\n\n        return _returndata;\n    }\n}\n"},{"file_path":"apps/tokenization/SygToken/contracts/storage/StorageLayout.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport { StorageLayoutV1 } from \"./StorageLayoutV1.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n    * @title StorageLayout\n    * @author SYGNUM AG - Blockchain team 3301\n    * @notice This contract is used to store the state variables of SygToken.sol and all its derivatives. The storage is separated from the logic to allow for a more flexible upgradeability pattern, avoiding storage collisions\n    * @dev CRITICAL: Do NOT add variables directly to this contract!\n    * Always create a new versioned base (StorageLayoutV2, StorageLayoutV3, etc.) that inherits from the previous version.\n    *\n    * Example upgrade path:\n    * 1. Create: abstract contract StorageLayoutV2 is StorageLayoutV1 { newVar; }\n    * 2. Update: abstract contract StorageLayout is StorageLayoutV2 {}\n*/\n\nabstract contract StorageLayout is StorageLayoutV1 {\n    // ⚠️ NEVER ADD VARIABLES HERE! See @dev comment above for upgrade instructions.\n}\n"},{"file_path":"apps/tokenization/SygToken/contracts/PausableSygToken.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.30;\n\nimport {PausableCore} from \"libs/Pausable/PausableCore.sol\";\nimport {PermissionedCore} from \"libs/Permissioned/PermissionedCore.sol\";\nimport {IPausable} from \"libs/Pausable/interfaces/IPausable.sol\";\n\n/**\n * @custom:security-contact blockchain@sygnum.com\n * @title PausableSygToken\n * @author SYGNUM AG - Blockchain team 3301\n * @notice Pausable contract with role-based access control for pause/unpause operations\n * @dev This contract extends PausableCore to add authorization checks for pause/unpause operations.\n *      Only accounts with appropriate permissions can pause or unpause the contract.\n */\nabstract contract PausableSygToken is PausableCore, PermissionedCore, IPausable {\n    /* ======== EXTERNAL/PUBLIC VIEW FUNCTIONS ======== */\n\n    /**\n     * @notice Returns whether the contract is paused\n     * @return Boolean True if the contract is paused, false otherwise\n     */\n    function isPaused() public view returns (bool) {\n        return _isPaused();\n    }\n\n    /* ======== EXTERNAL/PUBLIC STATE-CHANGING FUNCTIONS ======== */\n\n    /**\n     * @notice Pauses the contract\n     * @dev Requires pauser authorization to execute\n     */\n    function pause() external requiresAuth {\n        _pause();\n    }\n\n    /**\n     * @notice Unpauses the contract\n     * @dev Requires pauser authorization to execute\n     */\n    function unpause() external requiresAuth {\n        _unpause();\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[],"name":"AlreadyUpgrading","type":"error"},{"inputs":[],"name":"ContractNotInitializedAfterUpgrade","type":"error"},{"inputs":[],"name":"ContractNotPaused","type":"error"},{"inputs":[],"name":"ContractPaused","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"IncompleteRound","type":"error"},{"inputs":[{"internalType":"uint256","name":"given","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InsufficientFunds","type":"error"},{"inputs":[],"name":"InvalidDelay","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[{"internalType":"address","name":"_oracleAddress","type":"address"}],"name":"InvalidOracle","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"InvalidUpgradeCalldata","type":"error"},{"inputs":[],"name":"NoUpgradeScheduled","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotTokenUser","type":"error"},{"inputs":[{"internalType":"bytes32","name":"operationId","type":"bytes32"}],"name":"OperationExecutionFailed","type":"error"},{"inputs":[],"name":"PermitDeadlineExpired","type":"error"},{"inputs":[{"internalType":"address","name":"_oracleAddress","type":"address"}],"name":"SameOracleAddress","type":"error"},{"inputs":[{"internalType":"string","name":"_tokenURI","type":"string"}],"name":"SameTokenURI","type":"error"},{"inputs":[],"name":"TimeLockAlreadyExist","type":"error"},{"inputs":[],"name":"TimelockDoesNotExist","type":"error"},{"inputs":[],"name":"TimelockNotReached","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[],"name":"UnAuthorizedCall","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"expectedPermissionManager","type":"address"}],"name":"UnauthorizedUpgrade","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"context","type":"address"}],"name":"Callers","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"operationId","type":"bytes32"}],"name":"Canceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"operationId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Executed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ForcedTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"actualAmountReceived","type":"uint256"}],"name":"FundsRecovered","type":"event"},{"anonymous":false,"inputs":[],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"minterBurner","type":"bool"}],"name":"MinterBurnerUpdated","type":"event"},{"anonymous":false,"inputs":[],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOracle","type":"address"},{"indexed":true,"internalType":"address","name":"newOracle","type":"address"}],"name":"PriceFeedOracleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"operationId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"eta","type":"uint256"}],"name":"Queued","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"previousTokenURI","type":"string"},{"indexed":false,"internalType":"string","name":"newTokenURI","type":"string"}],"name":"TokenURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"blacklist","type":"bool"}],"name":"TokenUserBlacklisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"tokenUserManager","type":"bool"}],"name":"TokenUserManagerUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"bool","name":"tokenUser","type":"bool"}],"name":"TokenUserUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_blacklist","type":"bool"}],"name":"blacklistTokenUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"callUpgradeToAndCallUUPS","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"executeUpgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"forcedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBundleData","outputs":[{"internalType":"bytes","name":"_bundleData","type":"bytes"},{"internalType":"uint256","name":"_updatedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPermissionManagerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPrice","outputs":[{"internalType":"int256","name":"_price","type":"int256"},{"internalType":"uint256","name":"_updatedAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceFeedDecimals","outputs":[{"internalType":"uint8[]","name":"","type":"uint8[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceFeedDescription","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPriceFeedOracleAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_operationId","type":"bytes32"}],"name":"getScheduledOperationDetails","outputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"eta","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"},{"internalType":"string","name":"_tokenURI","type":"string"},{"internalType":"address","name":"_permissionManagerAddress","type":"address"},{"internalType":"uint256","name":"_timelockDelaySeconds","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isMinterBurner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isOperator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isRoleManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSygTokenImplementation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isSystem","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isTokenUser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isTokenUserManager","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"address payable","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"recoverFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_permissionManagerAddress","type":"address"}],"name":"setPermissionManagerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_minterBurner","type":"bool"}],"name":"updateMinterBurner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newPriceFeedOracleAddress","type":"address"}],"name":"updatePricefeedOracleAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_newTokenURI","type":"string"}],"name":"updateTokenURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_tokenUser","type":"bool"}],"name":"updateTokenUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bool","name":"_tokenUserManager","type":"bool"}],"name":"updateTokenUserManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newImplementation","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}