{"sources":{"@openzeppelin/contracts/access/AccessControl.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.6.0) (access/AccessControl.sol)\n\npragma solidity ^0.8.20;\n\nimport {IAccessControl} from \"./IAccessControl.sol\";\nimport {Context} from \"../utils/Context.sol\";\nimport {ERC165} from \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```solidity\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```solidity\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}\n * to enforce additional security measures for this role.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address account => bool) hasRole;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 role => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with an {AccessControlUnauthorizedAccount} error including the required role.\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role);\n        _;\n    }\n\n    /// @inheritdoc ERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view virtual returns (bool) {\n        return _roles[role].hasRole[account];\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`\n     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.\n     */\n    function _checkRole(bytes32 role) internal view virtual {\n        _checkRole(role, _msgSender());\n    }\n\n    /**\n     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`\n     * is missing `role`.\n     */\n    function _checkRole(bytes32 role, address account) internal view virtual {\n        if (!hasRole(role, account)) {\n            revert AccessControlUnauthorizedAccount(account, role);\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been revoked `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) public virtual {\n        if (callerConfirmation != _msgSender()) {\n            revert AccessControlBadConfirmation();\n        }\n\n        _revokeRole(role, callerConfirmation);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    /**\n     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleGranted} event.\n     */\n    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (!hasRole(role, account)) {\n            _roles[role].hasRole[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Attempts to revoke `role` from `account` and returns a boolean indicating if `role` was revoked.\n     *\n     * Internal function without access restriction.\n     *\n     * May emit a {RoleRevoked} event.\n     */\n    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {\n        if (hasRole(role, account)) {\n            _roles[role].hasRole[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"},"@openzeppelin/contracts/access/IAccessControl.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (access/IAccessControl.sol)\n\npragma solidity >=0.8.4;\n\n/**\n * @dev External interface of AccessControl declared to support ERC-165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev The `account` is missing a role.\n     */\n    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);\n\n    /**\n     * @dev The caller of a function is not the expected one.\n     *\n     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\n     */\n    error AccessControlBadConfirmation();\n\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted to signal this.\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call. This account bears the admin role (for the granted role).\n     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `callerConfirmation`.\n     */\n    function renounceRole(bytes32 role, address callerConfirmation) external;\n}\n"},"@openzeppelin/contracts/interfaces/IERC5313.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC5313.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface for the Light Contract Ownership Standard.\n *\n * A standardized minimal interface required to identify an account that controls a contract\n */\ninterface IERC5313 {\n    /**\n     * @dev Gets the address of the owner.\n     */\n    function owner() external view returns (address);\n}\n"},"@openzeppelin/contracts/utils/Context.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n\n    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},"@openzeppelin/contracts/utils/introspection/ERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},"@openzeppelin/contracts/utils/introspection/IERC165.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)\n\npragma solidity >=0.4.16;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},"contracts/XGLDExchangeRate.sol":{"content":"// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport { SingleAdminAccessControl } from \"./libraries/SingleAdminAccessControl.sol\";\nimport { IXGLDExchangeRate } from \"./interfaces/IXGLDExchangeRate.sol\";\n\n/// @notice Shared XGLD/XAUT exchange rate used by BSC minting and redemption.\ncontract XGLDExchangeRate is IXGLDExchangeRate, SingleAdminAccessControl {\n    bytes32 public constant RATE_UPDATER_ROLE = keccak256(\"RATE_UPDATER_ROLE\");\n    uint256 public constant RATE_PRECISION = 1_000_000;\n    uint256 public constant BPS_DENOMINATOR = 10_000;\n    uint256 public constant MAX_RATE_INCREASE_BPS = 5;\n\n    uint256 public override exchangeRate;\n    uint256 public lastUpdatedAt;\n\n    event ExchangeRateUpdated(uint256 oldRate, uint256 newRate, uint256 updatedAt);\n\n    error ZeroAddress();\n    error RateMustBePositive();\n    error RateMustIncrease();\n    error RateIncreaseTooLarge(uint256 requestedIncrease, uint256 maxIncrease);\n\n    constructor(uint256 initialRate, address admin) {\n        if (initialRate == 0) revert RateMustBePositive();\n        if (admin == address(0)) revert ZeroAddress();\n\n        exchangeRate = initialRate;\n        _grantRole(DEFAULT_ADMIN_ROLE, admin);\n    }\n\n    /// @notice Updates the active exchange rate. Caller must have RATE_UPDATER_ROLE.\n    /// @dev Rate can only increase by at most 5 bps per update.\n    function setExchangeRate(uint256 newRate) external onlyRole(RATE_UPDATER_ROLE) {\n        if (newRate == 0) revert RateMustBePositive();\n\n        uint256 oldRate = exchangeRate;\n        if (newRate <= oldRate) revert RateMustIncrease();\n\n        uint256 increase = newRate - oldRate;\n        uint256 maxIncrease = oldRate * MAX_RATE_INCREASE_BPS / BPS_DENOMINATOR;\n        if (increase > maxIncrease) revert RateIncreaseTooLarge(increase, maxIncrease);\n\n        exchangeRate = newRate;\n        lastUpdatedAt = block.timestamp;\n\n        emit ExchangeRateUpdated(oldRate, newRate, block.timestamp);\n    }\n}\n"},"contracts/interfaces/ISingleAdminAccessControl.sol":{"content":"// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\ninterface ISingleAdminAccessControl {\n    error InvalidAdminChange();\n    error NotPendingAdmin();\n\n    event AdminTransferred(address indexed oldAdmin, address indexed newAdmin);\n    event AdminTransferRequested(address indexed oldAdmin, address indexed newAdmin);\n}\n"},"contracts/interfaces/IXGLDExchangeRate.sol":{"content":"// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\ninterface IXGLDExchangeRate {\n    function exchangeRate() external view returns (uint256);\n}\n"},"contracts/libraries/SingleAdminAccessControl.sol":{"content":"// SPDX-License-Identifier: GPL-3.0\npragma solidity ^0.8.28;\n\nimport { AccessControl } from \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport { IERC5313 } from \"@openzeppelin/contracts/interfaces/IERC5313.sol\";\nimport \"../interfaces/ISingleAdminAccessControl.sol\";\n\nabstract contract SingleAdminAccessControl is IERC5313, ISingleAdminAccessControl, AccessControl {\n    address private _currentDefaultAdmin;\n    address private _pendingDefaultAdmin;\n\n    modifier notAdmin(bytes32 role) {\n        if (role == DEFAULT_ADMIN_ROLE) revert InvalidAdminChange();\n        _;\n    }\n\n    /// @notice Two-step admin transfer: step 1 — propose new admin.\n    function transferAdmin(address newAdmin) external onlyRole(DEFAULT_ADMIN_ROLE) {\n        if (newAdmin == msg.sender || newAdmin == address(0)) revert InvalidAdminChange();\n        _pendingDefaultAdmin = newAdmin;\n        emit AdminTransferRequested(_currentDefaultAdmin, newAdmin);\n    }\n\n    /// @notice Two-step admin transfer: step 2 — pending admin accepts.\n    function acceptAdmin() external {\n        if (msg.sender != _pendingDefaultAdmin) revert NotPendingAdmin();\n        _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n    }\n\n    function grantRole(bytes32 role, address account) public override onlyRole(DEFAULT_ADMIN_ROLE) notAdmin(role) {\n        _grantRole(role, account);\n    }\n\n    function revokeRole(bytes32 role, address account) public override onlyRole(DEFAULT_ADMIN_ROLE) notAdmin(role) {\n        _revokeRole(role, account);\n    }\n\n    function renounceRole(bytes32 role, address account) public virtual override notAdmin(role) {\n        super.renounceRole(role, account);\n    }\n\n    function owner() public view virtual returns (address) {\n        return _currentDefaultAdmin;\n    }\n\n    function _grantRole(bytes32 role, address account) internal override returns (bool) {\n        if (role == DEFAULT_ADMIN_ROLE) {\n            emit AdminTransferred(_currentDefaultAdmin, account);\n            _revokeRole(DEFAULT_ADMIN_ROLE, _currentDefaultAdmin);\n            _currentDefaultAdmin = account;\n            delete _pendingDefaultAdmin;\n        }\n        return super._grantRole(role, account);\n    }\n}\n"}},"abi":[{"type":"constructor","inputs":[{"name":"initialRate","type":"uint256","internalType":"uint256"},{"name":"admin","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"name":"AccessControlBadConfirmation","type":"error","inputs":[]},{"name":"AccessControlUnauthorizedAccount","type":"error","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"name":"InvalidAdminChange","type":"error","inputs":[]},{"name":"NotPendingAdmin","type":"error","inputs":[]},{"name":"RateIncreaseTooLarge","type":"error","inputs":[{"name":"requestedIncrease","type":"uint256","internalType":"uint256"},{"name":"maxIncrease","type":"uint256","internalType":"uint256"}]},{"name":"RateMustBePositive","type":"error","inputs":[]},{"name":"RateMustIncrease","type":"error","inputs":[]},{"name":"ZeroAddress","type":"error","inputs":[]},{"name":"AdminTransferRequested","type":"event","inputs":[{"name":"oldAdmin","type":"address","indexed":true,"internalType":"address"},{"name":"newAdmin","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"AdminTransferred","type":"event","inputs":[{"name":"oldAdmin","type":"address","indexed":true,"internalType":"address"},{"name":"newAdmin","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"ExchangeRateUpdated","type":"event","inputs":[{"name":"oldRate","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"newRate","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"updatedAt","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"name":"RoleAdminChanged","type":"event","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"name":"RoleGranted","type":"event","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"RoleRevoked","type":"event","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"name":"BPS_DENOMINATOR","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"DEFAULT_ADMIN_ROLE","type":"function","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"name":"MAX_RATE_INCREASE_BPS","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"RATE_PRECISION","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"RATE_UPDATER_ROLE","type":"function","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"name":"acceptAdmin","type":"function","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"name":"exchangeRate","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"getRoleAdmin","type":"function","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"name":"grantRole","type":"function","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"hasRole","type":"function","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"lastUpdatedAt","type":"function","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"name":"owner","type":"function","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"name":"renounceRole","type":"function","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"revokeRole","type":"function","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"setExchangeRate","type":"function","inputs":[{"name":"newRate","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"name":"supportsInterface","type":"function","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"name":"transferAdmin","type":"function","inputs":[{"name":"newAdmin","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"}],"matchId":"32101216","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-06-11T02:08:02Z","match":"exact_match","chainId":"56","address":"0x7Bbe7FDCd6BdFFd7F767a9531b6210b87b3e46E7"}