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 {}
}
Submitted on: 2025-10-03 17:13:50
Comments
Log in to comment.
No comments yet.