Artifacts
DISCLAIMER // NFA // DYOR
This analysis is based on decompiled bytecode — the contract source code is not verified on Etherscan. Function names, parameter types, and internal logic are inferred from selector matching, transaction input decoding, and event log analysis. We are not smart contract security experts. This document should not be considered a comprehensive security audit or financial advice. Always verify critical information independently.
⊙ generated by robots | curated by humans
| METADATA | |
|---|---|
| Contract Address | 0x99c96efF...Ab2dCC (etherscan) |
| Network | Ethereum Mainnet |
| Analysis Date | 2026-03-29 |
Overview
This document contains raw analysis artifacts including function selector mappings, event signatures, storage slot snapshots, transaction summaries, and verification commands. All artifacts are preserved for transparency and independent verification.
Artifact Location: /artifacts/0x99c96efF...Ab2dCC/
Reconstructed Solidity Source
Based on bytecode analysis, transaction patterns, storage slot reads, and event log decoding, the contract logic appears to follow this structure:
// SPDX-License-Identifier: UNLICENSED
// WARNING: Reconstructed from bytecode - NOT the original source code
// 16 function selectors remain unidentified and are not represented here
pragma solidity ^0.8.0;
interface IWETH {
function deposit() external payable;
function approve(address spender, uint256 amount) external returns (bool);
}
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params)
external payable returns (uint256 amountOut);
}
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
}
contract SentinelMitesVault {
//////////////////////////////////////////////////////////////
// STRUCTS
//////////////////////////////////////////////////////////////
struct Vault {
uint256 profit; // Accumulated profit (wei)
uint256 depositAmount; // Original ETH deposit (wei)
uint256 sentAmount; // Declared SENT token amount
uint256 tradeCountBuy; // Number of buy trades
uint256 tradeCountSell; // Number of sell trades
uint256 active; // 1 = active, 0 = inactive
uint256 depositTimestamp; // When deposit was made
uint256 lastTradeTimestamp; // When last trade executed
address lastTradeToken; // Last traded token address
uint256 lastTradeAmount; // Last trade token amount
uint256 accumulatedValue; // Accumulated ETH value
}
//////////////////////////////////////////////////////////////
// STORAGE
//////////////////////////////////////////////////////////////
// Slot 0
address public owner;
// Slot 1
uint256 private _active; // 1 = active
// Slot 2 (empty/unused)
// Slot 3
uint256 private _userCount;
// Slot 4 (empty/unused)
// Slot 5
address public keeper;
// Slot 6
address public feeRecipient;
// Slot 7
uint256 private _depositFee; // 0.01 ETH stored; 0.005 ETH observed
// Slot 8
uint256 private _totalDeposits;
// Slot 9
uint256 public totalTradesExecuted;
// Slot 10
uint256 public totalProfitGenerated;
// Slot 11
uint256 private _totalOperations;
// Slot 14
uint256 private _sentThreshold; // 10,000 SENT
// Dynamic storage
address[] public users;
mapping(address => bool) public isTracked;
mapping(address => mapping(uint256 => Vault)) public vaults;
// Immutable references (set in constructor)
address public immutable weth;
address public immutable swapRouter;
address public immutable sentToken;
address public presaleContract;
// Constants
uint256 public constant MAX_TRADE_ETH = 0.5 ether;
uint256 public constant SWAP_DEADLINE_BUFFER = 60;
//////////////////////////////////////////////////////////////
// EVENTS
//////////////////////////////////////////////////////////////
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
event VaultDeposit(
address indexed user,
uint256 indexed vaultId,
uint256 ethAmount,
uint256 sentAmount
);
event TradeExecuted(
address indexed user,
uint256 indexed vaultId,
address indexed token,
uint256 ethAmount,
uint256 tokenAmount,
uint256 direction,
uint256 timestamp
);
event TopUpOrWithdraw(
address indexed user,
uint256 indexed vaultId,
uint256 amount
);
//////////////////////////////////////////////////////////////
// MODIFIERS
//////////////////////////////////////////////////////////////
modifier onlyOwner() {
require(msg.sender == owner, "Not owner");
_;
}
modifier onlyKeeper() {
require(msg.sender == keeper, "Not keeper");
_;
}
//////////////////////////////////////////////////////////////
// CONSTRUCTOR
//////////////////////////////////////////////////////////////
constructor(
address _weth,
address _swapRouter,
address _sentToken,
address _feeRecipient,
address _keeper
) {
owner = msg.sender;
weth = _weth;
swapRouter = _swapRouter;
sentToken = _sentToken;
feeRecipient = _feeRecipient;
keeper = _keeper;
_active = 1;
emit OwnershipTransferred(address(0), msg.sender);
}
//////////////////////////////////////////////////////////////
// USER FUNCTIONS
//////////////////////////////////////////////////////////////
/// @notice Deposit ETH to create a new vault position
/// @param sentAmount Declared SENT token holdings
/// @dev Does NOT transfer SENT — only records the declared amount
function deposit(uint256 sentAmount) external payable {
require(msg.value > 0, "No ETH sent");
// Check SENT balance if declared
if (sentAmount > 0) {
uint256 balance = IERC20(sentToken).balanceOf(msg.sender);
require(balance >= sentAmount, "Insufficient SENT balance");
}
// Send fee to recipient
uint256 fee = 0.005 ether; // Observed fee amount
payable(feeRecipient).transfer(fee);
// Register user if new
if (!isTracked[msg.sender]) {
isTracked[msg.sender] = true;
users.push(msg.sender);
_userCount++;
}
// Create vault
uint256 vaultId = _getNextVaultId(msg.sender);
uint256 netDeposit = msg.value - fee;
vaults[msg.sender][vaultId] = Vault({
profit: 0,
depositAmount: netDeposit,
sentAmount: sentAmount,
tradeCountBuy: 0,
tradeCountSell: 0,
active: 1,
depositTimestamp: block.timestamp,
lastTradeTimestamp: 0,
lastTradeToken: address(0),
lastTradeAmount: 0,
accumulatedValue: 0
});
_totalDeposits += netDeposit;
_totalOperations++;
emit VaultDeposit(msg.sender, vaultId, netDeposit, sentAmount);
}
/// @notice Top up an existing vault
function topUp(uint256 vaultId, uint256 /* unknown */) external payable {
require(msg.value > 0, "No ETH sent");
// Update vault deposit amount and emit event
vaults[msg.sender][vaultId].depositAmount += msg.value;
_totalOperations++;
emit TopUpOrWithdraw(msg.sender, vaultId, msg.value);
}
/// @notice Withdraw full vault balance
function withdraw(uint256 vaultId) external {
Vault storage vault = vaults[msg.sender][vaultId];
require(vault.active == 1, "Vault not active");
uint256 amount = vault.depositAmount + vault.profit;
vault.active = 0;
vault.depositAmount = 0;
payable(msg.sender).transfer(amount);
_totalOperations++;
emit TopUpOrWithdraw(msg.sender, vaultId, amount);
}
/// @notice Withdraw partial amount from vault
function withdrawPartial(uint256 vaultId, uint256 amount) external {
Vault storage vault = vaults[msg.sender][vaultId];
require(vault.active == 1, "Vault not active");
require(vault.depositAmount >= amount, "Insufficient balance");
vault.depositAmount -= amount;
payable(msg.sender).transfer(amount);
_totalOperations++;
emit TopUpOrWithdraw(msg.sender, vaultId, amount);
}
//////////////////////////////////////////////////////////////
// KEEPER FUNCTIONS
//////////////////////////////////////////////////////////////
/// @notice Execute a trade on behalf of a user vault
/// @dev Wraps ETH to WETH and swaps via Uniswap V3
function executeTrade(
address user,
uint256 vaultId,
address targetToken,
uint24 feeTier,
uint256 ethAmount,
uint256 minTokenOut,
uint256 direction
) external onlyKeeper {
Vault storage vault = vaults[user][vaultId];
require(vault.active == 1, "Vault not active");
require(ethAmount <= MAX_TRADE_ETH, "Exceeds max trade");
// Wrap ETH to WETH
IWETH(weth).deposit{value: ethAmount}();
IWETH(weth).approve(swapRouter, ethAmount);
// Execute swap via Uniswap V3
uint256 amountOut = ISwapRouter(swapRouter).exactInputSingle(
ISwapRouter.ExactInputSingleParams({
tokenIn: weth,
tokenOut: targetToken,
fee: feeTier,
recipient: address(this),
deadline: block.timestamp + SWAP_DEADLINE_BUFFER,
amountIn: ethAmount,
amountOutMinimum: minTokenOut,
sqrtPriceLimitX96: 0
})
);
// Update vault state
vault.tradeCountBuy++;
vault.lastTradeToken = targetToken;
vault.lastTradeAmount = amountOut;
vault.lastTradeTimestamp = block.timestamp;
// Update globals
totalTradesExecuted++;
_totalOperations++;
// totalProfitGenerated updated via internal calculation
emit TradeExecuted(
user, vaultId, targetToken,
ethAmount, amountOut, direction, block.timestamp
);
}
/// @notice Close a trade position (sell tokens back to ETH)
function closeTrade(
address user,
uint256 vaultId,
uint24 feeTier,
uint256 amount,
uint256 direction
) external onlyKeeper {
Vault storage vault = vaults[user][vaultId];
require(vault.active == 1, "Vault not active");
// Reverse swap: token → WETH → ETH
// (implementation details inferred from transaction patterns)
vault.tradeCountSell++;
vault.lastTradeTimestamp = block.timestamp;
totalTradesExecuted++;
_totalOperations++;
}
//////////////////////////////////////////////////////////////
// ADMIN FUNCTIONS
//////////////////////////////////////////////////////////////
function setKeeper(address newKeeper) external onlyOwner {
keeper = newKeeper;
}
function setFeeRecipient(address newFeeRecipient) external onlyOwner {
feeRecipient = newFeeRecipient;
}
function setPresaleContract(address _presale) external onlyOwner {
presaleContract = _presale;
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "Zero address");
address oldOwner = owner;
owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
//////////////////////////////////////////////////////////////
// VIEW FUNCTIONS
//////////////////////////////////////////////////////////////
function getUserCount() external view returns (uint256) {
return _userCount;
}
function getUserTier(address user, uint256 vaultId)
external view returns (uint256)
{
// Tier calculation based on SENT amount and vault state
// Implementation details unclear from bytecode
return 1; // Placeholder
}
function getEligibility(address user)
external view returns (uint256, uint256, uint256, uint256)
{
uint256 sentBalance = IERC20(sentToken).balanceOf(user);
// Returns eligibility flags + SENT balance + eligible flag
// Exact logic unclear from bytecode
return (0, 0, sentBalance, sentBalance >= _sentThreshold ? 1 : 0);
}
function getStats()
external view returns (
uint256 totalDeposits,
uint256 trades,
uint256 profit,
uint256 userCount,
uint256 operations
)
{
return (
_totalDeposits,
totalTradesExecuted,
totalProfitGenerated,
_userCount,
_totalOperations
);
}
//////////////////////////////////////////////////////////////
// INTERNAL
//////////////////////////////////////////////////////////////
function _getNextVaultId(address user) internal view returns (uint256) {
// Returns next available vault index for user
// Implementation inferred from sequential vault IDs
return 0; // Simplified — actual logic tracks per-user count
}
}
Function Selector Mapping
Complete mapping of all 44 function selectors extracted from bytecode dispatch table:
# Matched Selectors (28)
0x1360003f => totalProfitGenerated() view returns (uint256)
0x2e1a7d4d => withdraw(uint256)
0x365b98b2 => users(uint256) view returns (address)
0x3fc8cef3 => weth() view returns (address)
0x444cef88 => sentToken() view returns (address)
0x46904840 => feeRecipient() view returns (address)
0x4af9daa8 => deposit(uint256) payable [custom - inferred]
0x63d9df85 => presaleContract() view returns (address)
0x66c91379 => withdrawPartial(uint256,uint256)
0x748747e6 => setKeeper(address)
0x7bbfc69e => vaults(address,uint256) view returns (...)
0x8da5cb5b => owner() view returns (address)
0xa8c94d1b => isTracked(address) view returns (bool)
0xa9bbd114 => setPresaleContract(address)
0xaced1661 => keeper() view returns (address)
0xb5cb15f7 => getUserCount() view returns (uint256)
0xc31c9c07 => swapRouter() view returns (address)
0xc59d4847 => getStats() view returns (uint256,uint256,uint256,uint256,uint256)
0xcbb117a3 => SWAP_DEADLINE_BUFFER() view returns (uint256)
0xcbe9e55e => getUserTier(address,uint256) view returns (uint256)
0xd0fd9cad => MAX_TRADE_ETH() view returns (uint256)
0xd2a037ab => totalTradesExecuted() view returns (uint256)
0xd86938ba => closeTrade(address,uint256,uint24,uint256,uint256) [custom - inferred]
0xdca11ab8 => getEligibility(address) view returns (uint256,uint256,uint256,uint256)
0xde643a71 => topUp(uint256,uint256)
0xe74b981b => setFeeRecipient(address)
0xea0ccfae => executeTrade(address,uint256,address,uint24,uint256,uint256,uint256) [custom - inferred]
0xf2fde38b => transferOwnership(address)
0xf8b8790f => (unknown) view returns (uint256) [returns constant 1000e18]
# Unmatched Selectors (16)
0x06e20080 => UNKNOWN
0x1a519533 => UNKNOWN
0x553a9a93 => UNKNOWN
0x5b451dff => UNKNOWN
0x6f747452 => UNKNOWN
0x8b4c6df1 => UNKNOWN
0x8c07635a => UNKNOWN
0xa0aca335 => UNKNOWN
0xae1e9118 => UNKNOWN
0xb3051d6e => UNKNOWN
0xbda962d5 => UNKNOWN
0xc84d5389 => UNKNOWN
0xc9b6e079 => UNKNOWN
0xda91a291 => UNKNOWN
0xe7ba4fe5 => UNKNOWN
0xe87ce5ee => UNKNOWN
0xf1cb0216 => UNKNOWN
Event Signatures
Event topic hashes observed on-chain:
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0
=> OwnershipTransferred(address indexed previousOwner, address indexed newOwner)
Count: 1
0xed9d3a11a7d707b642c8dfb02f78d4eca3b83394e0ff1065c8850d554e9b1cab
=> VaultDeposit(address indexed user, uint256 indexed vaultId, uint256 ethAmount, uint256 sentAmount)
Count: 28
0x0134eeeac969585050b0bbc7656999d77545758ef6f7739e46ef45752468a59b
=> TradeExecuted(address indexed user, uint256 indexed vaultId, address indexed token, uint256 ethAmount, uint256 tokenAmount, uint256 direction, uint256 timestamp)
Count: 13
0x91ede45f04a37a7c170f5c1207df3b6bc748dc1e04ad5e917a241d0f52feada3
=> TopUpOrWithdraw(address indexed user, uint256 indexed vaultId, uint256 amount, ...)
Count: 8
Storage Snapshot
Storage slots read on 2026-03-29:
Slot 0: 0x0000000000000000000000009fbcc72a6bc74d0060e14fe8b8f4b7ccfa63ea03 # owner
Slot 1: 0x0000000000000000000000000000000000000000000000000000000000000001 # active flag
Slot 2: 0x0000000000000000000000000000000000000000000000000000000000000000 # (empty)
Slot 3: 0x0000000000000000000000000000000000000000000000000000000000000055 # userCount (85)
Slot 4: 0x0000000000000000000000000000000000000000000000000000000000000000 # (empty)
Slot 5: 0x0000000000000000000000009fbcc72a6bc74d0060e14fe8b8f4b7ccfa63ea03 # keeper
Slot 6: 0x00000000000000000000000090ff7835f01537bb98d5835e4917f91c1efceead # feeRecipient
Slot 7: 0x000000000000000000000000000000000000000000000000002386f26fc10000 # fee (0.01 ETH)
Slot 8: 0x000000000000000000000000000000000000000000000000431de5396b62facc # totalDeposits
Slot 9: 0x00000000000000000000000000000000000000000000000000000000000000a2 # trades (162)
Slot 10: 0x000000000000000000000000000000000000000000000000003ec87442517ed7 # profit (~0.018 ETH)
Slot 11: 0x00000000000000000000000000000000000000000000000000000000000000d7 # operations (215)
Slot 14: 0x00000000000000000000000000000000000000000000021e19e0c9bab2400000 # threshold (10000 tokens)
Transaction Summary
| METHOD ID | FUNCTION | COUNT | CALLER | VALUE |
|---|---|---|---|---|
| 0x60e03461 | (creation) | 1 | Deployer | 0 |
| 0x4af9daa8 | deposit | 47 | Various users | 0.01-0.25 ETH |
| 0xea0ccfae | executeTrade | 26 | Owner/Keeper | 0 |
| 0xde643a71 | topUp | 20 | Various users | 0.005-0.055 ETH |
| 0xd86938ba | closeTrade | 5 | Owner/Keeper | 0 |
| 0x2e1a7d4d | withdraw | 2 | Users | 0 |
Total Transactions: 101 (all successful, no errors)
Sample Vault Decode
Vault data for first depositor (0x5db50b4a..., vault 0):
Field 0 (profit): 0.016013 ETH
Field 1 (deposit): 0.070 ETH
Field 2 (SENT amount): 500 SENT
Field 3 (buy trades): 7
Field 4 (sell trades): 7
Field 5 (active): 1 (true)
Field 6 (deposit time): 2026-03-28 12:34:47 UTC
Field 7 (last trade time): 2026-03-29 03:18:59 UTC
Field 8 (last trade token): 0xdAC17F95...831EC7 (USDT)
Field 9 (last trade amt): 109.00 USDT
Field 10 (accumulated): 0.054118 ETH
Internal Transaction Patterns
Two distinct internal transaction destinations observed:
Fee Recipient (0x90fF7835...fceEAD):
- Always receives exactly 0.005 ETH
- Triggered during deposit transactions
- 7+ instances observed in first 20 internal txs
WETH (0xC02aaA39...756Cc2):
- Receives varying ETH amounts (0.008 - 0.224 ETH)
- Triggered during executeTrade transactions
- Represents ETH wrapping before Uniswap swap
Sample Trade Execution Receipt
Transaction: 0x1cdd8480bdc3b31c8f21466238e1099851a645baa5c8ce61e128af60b665e251
| STEP | EVENT | DETAILS |
|---|---|---|
| 1 | WETH Deposit | 0.04 ETH wrapped |
| 2 | WETH Approval | Router approved for 0.04 WETH |
| 3 | USDC Transfer | 81.16 USDC received from pool |
| 4 | WETH Transfer | 0.04 WETH sent to pool |
| 5 | Uniswap Swap | Pool event recorded |
| 6 | TradeExecuted | Contract event: user, vault, USDC, 0.04 ETH, 81.16 USDC, direction=1 |
External Contract References
| CONTRACT | ADDRESS | STATUS |
|---|---|---|
| Owner/Keeper | 0x9fBcc72A6bc74D0060e14Fe8b8f4b7CcFA63eA03 |
EOA |
| Fee Recipient | 0x90fF7835f01537bB98d5835E4917F91c1EfcEEAD |
EOA |
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
☑ Verified |
| Uniswap V3 Router | 0xe592427A0AEce92De3Edee1F18E0157C05861564 |
☑ Verified |
| SENT Token | 0xe88BaAB9192a3cb2C0a50182Ab911506E5aDc304 |
☒ See analysis |
| WETH/USDC Pool | 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640 |
☑ Verified |
| Presale Contract | 0x0000000000000000000000000000000000000000 |
Not Set |
Verification Commands
Basic Contract Info
# Get contract bytecode size
cast code 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC | wc -c
# Check contract balance
cast balance 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC --ether
# Check if contract exists
cast codesize 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC
View Function Calls
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "owner()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "keeper()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "feeRecipient()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "weth()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "swapRouter()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "sentToken()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "getStats()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "getUserCount()"
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "vaults(address,uint256)" <ADDRESS> <ID>
cast call 0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC "getEligibility(address)" <ADDRESS>
Selector Verification
cast sig "topUp(uint256,uint256)" # 0xde643a71
cast sig "withdraw(uint256)" # 0x2e1a7d4d
cast sig "owner()" # 0x8da5cb5b
cast sig "transferOwnership(address)" # 0xf2fde38b
cast sig "getUserCount()" # 0xb5cb15f7
External Links
Raw Data Files
The following files are stored in /artifacts/0x99c96efF...Ab2dCC/:
| FILE | DESCRIPTION |
|---|---|
| bytecode.txt | Full contract bytecode (hex, 19.8 KB) |
Analysis Metadata
{
"contract_address": "0x99c96efFDbd52C6868CB500f10350DF444Ab2dCC",
"network": "ethereum-mainnet",
"analysis_date": "2026-03-29",
"analyst": "Claude Opus 4.6",
"analysis_method": "Bytecode disassembly + transaction pattern analysis + event log decoding",
"verification_status": "unverified",
"total_functions": 44,
"matched_functions": 28,
"unmatched_functions": 16,
"admin_functions": 4,
"keeper_functions": 2,
"user_functions": 4,
"view_functions": 18,
"events": 4,
"storage_slots_identified": 11,
"external_dependencies": 3,
"deployment_block": 24755545,
"deployment_timestamp": "2026-03-28T10:43:35Z",
"transaction_count": 101,
"user_count": 85,
"total_trades": 162,
"eth_balance": "4.836 ETH",
"token_cost": "75 tok"
}
Disclaimer
All artifacts in this document are based on bytecode analysis of an unverified contract. They represent our best interpretation of the contract's behavior but may not perfectly match the original source code. Variable names, function logic, and internal structures are inferred and should not be considered authoritative.