SOURCE AVAILABLEDistribution implementation
The published implementation fixes 30% holder ETH, 30% market buyback and burn, and 40% team development. No owner reserve-sweep function is implemented. Mainnet is not live. The corrected source is deployed and explorer-verified on public testnet. Inspect test transactions ↗
LOCAL TESTS PASSED38 Solidity + 34 operational tests
Exact funding, reserves, Merkle entitlements, duplicate protection, rejecting recipients, retries, late claims and separate buybacks. The expanded run includes 3 fuzz tests with 12,288 seeds in total; 4,096 sequences check 96 interleaved operations each against an independent cash model. Also covers 2,000 integer allocation scenarios and snapshot supply, archive, finality and reorg failures. Local doubles exercise faults. Public-testnet acceptance additionally uses an actual Uniswap V2 pool; production market compatibility remains unverified.
MAINNET NOT LIVEToken, payouts and buybacks
No official VELLIN token or mainnet distribution address exists yet. Public-testnet transfers use test assets and controlled wallets; they are not live holder distributions. Independent review, actual token/market integration, operating wallets, eligibility exclusions and reconciled daily net-profit input remain pending. Distribution mechanism ↗
INDEXER RECONSTRUCTIONTrading after 27 September
Wallet 4 has a dated ledger of 477 closed ETH positions through 15 October 2026, 11:29:07 UTC. Entries, exits, fees, losses, source CSV and the parser are public. This is not a complete current-wallet net-profit figure or an independent full-chain audit.
Inspect the full W4 journal ↗
PUBLIC TESTNET PASSEDPayments, buyback and burn.
Corrected source deployed and explorer-verified on chain46630. Exact 30/30/40 settlement, rejecting-recipient recovery, duplicate protection, slippage rejection and an actual Uniswap V2 swap checked on chain. Test funds only.
Addresses, transactions and evidence ↗
DAILY AUTOMATIONSeparate UTC-day acceptance.
Immediate transactions used current-block test fixtures. The real closed-day snapshot and production settlement run have separate acceptance status.
Daily acceptance status ↗
SIGNATURE NOT PUBLISHEDWallet control & autonomy
Matching runtime bytecode and observed transactions support strategy continuity, not real-world operator identity or proof of the offchain scheduler. No wallet-control signature has been published. Autonomous operation is not independently established by transaction frequency alone.
A control proof must name this domain, chain 4663, wallet, purpose, issue date and expiry, then carry a valid signature from that wallet. No key should ever be provided to this website. A signature would prove control only; it would not audit P&L or guarantee future payouts.
Runtime comparison and creation evidence ↗
REPORTING SCOPEThe archived book
The 27 September export contains 9,119 closed positions. Its roughly 52.4 ETH reconstructed total has incomplete fee coverage and has not been independently validated end to end. It is neither current net profit nor distributed income. The home chart now uses the rebuilt all-wallet ETH history through 15 October, with accounting scope and remaining cost gaps disclosed. Archive checks ↗
Read VellinDistributor.sol here
// SPDX-License-Identifier: MIT
pragma solidity 0.8.30;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import {Math} from "@openzeppelin/contracts/utils/math/Math.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IArbSysBlockNumber {
function arbBlockNumber() external view returns (uint256);
}
interface IV2BuybackRouter {
function WETH() external view returns (address);
function swapExactETHForTokensSupportingFeeOnTransferTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable;
}
/// @notice Fully funded daily ETH allocations; reporter-trusted accounting and snapshots.
/// @dev No token issuance, custody of holder tokens, upgrade proxy, or reserve withdrawal.
contract VellinDistributor is Ownable2Step, ReentrancyGuard, Pausable {
uint256 public constant HOLDER_PERCENT = 30;
uint256 public constant BURN_PERCENT = 30;
uint256 public constant MAX_BATCH = 50;
uint256 public constant PUSH_GAS = 50_000;
uint256 public constant AUTO_RETRY_DELAY = 1 hours;
address public constant BURN_ADDRESS = 0x000000000000000000000000000000000000dEaD;
IERC20 public immutable token;
IV2BuybackRouter public immutable router;
address public immutable team;
bytes32 public immutable policyHash;
address public keeper;
address[] private buybackPath;
struct Epoch {
bytes32 root;
bytes32 reportHash;
bytes32 snapshotHash;
uint64 snapshotBlock;
bool funded;
uint256 netProfit;
uint256 holderPool;
uint256 remaining;
}
struct Report {
uint64 day;
uint64 snapshotBlock;
bytes32 snapshotHash;
bytes32 root;
bytes32 reportHash;
int256 realisedPnl;
uint256 tradingFees;
uint256 infrastructureCosts;
}
struct Payment {
address account;
uint256 amount;
bytes32[] proof;
}
mapping(uint64 => Epoch) public epochs;
mapping(uint64 => mapping(address => bool)) public processed;
mapping(address => uint256) public credit;
mapping(address => uint256) public lastPaymentAttempt;
uint64 public lastDay;
uint64 public lastSnapshotBlock;
bool public hasEpoch;
uint256 public holderReserve;
uint256 public buybackReserve;
uint256 public creditReserve;
error InvalidConfiguration();
error InvalidEpoch();
error InvalidFunding();
error InvalidProof();
error AlreadyProcessed();
error InvalidBatch();
error InvalidPayment();
error UnauthorizedKeeper();
error InvalidBuyback();
error DirectTransferDisabled();
error RenounceDisabled();
event EpochFunded(
uint64 indexed day,
bytes32 root,
uint64 snapshotBlock,
bytes32 snapshotHash,
bytes32 reportHash,
int256 realisedPnl,
uint256 tradingFees,
uint256 infrastructureCosts,
uint256 netProfit,
uint256 holders,
uint256 buyback,
uint256 teamAmount
);
event HolderProcessed(uint64 indexed day, address indexed account, uint256 amount);
event PaymentSent(address indexed beneficiary, address indexed destination, uint256 amount);
event PaymentDeferred(address indexed beneficiary, uint256 amount);
event BuybackBurned(uint256 ethSpent, uint256 tokensSentToBurn, uint256 minimumOut);
event KeeperUpdated(address indexed keeper);
constructor(
address initialOwner,
address token_,
address router_,
address team_,
address keeper_,
address[] memory path_,
bytes32 policyHash_
) Ownable(initialOwner) {
if (
token_.code.length == 0 || router_.code.length == 0 || team_ == address(0) || team_ == BURN_ADDRESS
|| keeper_ == address(0) || policyHash_ == bytes32(0) || path_.length < 2 || path_.length > 5
|| path_[path_.length - 1] != token_ || path_[0] != IV2BuybackRouter(router_).WETH()
) revert InvalidConfiguration();
for (uint256 i; i < path_.length; ++i) {
if (path_[i] == address(0)) revert InvalidConfiguration();
}
token = IERC20(token_);
router = IV2BuybackRouter(router_);
team = team_;
keeper = keeper_;
buybackPath = path_;
policyHash = policyHash_;
}
function path() external view returns (address[] memory) {
return buybackPath;
}
function split(int256 realisedPnl, uint256 tradingFees, uint256 infrastructureCosts)
public
pure
returns (uint256 net, uint256 holders, uint256 burn, uint256 teamAmount)
{
uint256 costs = tradingFees + infrastructureCosts;
if (realisedPnl <= 0 || uint256(realisedPnl) <= costs) return (0, 0, 0, 0);
net = uint256(realisedPnl) - costs;
holders = Math.mulDiv(net, HOLDER_PERCENT, 100);
burn = Math.mulDiv(net, BURN_PERCENT, 100);
teamAmount = net - holders - burn; // At most two wei of split rounding.
}
/// @dev Nitro's NUMBER opcode is a parent-chain height; snapshots use L2 RPC block numbers.
function _currentChainBlock() private view returns (uint256) {
if (block.chainid == 4663 || block.chainid == 46630) {
// Fail closed if the required Robinhood/Arbitrum system precompile is unavailable.
return IArbSysBlockNumber(address(100)).arbBlockNumber();
}
return block.number;
}
/// @notice Developer deposits exactly the positive, approved daily net result.
/// @dev Report contents and end-of-day snapshot accuracy remain operator-attested.
function fundEpoch(Report calldata r) external payable nonReentrant onlyOwner whenNotPaused {
if (
r.day >= block.timestamp / 1 days || (hasEpoch && r.day <= lastDay) || epochs[r.day].funded
|| r.snapshotBlock >= _currentChainBlock() || r.snapshotBlock == 0
|| (hasEpoch && r.snapshotBlock <= lastSnapshotBlock) || r.snapshotHash == bytes32(0)
|| r.reportHash == bytes32(0)
) revert InvalidEpoch();
(uint256 net, uint256 holders, uint256 burn, uint256 teamAmount) =
split(r.realisedPnl, r.tradingFees, r.infrastructureCosts);
if (msg.value != net || (holders == 0) != (r.root == bytes32(0))) revert InvalidFunding();
epochs[r.day] = Epoch(r.root, r.reportHash, r.snapshotHash, r.snapshotBlock, true, net, holders, holders);
lastDay = r.day;
lastSnapshotBlock = r.snapshotBlock;
hasEpoch = true;
holderReserve += holders;
buybackReserve += burn;
credit[team] += teamAmount;
creditReserve += teamAmount;
emit EpochFunded(
r.day,
r.root,
r.snapshotBlock,
r.snapshotHash,
r.reportHash,
r.realisedPnl,
r.tradingFees,
r.infrastructureCosts,
net,
holders,
burn,
teamAmount
);
_pushCredit(team);
}
/// @notice Anyone can deliver valid payments to their fixed beneficiaries. Replays skip.
function distribute(uint64 day, Payment[] calldata payments) external nonReentrant {
if (payments.length == 0 || payments.length > MAX_BATCH) revert InvalidBatch();
for (uint256 i; i < payments.length; ++i) {
Payment calldata p = payments[i];
if (processed[day][p.account]) continue;
_creditHolder(day, p.account, p.amount, p.proof);
_pushCredit(p.account);
}
}
/// @notice Holder fallback, including contracts that cannot accept the bounded push.
function claim(uint64 day, uint256 amount, bytes32[] calldata proof, address payable destination)
external
nonReentrant
{
if (processed[day][msg.sender]) revert AlreadyProcessed();
_creditHolder(day, msg.sender, amount, proof);
_withdrawCredit(msg.sender, destination);
}
function retryPayment(address account) external nonReentrant {
_pushCredit(account);
}
/// @notice Bounded keeper recovery; persistently rejecting wallets are retried at most hourly.
/// @dev Holder withdrawals and individual caller-funded retries remain immediately accessible.
function retryPayments(address[] calldata accounts) external nonReentrant {
if (accounts.length == 0 || accounts.length > MAX_BATCH) revert InvalidBatch();
for (uint256 i; i < accounts.length; ++i) {
address account = accounts[i];
if (credit[account] != 0 && block.timestamp >= lastPaymentAttempt[account] + AUTO_RETRY_DELAY) {
_pushCredit(account);
}
}
}
function withdrawCredit(address payable destination) external nonReentrant {
_withdrawCredit(msg.sender, destination);
}
function _creditHolder(uint64 day, address account, uint256 amount, bytes32[] calldata proof) private {
Epoch storage e = epochs[day];
if (
!e.funded || account == address(0) || account == BURN_ADDRESS || account == address(this) || amount == 0
|| amount > e.remaining || !MerkleProof.verifyCalldata(proof, e.root, leaf(day, account, amount))
) revert InvalidProof();
processed[day][account] = true;
e.remaining -= amount;
holderReserve -= amount;
credit[account] += amount;
creditReserve += amount;
emit HolderProcessed(day, account, amount);
}
function leaf(uint64 day, address account, uint256 amount) public view returns (bytes32) {
// OpenZeppelin StandardMerkleTree double-hashed ABI encoding; domain-bound.
return keccak256(bytes.concat(keccak256(abi.encode(block.chainid, address(this), day, account, amount))));
}
function _pushCredit(address account) private {
uint256 amount = credit[account];
if (amount == 0) return;
lastPaymentAttempt[account] = block.timestamp;
credit[account] = 0;
creditReserve -= amount;
bool sent;
// No returndata copy: even a hostile receiver cannot return-bomb the batch.
assembly ("memory-safe") { sent := call(50000, account, amount, 0, 0, 0, 0) }
if (sent) {
emit PaymentSent(account, account, amount);
} else {
credit[account] = amount;
creditReserve += amount;
emit PaymentDeferred(account, amount);
}
}
function _withdrawCredit(address account, address payable destination) private {
uint256 amount = credit[account];
if (amount == 0 || destination == address(0) || destination == BURN_ADDRESS || destination == address(this)) {
revert InvalidPayment();
}
credit[account] = 0;
creditReserve -= amount;
(bool sent,) = destination.call{value: amount}("");
if (!sent) revert InvalidPayment();
emit PaymentSent(account, destination, amount);
}
/// @notice Uses only the 30% burn reserve; swap failure leaves holder payments available.
/// @dev Target V2 router/path must be verified for the actual launch market before deployment.
function executeBuyback(uint256 ethAmount, uint256 minimumTokens, uint256 deadline)
external
nonReentrant
whenNotPaused
{
if (msg.sender != keeper && msg.sender != owner()) revert UnauthorizedKeeper();
if (
ethAmount == 0 || ethAmount > buybackReserve || minimumTokens == 0 || deadline < block.timestamp
|| deadline > block.timestamp + 10 minutes
) revert InvalidBuyback();
buybackReserve -= ethAmount;
uint256 beforeBurn = token.balanceOf(BURN_ADDRESS);
router.swapExactETHForTokensSupportingFeeOnTransferTokens{value: ethAmount}(
minimumTokens, buybackPath, BURN_ADDRESS, deadline
);
uint256 burned = token.balanceOf(BURN_ADDRESS) - beforeBurn;
if (burned < minimumTokens) revert InvalidBuyback();
emit BuybackBurned(ethAmount, burned, minimumTokens);
}
function reserved() public view returns (uint256) {
return holderReserve + buybackReserve + creditReserve;
}
function setKeeper(address next) external onlyOwner {
if (next == address(0)) revert InvalidConfiguration();
keeper = next;
emit KeeperUpdated(next);
}
// Pause new reports and buybacks; funded holder claims/credits remain accessible.
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function renounceOwnership() public view override onlyOwner {
revert RenounceDisabled();
}
receive() external payable {
revert DirectTransferDisabled();
}
}