Reflection Token Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Reflection Token Development
Medium
~2-3 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Reflection Token Development

Reflection tokens are one of technically most problematic ERC-20 classes. Idea is simple: part of each transaction automatically distributed among all holders proportionally to their balance. In practice naive implementation requires iterating through all holders on each transfer, meaning gas proportional to holder count — at 10,000 holders transaction becomes so expensive contract stops working. Smart implementation through rFactor (reflection factor) solves this in O(1).

Reflection mechanism: mathematics

Standard approach — two balance types: rBalance (reflection balance) and tBalance (token balance). Holders store rBalance, which automatically grows on each transaction.

Key idea: instead of redistributing tokens among all holders, change conversion rate rBalance → tBalance. On transfer part of rAmount is excluded from rTotal (burned in reflection space), increasing rate = rTotal / tTotal for everyone else.

contract ReflectionToken is IERC20, Ownable {
    uint256 private constant MAX = ~uint256(0);
    
    uint256 private _tTotal;          // total supply in token-space
    uint256 private _rTotal;          // total supply in reflection-space
    
    uint256 private _tFeeTotal;       // accumulated fees
    
    uint256 public taxFee = 5;        // 5% — distributed to holders
    uint256 public liquidityFee = 3;  // 3% — to liquidity pool
    uint256 public burnFee = 2;       // 2% — burned
    
    mapping(address => uint256) private _rOwned;  // reflection balance
    mapping(address => uint256) private _tOwned;  // only for excluded addresses
    mapping(address => bool) private _isExcluded; // excluded from reflection
    
    constructor(uint256 totalSupply) {
        _tTotal = totalSupply * 10**18;
        _rTotal = (MAX - (MAX % _tTotal));  // maximum possible rTotal divisible by tTotal
        _rOwned[msg.sender] = _rTotal;
    }
    
    function _getRate() private view returns (uint256) {
        (uint256 rSupply, uint256 tSupply) = _getCurrentSupply();
        return rSupply / tSupply;
    }
    
    function _getCurrentSupply() private view returns (uint256, uint256) {
        uint256 rSupply = _rTotal;
        uint256 tSupply = _tTotal;
        
        // excluded accounts (liquidity pools, contracts) don't participate in reflection
        for (uint256 i = 0; i < _excluded.length; i++) {
            if (_rOwned[_excluded[i]] > rSupply || _tOwned[_excluded[i]] > tSupply)
                return (_rTotal, _tTotal);
            rSupply -= _rOwned[_excluded[i]];
            tSupply -= _tOwned[_excluded[i]];
        }
        
        if (rSupply < _rTotal / _tTotal) return (_rTotal, _tTotal);
        return (rSupply, tSupply);
    }
    
    function balanceOf(address account) public view returns (uint256) {
        if (_isExcluded[account]) return _tOwned[account];
        return tokenFromReflection(_rOwned[account]);
    }
    
    function tokenFromReflection(uint256 rAmount) public view returns (uint256) {
        require(rAmount <= _rTotal, "Amount too large");
        return rAmount / _getRate();
    }
    
    function _transferStandard(address sender, address recipient, uint256 tAmount) private {
        // calculate all values
        (uint256 rAmount, uint256 rTransferAmount, uint256 rFee,
         uint256 tTransferAmount, uint256 tFee, uint256 tLiquidity, uint256 tBurn) 
            = _getValues(tAmount);
        
        // update reflection balances
        _rOwned[sender] -= rAmount;
        _rOwned[recipient] += rTransferAmount;
        
        // reflection fee: decrease rTotal — this automatically increases
        // all other holders' balances without explicit iteration
        _reflectFee(rFee, tFee);
        
        // handle liquidity and burn
        _takeLiquidity(tLiquidity);
        _burn(sender, tBurn);
        
        emit Transfer(sender, recipient, tTransferAmount);
    }
    
    function _reflectFee(uint256 rFee, uint256 tFee) private {
        _rTotal -= rFee;     // key operation: decrease rTotal
        _tFeeTotal += tFee;  // statistics
    }
}

Problem of excluded addresses

Liquidity pool addresses (Uniswap pair, PancakeSwap pair) must be excluded from reflection. If pool participates in reflection, its token balance constantly grows, violating token/ETH ratio in pool and creating arb opportunities. This is classic mistake in early reflection tokens.

function excludeFromReward(address account) public onlyOwner {
    require(!_isExcluded[account], "Already excluded");
    if (_rOwned[account] > 0) {
        _tOwned[account] = tokenFromReflection(_rOwned[account]);
    }
    _isExcluded[account] = true;
    _excluded.push(account);
}

When adding to excluded, current tBalance is saved (converted from rBalance) — otherwise account loses funds.

Vulnerabilities and risks

Iteration over excluded: function _getCurrentSupply() iterates through excluded addresses array. If this array is large (attacker could add many addresses through some function), transactions start hitting gas limit. _excluded.length must be strictly limited, function excludeFromReward only for owner.

Precision loss at high transaction count: _rTotal decreases with each transaction. Theoretically after enormous number of transactions _rTotal could become so small _getRate() returns 0 and contract breaks. In practice with reasonable supply and fees this happens in thousands of years, but invariant worth checking in tests.

Anti-whale measures: without additional restrictions large holders can manipulate reflection. Standard solution — maxTransactionAmount and maxWalletSize:

uint256 public maxTxAmount = _tTotal / 100;      // 1% of supply
uint256 public maxWalletToken = _tTotal / 50;    // 2% of supply

function _transfer(address from, address to, uint256 amount) internal {
    require(amount <= maxTxAmount, "Exceeds max tx");
    if (!_isExcluded[to]) {
        require(balanceOf(to) + amount <= maxWalletToken, "Exceeds max wallet");
    }
    // ...
}

Auto-liquidity mechanism

Many reflection tokens include auto-liquidity: accumulated liquidityFee periodically converted to LP tokens via Uniswap/PancakeSwap. This maintains liquidity without team involvement.

bool inSwapAndLiquify = false;
uint256 private numTokensSellToAddToLiquidity = _tTotal / 1000; // 0.1%

function _transfer(...) {
    uint256 contractBalance = balanceOf(address(this));
    bool overMinTokenBalance = contractBalance >= numTokensSellToAddToLiquidity;
    
    if (overMinTokenBalance && !inSwapAndLiquify && from != uniswapV2Pair) {
        inSwapAndLiquify = true;
        swapAndLiquify(numTokensSellToAddToLiquidity);
        inSwapAndLiquify = false;
    }
    // ...
}

Flag inSwapAndLiquify prevents recursive call on token swap through Uniswap.

Economic feasibility

High transfer fees (5–10% reflection + 3–5% liquidity + burn) create buy/sell spread making token poorly suited as actual payment method. Reflection tokens work as long-term holder reward mechanism and high-frequency trading deterrent, but at excessive fees repel liquid traders creating poor price discovery.

Recommended total fee range: 5–8%. Higher — economically dysfunctional construction regardless of technical correctness.