Skip to content
Chain 4441 · LiteForge TestnetHead#0
LitVM·Scan
Hard Money Web3 Explorer
Verified Contract
0x0505a5Cf69376C633d2cA0D34Cc4d3B9f69cB09e
Pin to watchlist
scan to copy
zkLTC Balance
0
hard money native
Transactions
11
Token transfers
22
Validations
0
blocks produced
Hard Money Score
33
/100
TOKEN DOMINANT
share of activity in native zkLTC vs. tokens
native
11
tokens
22
Contract name
AMMPool
Compiler
v0.8.30+commit.73712a01
Optimization
enabled · 200 runs
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

// ─── ERC20 Base ───────────────────────────────────────────────
abstract contract ERC20Base {
    string public name;
    string public symbol;
    uint8 public decimals = 18;
    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    constructor(string memory _name, string memory _symbol) {
        name = _name; symbol = _symbol;
    }
    function _mint(address to, uint256 amt) internal {
        totalSupply += amt; balanceOf[to] += amt;
        emit Transfer(address(0), to, amt);
    }
    function _burn(address from, uint256 amt) internal {
        require(balanceOf[from] >= amt, "bal");
        totalSupply -= amt; balanceOf[from] -= amt;
        emit Transfer(from, address(0), amt);
    }
    function transfer(address to, uint256 amt) public returns (bool) {
        require(balanceOf[msg.sender] >= amt, "bal");
        balanceOf[msg.sender] -= amt; balanceOf[to] += amt;
        emit Transfer(msg.sender, to, amt); return true;
    }
    function approve(address sp, uint256 amt) public returns (bool) {
        allowance[msg.sender][sp] = amt;
        emit Approval(msg.sender, sp, amt); return true;
    }
    function transferFrom(address from, address to, uint256 amt) public returns (bool) {
        require(balanceOf[from] >= amt, "bal");
        require(allowance[from][msg.sender] >= amt, "allow");
        allowance[from][msg.sender] -= amt;
        balanceOf[from] -= amt; balanceOf[to] += amt;
        emit Transfer(from, to, amt); return true;
    }
}

// ─── Megan Token ─────────────────────────────────────────────
contract MeganToken is ERC20Base {
    address public owner;
    constructor() ERC20Base("Megan", "MGN") {
        owner = msg.sender;
        _mint(msg.sender, 2_000_000 * 1e18);
    }
    function mint(address to, uint256 amt) external {
        require(msg.sender == owner, "owner");
        _mint(to, amt);
    }
    function burn(uint256 amt) external { _burn(msg.sender, amt); }
}

// ─── Lola Token ───────────────────────────────────────────────
contract LolaToken is ERC20Base {
    address public owner;
    constructor() ERC20Base("Lola", "LLA") {
        owner = msg.sender;
        _mint(msg.sender, 2_000_000 * 1e18);
    }
    function mint(address to, uint256 amt) external {
        require(msg.sender == owner, "owner");
        _mint(to, amt);
    }
    function burn(uint256 amt) external { _burn(msg.sender, amt); }
}

// ─── ERC721 Base ──────────────────────────────────────────────
abstract contract ERC721Base {
    string public name;
    string public symbol;
    uint256 public totalSupply;
    mapping(uint256 => address) public ownerOf;
    mapping(address => uint256) public balanceOf;
    mapping(uint256 => address) public getApproved;
    mapping(address => mapping(address => bool)) public isApprovedForAll;

    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    constructor(string memory _name, string memory _symbol) {
        name = _name; symbol = _symbol;
    }
    function _mint(address to) internal returns (uint256 id) {
        id = ++totalSupply;
        ownerOf[id] = to; balanceOf[to]++;
        emit Transfer(address(0), to, id);
    }
    function approve(address to, uint256 id) public {
        require(ownerOf[id] == msg.sender || isApprovedForAll[ownerOf[id]][msg.sender], "auth");
        getApproved[id] = to;
        emit Approval(ownerOf[id], to, id);
    }
    function setApprovalForAll(address op, bool approved) public {
        isApprovedForAll[msg.sender][op] = approved;
        emit ApprovalForAll(msg.sender, op, approved);
    }
    function transferFrom(address from, address to, uint256 id) public {
        require(ownerOf[id] == from, "owner");
        require(
            msg.sender == from ||
            msg.sender == getApproved[id] ||
            isApprovedForAll[from][msg.sender],
            "auth"
        );
        ownerOf[id] = to; balanceOf[from]--; balanceOf[to]++;
        delete getApproved[id];
        emit Transfer(from, to, id);
    }
}

// ─── Georgia NFT ──────────────────────────────────────────────
contract GeorgiaNFT is ERC721Base {
    address public owner;
    mapping(uint256 => uint256) public nftPower;
    mapping(address => uint256[]) private _owned;

    constructor() ERC721Base("Georgia", "GEO") { owner = msg.sender; }

    function mint(address to) external returns (uint256 id) {
        require(msg.sender == owner, "owner");
        id = _mint(to);
        nftPower[id] = 100 + (id * 7) % 901;
        _owned[to].push(id);
    }
    function tokensOf(address user) external view returns (uint256[] memory) {
        return _owned[user];
    }
    function burn(uint256 id) external {
        require(ownerOf[id] == msg.sender, "owner");
        ownerOf[id] = address(0); balanceOf[msg.sender]--;
        emit Transfer(msg.sender, address(0), id);
    }
}

