Accounts
0x17...c258
0x17...c258

0x17...c258

$500
This contract's source code is verified!
Contract Metadata
Compiler
0.8.28+commit.7893614a
Language
Solidity
Contract Source Code
File 1 of 1: chonks.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

error ZeroValue();

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address recipient, uint256 amount) external;
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external;
    function transferFrom(address sender, address recipient, uint256 amount) external;
}

interface ICHONKS {
    function walletOfOwner(address) external view returns (uint256[] memory);
    function safeTransferFrom(address, address, uint256) external;
    function transferFrom(address, address, uint256) external;
}

contract Holder {
    address constant chonksNft = 0x07152bfde079b5319e5308C43fB1Dbc9C76cb4F9;
    address constant controller = 0x172ab1C8278Fc267D959682534f319609B6Dc258;

    function withdraw(uint256 id, address to) external {
        if (msg.sender != controller) {
            revert();
        }

        ICHONKS(chonksNft).transferFrom(address(this), to, id);
    }
}

contract HolderManager {
    address constant self = 0x172ab1C8278Fc267D959682534f319609B6Dc258;
    address constant clone = 0x6dF9D496f26f03ACf63977F68b95875de275C424;

    function getHolder(uint256 id) internal pure returns(address predicted){
        assembly {
            let ptr := mload(0x40)
            mstore(add(ptr, 0x38), self)
            mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff)
            mstore(add(ptr, 0x14), clone)
            mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73)
            mstore(add(ptr, 0x58), id)
            mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37))
            predicted := keccak256(add(ptr, 0x43), 0x55)
        }
    }

    function createHolder(uint256 id) internal {
        assembly {
            mstore(0x00, or(shr(0xe8, shl(0x60, clone)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000))
            mstore(0x20, or(shl(0x78, clone), 0x5af43d82803e903d91602b57fd5bf3))
            let returnAddress := create2(0, 0x09, 0x37, id)
        }
    }
}

contract WrappedChonks is HolderManager {
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);

    event WrapChonk(address indexed from, uint256 indexed tokenId);
    event UnwrapChonk(address indexed to, uint256 indexed tokenId);

    mapping (address => uint256) private _balances;
    mapping (address => mapping (address => uint256)) private _allowances;

    address constant public chonksNft = 0x07152bfde079b5319e5308C43fB1Dbc9C76cb4F9;

    string private _name = "Wrapped Chonks";
    string private _symbol = "CHONKS";

    uint256 constant private _decimals = 18;
    uint256 private _supply = IERC20(chonksNft).totalSupply() * 10**_decimals;
    uint256 constant private _oneToken = 10**_decimals;

    uint256[] private _selfChonksIdQueue;
    uint256 private _selfChonksQueueIndex;

    mapping (uint256 => bool) private holderExists;

    constructor () {
        _balances[address(this)] = _supply;
        emit Transfer(address(0), address(this), _supply);
    }

    function owner() public pure returns (address) {
        return address(0);
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public pure returns (uint256) {
        return _decimals;
    }

    function totalSupply() public view returns (uint256) {
        return _supply;
    }

    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    function transfer(address recipient, uint256 amount) public {
        _transfer(msg.sender, recipient, amount);
    }

    function allowance(address holder, address spender) public view returns (uint256) {
        return _allowances[holder][spender];
    }

    function approve(address spender, uint256 amount) public {
        _approve(msg.sender, spender, amount);
    }

    function transferFrom(address sender, address recipient, uint256 amount) public {
        if (sender != msg.sender) {
            _approve(sender, msg.sender, _allowances[sender][msg.sender] - amount);
        }
        _transfer(sender, recipient, amount);
    }

    function _approve(address holder, address spender, uint256 amount) private {
        _allowances[holder][spender] = amount;
        emit Approval(holder, spender, amount);
    }

    function _transfer(address from, address to, uint256 amount) private {
        if (amount == 0) revert ZeroValue();

        _balances[from] -= amount;
        _balances[to] += amount;
        emit Transfer(from, to, amount);
    }

    function unwrapChonks(uint256 chonksAmount) external {
        _transfer(msg.sender, address(this), chonksAmount * _oneToken);

        for (; chonksAmount > 0; --chonksAmount) {
            _unwrapChonk();
        }
    }

    function _unwrapChonk() private {
        uint256 unwrapId = _selfChonksIdQueue[_selfChonksQueueIndex];

        Holder(getHolder(unwrapId)).withdraw(unwrapId, msg.sender);

        delete _selfChonksIdQueue[_selfChonksQueueIndex];
        unchecked {
            ++_selfChonksQueueIndex;
        }

        emit UnwrapChonk(msg.sender, unwrapId);
    }

    function wrappedIds(uint256 amount) public view returns(uint256[] memory) {
        uint256 totalLength = _selfChonksIdQueue.length - _selfChonksQueueIndex;
        if (amount == 0 || amount > totalLength) {
            amount = totalLength;
        }        
        
        uint256[] memory storedIds = new uint256[](amount);

        for (uint256 i; i < amount; ++i) {
            unchecked {
                storedIds[i] = _selfChonksIdQueue[_selfChonksQueueIndex+i];
            }
        }

        return storedIds;
    }

    function wrappedChonksAmount() public view returns(uint256) {
        return _selfChonksIdQueue.length - _selfChonksQueueIndex;
    }

    function onERC721Received(address _address, address from, uint256 tokenId, bytes calldata _data) external returns (bytes4) {
        if (msg.sender != chonksNft) {
            revert();
        }

        if (!holderExists[tokenId]) {
            createHolder(tokenId);
            holderExists[tokenId] = true;
        }

        ICHONKS(chonksNft).transferFrom(address(this), getHolder(tokenId), tokenId);

        _selfChonksIdQueue.push(tokenId);
        emit WrapChonk(from, tokenId);

        _transfer(address(this), from, _oneToken);

        return bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"));
    }
}
Settings
{
  "compilationTarget": {
    "chonks.sol": "WrappedChonks"
  },
  "evmVersion": "cancun",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "remappings": [],
  "viaIR": true
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"UnwrapChonk","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"WrapChonk","type":"event"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chonksNft","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chonksAmount","type":"uint256"}],"name":"unwrapChonks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"wrappedChonksAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrappedIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"}]