{"sources":{"src/ProxyAdminExecutor.sol":{"content":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.26;\n\n/// @title ProxyAdminExecutor\n/// @notice Minimal implementation for the `OwnedUpgradabilityProxy` (ZeppelinOS)\n///         at 0x0BABA1Ad5bE3a5C0a66E7ac838a129Bf948f1eA4.\n/// @dev Exposes exactly one entry point, {transact}, which performs a single\n///      arbitrary call from the proxy's own context, i.e. spending the proxy's\n///      own ETH and token balances. It is:\n///\n///        - owner-gated: the caller must equal the proxy's own owner, read live\n///          from the ZeppelinOS proxy-owner storage slot. There is a single\n///          source of truth for ownership and no separate admin state to\n///          initialize, so the implementation cannot be left half-configured.\n///\n///        - non-reentrant: guarded with EIP-1153 transient storage. The guard\n///          writes NO persistent storage and is cleared automatically at the end\n///          of the transaction, so it can never collide with — or corrupt — the\n///          proxy's implementation/owner slots or any token balances.\n///\n///      This contract declares no persistent state and writes no persistent\n///      storage. The proxy's upgrade and ownership machinery — `upgradeTo`,\n///      `upgradeToAndCall`, `proxyOwner`, `transferProxyOwnership`,\n///      `implementation` — lives in the proxy contract's own bytecode (those\n///      selectors are dispatched by the proxy before its `fallback`, never by\n///      this implementation), so upgradeability and ownership are retained no\n///      matter what this implementation does. After upgrading to this contract\n///      the proxy exposes only those native proxy functions plus {transact};\n///      the old `getImplementation()` decoy no longer resolves.\ncontract ProxyAdminExecutor {\n    /// @dev keccak256(\"org.zeppelinos.proxy.owner\"): the exact slot the proxy\n    ///      reads in `proxyOwner()` / `onlyProxyOwner`.\n    bytes32 private constant _PROXY_OWNER_SLOT = 0x337c729c04082e3bdd94ba7d2b5a8a642f3a138702366a91707825373a2029ba;\n\n    /// @dev Transient (EIP-1153) reentrancy-lock slot:\n    ///      keccak256(\"proxy.admin.executor.reentrancy.lock\").\n    bytes32 private constant _REENTRANCY_LOCK_SLOT = 0x7ad6fd455985f1f61742d1f8074b916eb0b953b15044a0f9774e942ffa2cf239;\n\n    /// @notice Emitted on every successful {transact}.\n    event Transacted(address indexed to, uint256 value, bytes data, bytes result);\n\n    /// @notice Thrown when the caller is not the proxy owner.\n    error NotProxyOwner(address caller, address owner);\n\n    /// @notice Thrown on a reentrant {transact} call.\n    error Reentrancy();\n\n    /// @notice Thrown when the inner call reverts; `returndata` bubbles the reason.\n    error CallReverted(bytes returndata);\n\n    /// @notice Execute one arbitrary call from the proxy's own context.\n    /// @param to     Target address (a token contract, an EOA/contract for ETH, etc.).\n    /// @param value  Wei to send with the call, drawn from the proxy's own balance\n    ///               (plus any ETH attached to this call). Use 0 for token calls.\n    /// @param data   Calldata for the target; empty for a plain ETH transfer.\n    /// @return result Raw return data from the call.\n    function transact(address to, uint256 value, bytes calldata data) external payable returns (bytes memory result) {\n        // --- ownership gate: compare msg.sender against the proxy's owner slot ---\n        address owner;\n        assembly {\n            owner := sload(_PROXY_OWNER_SLOT)\n        }\n        if (msg.sender != owner) {\n            revert NotProxyOwner(msg.sender, owner);\n        }\n\n        // --- reentrancy gate via transient storage (no persistent writes) ---\n        uint256 locked;\n        assembly {\n            locked := tload(_REENTRANCY_LOCK_SLOT)\n        }\n        if (locked != 0) {\n            revert Reentrancy();\n        }\n        assembly {\n            tstore(_REENTRANCY_LOCK_SLOT, 1)\n        }\n\n        bool ok;\n        (ok, result) = to.call{ value: value }(data);\n        if (!ok) {\n            revert CallReverted(result);\n        }\n\n        // Clear the transient lock (also auto-discarded at end of transaction).\n        assembly {\n            tstore(_REENTRANCY_LOCK_SLOT, 0)\n        }\n\n        emit Transacted(to, value, data, result);\n    }\n}\n"}},"matchId":"39689692","creationMatch":"exact_match","runtimeMatch":"exact_match","verifiedAt":"2026-07-06T05:33:19Z","match":"exact_match","chainId":"1","address":"0xB40973B8bffDe1553AE05DE4b298610524E1c37a"}