// ─── Tbilisi NFT ──────────────────────────────────────────────
contract TbilisiNFT is ERC721Base {
    address public owner;
    mapping(uint256 => uint256) public nftRarity;
    mapping(address => uint256[]) private _owned;

    constructor() ERC721Base("Tbilisi", "TBS") { owner = msg.sender; }

    function mint(address to) external returns (uint256 id) {
        require(msg.sender == owner, "owner");
        id = _mint(to);
        nftRarity[id] = (id % 3) + 1;
        _owned[to].push(id);
    }
    function tokensOf(address user) external view returns (uint256[] memory) {
        return _owned[user];
    }
    function burn(uint256 id) external {
        require(ownerOf[id] == msg.sender, "owner");
        ownerOf[id] = address(0); balanceOf[msg.sender]--;
        emit Transfer(msg.sender, address(0), id);
    }
}

// ─── Oracle ───────────────────────────────────────────────────
contract Oracle {
    address public owner;
    mapping(address => uint256) public price;
    mapping(address => uint256) public updatedAt;

    event PriceUpdated(address indexed token, uint256 newPrice);

    constructor() { owner = msg.sender; }

    function setPrice(address token, uint256 _price) external {
        require(msg.sender == owner, "owner");
        price[token] = _price;
        updatedAt[token] = block.timestamp;
        emit PriceUpdated(token, _price);
    }
    function getPrice(address token) external view returns (uint256) {
        require(price[token] > 0, "no price");
        return price[token];
    }
}

// ─── AMM Pool ─────────────────────────────────────────────────
contract AMMPool {
    address public tokenA;
    address public tokenB;
    uint256 public reserveA;
    uint256 public reserveB;
    uint256 public totalLP;
    mapping(address => uint256) public lpBalance;

    event LiquidityAdded(address indexed user, uint256 amtA, uint256 amtB, uint256 lp);
    event LiquidityRemoved(address indexed user, uint256 amtA, uint256 amtB, uint256 lp);
    event Swapped(address indexed user, address tokenIn, uint256 amtIn, uint256 amtOut);

    constructor(address _a, address _b) { tokenA = _a; tokenB = _b; }

    function addLiquidity(uint256 amtA, uint256 amtB) external returns (uint256 lp) {
        require(amtA > 0 && amtB > 0, "zero");
        ERC20Base(tokenA).transferFrom(msg.sender, address(this), amtA);
        ERC20Base(tokenB).transferFrom(msg.sender, address(this), amtB);
        if (totalLP == 0) {
            lp = _sqrt(amtA * amtB);
        } else {
            uint256 lpA = (amtA * totalLP) / reserveA;
            uint256 lpB = (amtB * totalLP) / reserveB;
            lp = lpA < lpB ? lpA : lpB;
        }
        require(lp > 0, "lp=0");
        reserveA += amtA; reserveB += amtB;
        totalLP += lp; lpBalance[msg.sender] += lp;
        emit LiquidityAdded(msg.sender, amtA, amtB, lp);
    }

    function removeLiquidity(uint256 lp) external returns (uint256 amtA, uint256 amtB) {
        require(lpBalance[msg.sender] >= lp, "lp bal");
        amtA = (lp * reserveA) / totalLP;
        amtB = (lp * reserveB) / totalLP;
        lpBalance[msg.sender] -= lp; totalLP -= lp;
        reserveA -= amtA; reserveB -= amtB;
        ERC20Base(tokenA).transfer(msg.sender, amtA);
        ERC20Base(tokenB).transfer(msg.sender, amtB);
        emit LiquidityRemoved(msg.sender, amtA, amtB, lp);
    }

    function swapAforB(uint256 amtIn) external returns (uint256 amtOut) {
        require(amtIn > 0 && reserveA > 0 && reserveB > 0, "no liq");
        ERC20Base(tokenA).transferFrom(msg.sender, address(this), amtIn);
        uint256 fee = amtIn * 997;
        amtOut = (fee * reserveB) / (reserveA * 1000 + fee);
        reserveA += amtIn; reserveB -= amtOut;
        ERC20Base(tokenB).transfer(msg.sender, amtOut);
        emit Swapped(msg.sender, tokenA, amtIn, amtOut);
    }

    function swapBforA(uint256 amtIn) external returns (uint256 amtOut) {
        require(amtIn > 0 && reserveA > 0 && reserveB > 0, "no liq");
        ERC20Base(tokenB).transferFrom(msg.sender, address(this), amtIn);
        uint256 fee = amtIn * 997;
        amtOut = (fee * reserveA) / (reserveB * 1000 + fee);
        reserveB += amtIn; reserveA -= amtOut;
        ERC20Base(tokenA).transfer(msg.sender, amtOut);
        emit Swapped(msg.sender, tokenB, amtIn, amtOut);
    }

    function _sqrt(uint256 x) internal pure returns (uint256 y) {
        if (x == 0) return 0;
        uint256 z = (x + 1) / 2; y = x;
        while (z < y) { y = z; z = (x / z + z) / 2; }
    }
}

