Yield Auto-Rebalancing Engine

What it does:
A smart contract that automatically reallocates user funds across multiple yield strategies to maintain an optimal risk-return balance based on predefined rules.

Why it matters:
DeFi yields change constantly. Manually chasing APY is inefficient, emotional, and costly. This contract enforces disciplined, rules-based rebalancing to maximize yield while controlling risk.

How it works:

  • Users deposit funds into a unified yield vault.

  • Multiple yield strategies are registered (Aave, Compound, LSTs, etc.).

  • Target allocation percentages are defined on-chain.

  • The contract periodically rebalances funds to match targets.

  • Performance metrics and allocations are stored transparently.

      // SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/**
 * @title YieldAutoRebalancer
 * @author Nam
 * @notice Automatically reallocates funds across yield strategies
 *         based on target weights
 */
contract YieldAutoRebalancer {

    // -------------------- DATA STRUCTURES --------------------

    struct Strategy {
        address strategyAddress;   // External yield strategy contract
        uint256 weight;            // Target weight (percentage)
        uint256 balance;           // Tracked balance allocated
        bool active;
    }

    Strategy[] public strategies;

    address public owner;
    uint256 public totalManaged;

    // -------------------- EVENTS --------------------

    event Deposited(address indexed user, uint256 amount);
    event StrategyAdded(address strategy, uint256 weight);
    event StrategyUpdated(uint256 index, uint256 newWeight);
    event Rebalanced(uint256 totalFunds);

    // -------------------- MODIFIERS --------------------

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    // -------------------- CONSTRUCTOR --------------------

    constructor() {
        owner = msg.sender;
    }

    // -------------------- USER FUNCTIONS --------------------

    /**
     * @notice Deposit ETH into the yield engine
     */
    function deposit() external payable {
        require(msg.value > 0, "Zero deposit");

        totalManaged += msg.value;
        emit Deposited(msg.sender, msg.value);
    }

    // -------------------- STRATEGY MANAGEMENT --------------------

    /**
     * @notice Add a new yield strategy
     * @param _strategy External strategy address
     * @param _weight Target allocation weight (sum = 100)
     */
    function addStrategy(address _strategy, uint256 _weight)
        external
        onlyOwner
    {
        require(_strategy != address(0), "Invalid address");

        strategies.push(
            Strategy({
                strategyAddress: _strategy,
                weight: _weight,
                balance: 0,
                active: true
            })
        );

        emit StrategyAdded(_strategy, _weight);
    }

    /**
     * @notice Update strategy weight
     */
    function updateStrategyWeight(uint256 _index, uint256 _newWeight)
        external
        onlyOwner
    {
        require(_index < strategies.length, "Invalid index");
        strategies[_index].weight = _newWeight;

        emit StrategyUpdated(_index, _newWeight);
    }

    // -------------------- REBALANCING LOGIC --------------------

    /**
     * @notice Rebalance funds across strategies
     * @dev In real systems, this would call deposit/withdraw
     *      functions on external strategy contracts
     */
    function rebalance() external onlyOwner {
        uint256 totalWeight;
        for (uint256 i = 0; i  0, "No active strategies");

        for (uint256 i = 0; i < strategies.length; i++) {
            if (!strategies[i].active) continue;

            uint256 targetAllocation =
                (totalManaged * strategies[i].weight) / totalWeight;

            strategies[i].balance = targetAllocation;
        }

        emit Rebalanced(totalManaged);
    }

    // -------------------- VIEW FUNCTIONS --------------------

    /**
     * @notice Get strategy count
     */
    function strategyCount() external view returns (uint256) {
        return strategies.length;
    }

    /**
     * @notice Get full strategy info
     */
    function getStrategy(uint256 _index)
        external
        view
        returns (
            address strategy,
            uint256 weight,
            uint256 balance,
            bool active
        )
    {
        Strategy memory s = strategies[_index];
        return (
            s.strategyAddress,
            s.weight,
            s.balance,
            s.active
        );
    }
}