AltarV2

Description:

Decentralized Finance (DeFi) protocol contract providing Swap, Liquidity functionality.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

/* ---------- Minimal interfaces ---------- */
interface IERC20 {
    function transfer(address to, uint256) external returns (bool);
    function transferFrom(address from, address to, uint256) external returns (bool);
    function approve(address spender, uint256) external returns (bool);
    function balanceOf(address) external view returns (uint256);
}
interface IMintable is IERC20 {
    function mint(address to, uint256 amount) external;
}

interface IRelicHub {
    function mintForCaller(
        address to,
        uint256 ethIn,
        uint256 jujuBurned,
        uint256 poochMint,
        string calldata tag
    ) external returns (uint256 tokenId);
}

interface IRouter02 {
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bytes32 pairSalt,
        bytes calldata pairBytecode
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
}

interface ISwapMin {
    function swapExactETHForTokens(
        uint amountOutMin,
        address tokenOut,
        address to
    ) external payable returns (uint amountOut);
}

/* ------------------------------ Exalted AltarV2 ------------------------------ */
contract AltarV2 {
    /* ===== Canon wires ===== */
    address public immutable JUJU;
    address public immutable POOCH;
    address public immutable WETH;
    address public immutable RELIC_HUB;
    address public immutable ROUTER02;
    address public SWAP_MIN; // settable

    address public constant DEAD = 0x000000000000000000000000000000000000dEaD;

    /* ===== Game constants ===== */
    uint256 public constant JUJU_GIFT  = 132134558914423337;     // ~0.132134558914... JUJU
    uint256 public constant POOCH_GIFT = 13213455891442333776;   // ~13.21345589144... POOCH

    /* ===== ETH engine split ===== */
    uint256 public constant ETH_BURN_BPS = 2100; // 21.00% to DEAD
    uint256 public constant ETH_FEE_BPS  = 200;  // 2.00% to feeReceiver
    uint256 public constant BPS_DENOM    = 10000;
    address public feeReceiver;

    /* ===== LP helpers ===== */
    uint256 public constant JUJU_PER_ETH = 100_000; // for MINT_FOR_LP
    uint256 public constant MIN_ENGINE_WEI = 1e12;  // dust guard (~0.000001 ETH)

    /* ===== Modes ===== */
    enum LpPolicy { MINT_FOR_LP, BUY_FOR_LP, TREASURY_ONLY }

    struct Mode {
        LpPolicy lpPolicy;      // 0,1,2
        address  lpReceiver;    // also the treasury for TREASURY_ONLY
        string   tagTemplate;
        bool     poochEnabled;  // enables burnForPooch mint
        mapping(address => bool) qualifierAllowed;
        mapping(address => uint256) xpPerUnit;
        bool exists;
    }
    mapping(uint256 => Mode) private modes;

    /* ===== Admin ===== */
    address public owner;
    modifier onlyOwner() { require(msg.sender == owner, "not owner"); _; }

    /* ===== Events ===== */
    event Offered(address indexed user, uint256 indexed modeId, uint256 ethIn, uint256 ethBurned, uint256 ethFee, uint256 ethToLp, uint256 jujuGift);
    event LpAdded(address indexed user, uint256 indexed modeId, uint256 jujuAdded, uint256 ethAdded, uint256 liquidity);
    event BurnedForPooch(address indexed user, uint256 indexed modeId, uint256 jujuBurned, address[] quals, uint256[] qualAmts, uint256 poochOut);
    event ModeUpdated(uint256 indexed modeId);
    event SwapRouterSet(address indexed router);
    event FeeReceiverSet(address indexed receiver);

    constructor(
        address _JUJU,
        address _POOCH,
        address _WETH,
        address _RELIC_HUB,
        address _ROUTER02,
        address _SWAP_MIN
    ) {
        owner = msg.sender;
        JUJU = _JUJU;
        POOCH = _POOCH;
        WETH = _WETH;
        RELIC_HUB = _RELIC_HUB;
        ROUTER02 = _ROUTER02;
        SWAP_MIN = _SWAP_MIN;
        feeReceiver = msg.sender;
    }

    /* ================== Admin config ================== */
    function setMode(
        uint256 modeId,
        LpPolicy lpPolicy,
        address lpReceiver,
        string calldata tagTemplate,
        bool poochEnabled
    ) external onlyOwner {
        Mode storage m = modes[modeId];
        m.lpPolicy = lpPolicy;
        m.lpReceiver = lpReceiver;
        m.tagTemplate = tagTemplate;
        m.poochEnabled = poochEnabled;
        m.exists = true;
        emit ModeUpdated(modeId);
    }

    function setQualifier(uint256 modeId, address token, bool allowed, uint256 xpPerUnit) external onlyOwner {
        Mode storage m = modes[modeId]; require(m.exists, "mode");
        m.qualifierAllowed[token] = allowed;
        m.xpPerUnit[token] = xpPerUnit;
        emit ModeUpdated(modeId);
    }

    function setSwapRouter(address router) external onlyOwner {
        SWAP_MIN = router;
        emit SwapRouterSet(router);
    }

    function setFeeReceiver(address a) external onlyOwner {
        feeReceiver = a;
        emit FeeReceiverSet(a);
    }

    function transferOwnership(address n) external onlyOwner { owner = n; }

    /* ================== Internals ================== */
    function _addLp(uint256 tokenAmt, uint256 ethAmt, address to) internal {
        IERC20(JUJU).approve(ROUTER02, tokenAmt);
        IRouter02(ROUTER02).addLiquidityETH{value: ethAmt}(
            JUJU, tokenAmt, 0, 0, to, block.timestamp, bytes32(0), ""
        );
    }

    function _tag(string memory tpl, address /*user*/) internal pure returns (string memory) {
        return tpl; // simple template pass-through
    }

    /* ================== Core: ETH offer ================== */
    function offerEth(uint256 modeId) external payable {
        Mode storage m = modes[modeId]; require(m.exists, "mode");
        uint256 ethIn = msg.value; require(ethIn > 0, "NO_ETH");

        // MODE: TREASURY_ONLY → pure pass-through + Relic, no engine, no JUJU gift.
        if (m.lpPolicy == LpPolicy.TREASURY_ONLY) {
            (bool okTreasury,) = m.lpReceiver.call{value: ethIn}("");
            require(okTreasury, "treasury fail");

            IRelicHub(RELIC_HUB).mintForCaller(
                msg.sender, ethIn, 0, 0, _tag(m.tagTemplate, msg.sender)
            );
            emit Offered(msg.sender, modeId, ethIn, 0, 0, 0, 0);
            return;
        }

        // ENGINE MODES (MINT_FOR_LP / BUY_FOR_LP)
        require(ethIn >= MIN_ENGINE_WEI, "engine dust");
        uint256 ethBurn = (ethIn * ETH_BURN_BPS) / BPS_DENOM;
        uint256 ethFee  = (ethIn * ETH_FEE_BPS)  / BPS_DENOM;
        uint256 ethLp   = ethIn - ethBurn - ethFee;

        (bool ok,) = DEAD.call{value: ethBurn}(""); require(ok, "burn fail");
        (ok,) = feeReceiver.call{value: ethFee}(""); require(ok, "fee fail");

        // JUJU gift only when engine runs
        IMintable(JUJU).mint(msg.sender, JUJU_GIFT);

        if (m.lpPolicy == LpPolicy.MINT_FOR_LP) {
            uint256 jujuForLp = ethLp * JUJU_PER_ETH;
            IMintable(JUJU).mint(address(this), jujuForLp);
            _addLp(jujuForLp, ethLp, m.lpReceiver);
            emit LpAdded(msg.sender, modeId, jujuForLp, ethLp, 0);
        } else {
            // BUY_FOR_LP
            require(SWAP_MIN != address(0), "swap router not set");
            uint256 buyEth  = ethLp / 2;
            uint256 keepEth = ethLp - buyEth;
            require(buyEth > 0 && keepEth > 0, "LP too small");

            uint256 bought  = ISwapMin(SWAP_MIN).swapExactETHForTokens{value: buyEth}(0, JUJU, address(this));
            _addLp(bought, keepEth, m.lpReceiver);
            emit LpAdded(msg.sender, modeId, bought, keepEth, 0);
        }

        IRelicHub(RELIC_HUB).mintForCaller(
            msg.sender, ethIn, 0, 0, _tag(m.tagTemplate, msg.sender)
        );
        emit Offered(msg.sender, modeId, ethIn, ethBurn, ethFee, ethLp, JUJU_GIFT);
    }

    /* ========== Burn JUJU (+ qualifiers) to mint POOCH ========== */
    function burnForPooch(
        uint256 modeId,
        uint256 jujuToBurn,
        address[] calldata quals,
        uint256[] calldata amounts
    ) external {
        Mode storage m = modes[modeId]; require(m.exists, "mode");
        require(jujuToBurn >= JUJU_GIFT, "need gift min");
        require(quals.length == amounts.length, "len");

        // burn JUJU
        require(IERC20(JUJU).transferFrom(msg.sender, DEAD, jujuToBurn), "juju xfer");

        // burn qualifiers (e.g., LINK, PYUSD)
        for (uint i = 0; i < quals.length; i++) {
            address t = quals[i]; uint256 a = amounts[i];
            require(m.qualifierAllowed[t], "qual disallowed");
            require(IERC20(t).transferFrom(msg.sender, DEAD, a), "qual xfer");
        }

        uint256 poochOut = 0;
        if (m.poochEnabled) {
            poochOut = POOCH_GIFT; // simple fixed reward; can be upgraded to rate
            IMintable(POOCH).mint(msg.sender, poochOut);
        }

        IRelicHub(RELIC_HUB).mintForCaller(
            msg.sender, 0, jujuToBurn, poochOut, _tag(m.tagTemplate, msg.sender)
        );
        emit BurnedForPooch(msg.sender, modeId, jujuToBurn, quals, amounts, poochOut);
    }

    receive() external payable {}
}

Tags:
DeFi, Swap, Liquidity|addr:0x9bead1f04cba5d837224d6762f6a1b53cd0c5f54|verified:true|block:23497775|tx:0x8b6be45d7e8e86e825ed3cc08d3a83a5d0b340307955afc77bd607583a2c5f4e|first_check:1759504428

Submitted on: 2025-10-03 17:13:50

Comments

Log in to comment.

No comments yet.