// ─── NFT Staking ──────────────────────────────────────────────
contract NFTStaking {
    address public rewardToken;
    address public georgiaNFT;
    address public tbilisiNFT;
    uint256 public rewardPerBlock = 1e16;

    struct Stake { uint256 tokenId; address nftContract; uint256 stakedAt; }
    mapping(address => Stake[]) public stakes;

    event NFTStaked(address indexed user, address nft, uint256 id);
    event NFTUnstaked(address indexed user, address nft, uint256 id, uint256 reward);
    event RewardClaimed(address indexed user, uint256 reward);

    constructor(address _reward, address _geo, address _tbs) {
        rewardToken = _reward; georgiaNFT = _geo; tbilisiNFT = _tbs;
    }

    function stakeNFT(address nftContract, uint256 tokenId) external {
        require(nftContract == georgiaNFT || nftContract == tbilisiNFT, "unsupported");
        ERC721Base(nftContract).transferFrom(msg.sender, address(this), tokenId);
        stakes[msg.sender].push(Stake(tokenId, nftContract, block.number));
        emit NFTStaked(msg.sender, nftContract, tokenId);
    }

    function unstakeNFT(uint256 idx) external {
        Stake[] storage s = stakes[msg.sender];
        require(idx < s.length, "idx");
        Stake memory st = s[idx];
        uint256 reward = (block.number - st.stakedAt) * rewardPerBlock;
        s[idx] = s[s.length - 1]; s.pop();
        ERC721Base(st.nftContract).transferFrom(address(this), msg.sender, st.tokenId);
        if (reward > 0 && ERC20Base(rewardToken).balanceOf(address(this)) >= reward)
            ERC20Base(rewardToken).transfer(msg.sender, reward);
        emit NFTUnstaked(msg.sender, st.nftContract, st.tokenId, reward);
    }

    function claimReward(uint256 idx) external {
        Stake[] storage s = stakes[msg.sender];
        require(idx < s.length, "idx");
        uint256 reward = (block.number - s[idx].stakedAt) * rewardPerBlock;
        s[idx].stakedAt = block.number;
        if (reward > 0 && ERC20Base(rewardToken).balanceOf(address(this)) >= reward)
            ERC20Base(rewardToken).transfer(msg.sender, reward);
        emit RewardClaimed(msg.sender, reward);
    }

    function pendingReward(address user, uint256 idx) external view returns (uint256) {
        Stake[] storage s = stakes[user];
        if (idx >= s.length) return 0;
        return (block.number - s[idx].stakedAt) * rewardPerBlock;
    }

    function stakeCount(address user) external view returns (uint256) {
        return stakes[user].length;
    }
}

// ─── Token Staking ────────────────────────────────────────────
contract TokenStaking {
    address public stakingToken;
    address public rewardToken;
    uint256 public rewardRate = 100;

    struct Info { uint256 amount; uint256 lastBlock; }
    mapping(address => Info) public stakers;
    uint256 public totalStaked;

    event Staked(address indexed user, uint256 amt);
    event Unstaked(address indexed user, uint256 amt);
    event RewardClaimed(address indexed user, uint256 amt);

    constructor(address _staking, address _reward) {
        stakingToken = _staking; rewardToken = _reward;
    }

    function stake(uint256 amt) external {
        require(amt > 0, "zero");
        _claim(msg.sender);
        ERC20Base(stakingToken).transferFrom(msg.sender, address(this), amt);
        stakers[msg.sender].amount += amt; totalStaked += amt;
        stakers[msg.sender].lastBlock = block.number;
        emit Staked(msg.sender, amt);
    }

    function unstake(uint256 amt) external {
        require(stakers[msg.sender].amount >= amt, "amt");
        _claim(msg.sender);
        stakers[msg.sender].amount -= amt; totalStaked -= amt;
        ERC20Base(stakingToken).transfer(msg.sender, amt);
        emit Unstaked(msg.sender, amt);
    }

    function claimReward() external {
        uint256 r = _claim(msg.sender);
        require(r > 0, "no reward");
        emit RewardClaimed(msg.sender, r);
    }

    function pending(address user) public view returns (uint256) {
        Info storage i = stakers[user];
        if (i.amount == 0) return 0;
        return (i.amount * (block.number - i.lastBlock) * rewardRate) / 1e24;
    }

    function _claim(address user) internal returns (uint256 r) {
        r = pending(user);
        if (r > 0 && ERC20Base(rewardToken).balanceOf(address(this)) >= r)
            ERC20Base(rewardToken).transfer(user, r);
        stakers[user].lastBlock = block.number;
    }
}