Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x8fe4131eDdb5a603C098Ce974CdaBC105D1F70FC
Balance 0 ETH
Nonce 1
Code Size 3984 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3984 bytes
0x608060405234801561000f575f80fd5b506004361061011c575f3560e01c80639a84a860116100a9578063cef028e81161006e578063cef028e814610283578063dcbf137d14610296578063ddb6dfc4146102a9578063e086e5ec146102b2578063eb87eb38146102ba575f80fd5b80639a84a860146102065780639c54a51914610219578063b31c710a1461023b578063b91816111461024e578063c42bd05a14610270575f80fd5b806363ef1605116100ef57806363ef16051461017d578063664daa3e146101905780636fdca5e0146101a7578063735de9f7146101ba57806373b2e80e146101e4575f80fd5b806322cb804a1461012057806343156db61461013557806347535d7b14610148578063476e5f451461016a575b5f80fd5b61013361012e366004610c3c565b6102cd565b005b610133610143366004610c3c565b610376565b6005546101559060ff1681565b60405190151581526020015b60405180910390f35b610133610178366004610c64565b6103de565b61013361018b366004610ce9565b610625565b6101996103be81565b604051908152602001610161565b6101336101b5366004610d1e565b61067e565b5f546101cc906001600160a01b031681565b6040516001600160a01b039091168152602001610161565b6101556101f2366004610d39565b60076020525f908152604090205460ff1681565b610133610214366004610d39565b6106c0565b610155610227366004610d39565b60086020525f908152604090205460ff1681565b6001546101cc906001600160a01b031681565b61015561025c366004610d39565b60066020525f908152604090205460ff1681565b6002546101cc906001600160a01b031681565b610155610291366004610d66565b610712565b6101336102a4366004610e25565b610758565b61019960045481565b61013361078c565b6101336102c8366004610d39565b610845565b335f9081526006602052604090205460ff166102fc5760405163ea8e4eb560e01b815260040160405180910390fd5b60025460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb906044015b6020604051808303815f875af115801561034d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103719190610e3c565b505050565b335f9081526006602052604090205460ff166103a55760405163ea8e4eb560e01b815260040160405180910390fd5b60015460405163a9059cbb60e01b81526001600160a01b038481166004830152602482018490529091169063a9059cbb90604401610331565b8181808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525086925061041e915083905082610712565b61043b576040516309bde33960e01b815260040160405180910390fd5b335f9081526007602052604090205460ff161561046b57604051630c8d9eab60e31b815260040160405180910390fd5b335f9081526008602052604090205460ff161561049b5760405163763c9be160e01b815260040160405180910390fd5b6001546040516323b872dd60e01b8152336004820152306024820152604481018790526001600160a01b03909116906323b872dd906064016020604051808303815f875af11580156104ef573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105139190610e3c565b6105565760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b60448201526064015b60405180910390fd5b60055460ff166105795760405163085de62560e01b815260040160405180910390fd5b61058285610894565b505f6105906103be87610e6b565b60025460405163a9059cbb60e01b8152336004820152602481018390529192506001600160a01b03169063a9059cbb906044016020604051808303815f875af11580156105df573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106039190610e3c565b5050335f908152600760205260409020805460ff191660011790555050505050565b335f9081526006602052604090205460ff166106545760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b03919091165f908152600660205260409020805460ff1916911515919091179055565b335f9081526006602052604090205460ff166106ad5760405163ea8e4eb560e01b815260040160405180910390fd5b6005805460ff1916911515919091179055565b335f9081526006602052604090205460ff166106ef5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b03165f908152600860205260409020805460ff19166001179055565b604080513360208201529081018290525f90819060600160405160208183030381529060405280519060200120905061074e8460045483610b91565b9150505b92915050565b335f9081526006602052604090205460ff166107875760405163ea8e4eb560e01b815260040160405180910390fd5b600455565b335f9081526006602052604090205460ff166107bb5760405163ea8e4eb560e01b815260040160405180910390fd5b6040515f90339047908381818185875af1925050503d805f81146107fa576040519150601f19603f3d011682016040523d82523d5f602084013e6107ff565b606091505b50509050806108425760405162461bcd60e51b815260206004820152600f60248201526e151c985b9cd9995c8819985a5b1959608a1b604482015260640161054d565b50565b335f9081526006602052604090205460ff166108745760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b03165f908152600860205260409020805460ff19169055565b604080516003808252608082019092525f9182919060208201606080368337505060015482519293506001600160a01b0316918391505f906108d8576108d8610e82565b6001600160a01b03928316602091820292909201015260035482519116908290600190811061090957610909610e82565b6001600160a01b039283166020918202929092010152600280548351921691839190811061093957610939610e82565b6001600160a01b0392831660209182029290920101526002546040516370a0823160e01b81523060048201525f9291909116906370a0823190602401602060405180830381865afa158015610990573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109b49190610e96565b6001545f5460405163095ea7b360e01b81526001600160a01b03918216600482015260248101889052929350169063095ea7b3906044016020604051808303815f875af1158015610a07573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a2b9190610e3c565b505f80546001600160a01b0316906338ed17399086908530610a4e4260b4610ead565b6040518663ffffffff1660e01b8152600401610a6e959493929190610ec0565b5f604051808303815f87803b158015610a85575f80fd5b505af1158015610a97573d5f803e3d5ffd5b50506002546040516370a0823160e01b81523060048201525f93508492506001600160a01b03909116906370a0823190602401602060405180830381865afa158015610ae5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b099190610e96565b610b139190610f2f565b60025460405163a9059cbb60e01b815261dead6004820152602481018390529192506001600160a01b03169063a9059cbb906044016020604051808303815f875af1158015610b64573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b889190610e3c565b50949350505050565b5f82610b9d8584610ba6565b14949350505050565b5f81815b8451811015610bea57610bd682868381518110610bc957610bc9610e82565b6020026020010151610bf2565b915080610be281610f42565b915050610baa565b509392505050565b5f818310610c0c575f828152602084905260409020610c1a565b5f8381526020839052604090205b9392505050565b80356001600160a01b0381168114610c37575f80fd5b919050565b5f8060408385031215610c4d575f80fd5b610c5683610c21565b946020939093013593505050565b5f805f60408486031215610c76575f80fd5b83359250602084013567ffffffffffffffff80821115610c94575f80fd5b818601915086601f830112610ca7575f80fd5b813581811115610cb5575f80fd5b8760208260051b8501011115610cc9575f80fd5b6020830194508093505050509250925092565b8015158114610842575f80fd5b5f8060408385031215610cfa575f80fd5b610d0383610c21565b91506020830135610d1381610cdc565b809150509250929050565b5f60208284031215610d2e575f80fd5b8135610c1a81610cdc565b5f60208284031215610d49575f80fd5b610c1a82610c21565b634e487b7160e01b5f52604160045260245ffd5b5f8060408385031215610d77575f80fd5b823567ffffffffffffffff80821115610d8e575f80fd5b818501915085601f830112610da1575f80fd5b8135602082821115610db557610db5610d52565b8160051b604051601f19603f83011681018181108682111715610dda57610dda610d52565b604052928352818301935084810182019289841115610df7575f80fd5b948201945b83861015610e1557853585529482019493820193610dfc565b9997909101359750505050505050565b5f60208284031215610e35575f80fd5b5035919050565b5f60208284031215610e4c575f80fd5b8151610c1a81610cdc565b634e487b7160e01b5f52601160045260245ffd5b808202811582820484141761075257610752610e57565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610ea6575f80fd5b5051919050565b8082018082111561075257610752610e57565b5f60a082018783526020878185015260a0604085015281875180845260c08601915082890193505f5b81811015610f0e5784516001600160a01b031683529383019391830191600101610ee9565b50506001600160a01b03969096166060850152505050608001529392505050565b8181038181111561075257610752610e57565b5f60018201610f5357610f53610e57565b506001019056fea2646970667358221220e94290bf813dafe6e1c88d595f3e53cf4ba49f576dc4d1fae471f4797083e0a564736f6c63430008150033

Verified Source Code Full Match

Compiler: v0.8.21+commit.d9974bed EVM: shanghai Optimization: Yes (200 runs)
Migrator.sol 344 lines
// SPDX-License-Identifier: None

pragma solidity =0.8.21;

interface newIERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

interface oldIERC20 {
    event Transfer(address indexed from, address indexed to, uint256 value);
    function balanceOf(address account) external view returns (uint256);
    function transfer(address to, uint256 amount) external returns (bool);
    function approve(address spender, uint256 amount) external returns (bool);
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

library MerkleProof {

    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    function verifyCalldata(
        bytes32[] calldata proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProofCalldata(proof, leaf) == root;
    }

    function processProof(
        bytes32[] memory proof,
        bytes32 leaf
    ) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    function processProofCalldata(
        bytes32[] calldata proof,
        bytes32 leaf
    ) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            computedHash = _hashPair(computedHash, proof[i]);
        }
        return computedHash;
    }

    function multiProofVerify(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProof(proof, proofFlags, leaves) == root;
    }

    function multiProofVerifyCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32 root,
        bytes32[] memory leaves
    ) internal pure returns (bool) {
        return processMultiProofCalldata(proof, proofFlags, leaves) == root;
    }

    function processMultiProof(
        bytes32[] memory proof,
        bool[] memory proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        // Check proof validity.
        require(
            leavesLen + proofLen - 1 == totalHashes,
            "MerkleProof: invalid multiproof"
        );

        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen
                ? leaves[leafPos++]
                : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function processMultiProofCalldata(
        bytes32[] calldata proof,
        bool[] calldata proofFlags,
        bytes32[] memory leaves
    ) internal pure returns (bytes32 merkleRoot) {
        uint256 leavesLen = leaves.length;
        uint256 proofLen = proof.length;
        uint256 totalHashes = proofFlags.length;

        require(
            leavesLen + proofLen - 1 == totalHashes,
            "MerkleProof: invalid multiproof"
        );

        bytes32[] memory hashes = new bytes32[](totalHashes);
        uint256 leafPos = 0;
        uint256 hashPos = 0;
        uint256 proofPos = 0;
        for (uint256 i = 0; i < totalHashes; i++) {
            bytes32 a = leafPos < leavesLen
                ? leaves[leafPos++]
                : hashes[hashPos++];
            bytes32 b = proofFlags[i]
                ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++])
                : proof[proofPos++];
            hashes[i] = _hashPair(a, b);
        }

        if (totalHashes > 0) {
            require(proofPos == proofLen, "MerkleProof: invalid multiproof");
            unchecked {
                return hashes[totalHashes - 1];
            }
        } else if (leavesLen > 0) {
            return leaves[0];
        } else {
            return proof[0];
        }
    }

    function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
        return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
    }

    function _efficientHash(
        bytes32 a,
        bytes32 b
    ) private pure returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}

interface IUniswapV2Router02 {
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}

error NoSwap4U();
error NotAuthorized();
error InvalidProof();
error AlreadyClaimed();
error TooEarly();

contract TokenSwap {
    uint256 public constant NEW_TOKEN_PER_OLD = 958;
    IUniswapV2Router02 public uniswapRouter;
    oldIERC20 public oldToken;
    newIERC20 public newToken;
    address private WETH;
    bytes32 public merkleRootHash;
    bool public isOpen;
    mapping(address => bool) public authorized;
    mapping(address => bool) public hasClaimed;
    mapping(address => bool) public noswap4u;

    constructor(address _oldToken, address _newToken) {
        if (block.chainid == 1) {
            WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
        } else if (block.chainid == 5) {
            WETH = 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6;
        }
        uniswapRouter = IUniswapV2Router02(
            0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
        );
        oldToken = oldIERC20(_oldToken);
        newToken = newIERC20(_newToken);
        authorized[msg.sender] = true;
    }

    modifier onlyAuthorized() {
        if (!authorized[msg.sender]) {
            revert NotAuthorized();
        }
        _;
    }

    function verify(
        bytes32[] memory proof,
        uint256 amount
    ) public view returns (bool) {
        bytes32 leaf = keccak256(abi.encode(msg.sender, amount));
        return MerkleProof.verify(proof, merkleRootHash, leaf);
    }

    modifier onlyMerkleVerified(bytes32[] memory proof, uint256 amount) {
        if (!verify(proof, amount)) {
            revert InvalidProof();
        }
        if (hasClaimed[msg.sender]) {
            revert AlreadyClaimed();
        }
        if (noswap4u[msg.sender]) {
            revert NoSwap4U();
        }
        _;
    }

    function setOpen(bool _value) external onlyAuthorized {
        isOpen = _value;
    }

    function modifyAuthorized(
        address _address,
        bool _value
    ) public onlyAuthorized {
        authorized[_address] = _value;
    }

    function noswap4uAdd(address _address) external onlyAuthorized {
        noswap4u[_address] = true;
    }

    function okfineucanswap(address _address) external onlyAuthorized {
        noswap4u[_address] = false;
    }

    function modifyRoot(bytes32 _merkleRoot) external onlyAuthorized {
        merkleRootHash = _merkleRoot;
    }

    function swapExactTokensForTokens(
        uint256 amount,
        bytes32[] calldata proof
    ) external onlyMerkleVerified(proof, amount) {
        require(
            oldToken.transferFrom(msg.sender, address(this), amount),
            "Transfer failed"
        );
        if (!isOpen) {
            revert TooEarly();
        }

        migrateSwap(amount);
        uint256 newAmount = amount * NEW_TOKEN_PER_OLD;
        newToken.transfer(msg.sender, newAmount);

        hasClaimed[msg.sender] = true;
    }

    function migrateSwap(uint256 amount) internal returns (uint256) {
        address[] memory path = new address[](3);
        path[0] = address(oldToken);
        path[1] = WETH;
        path[2] = address(newToken);

        // Record balance before swap
        uint256 newTokenBalanceBefore = newToken.balanceOf(address(this));

        // Approve and swap
        oldToken.approve(address(uniswapRouter), amount);
        uniswapRouter.swapExactTokensForTokens(
            amount,
            0, // No slippage protection
            path,
            address(this),
            block.timestamp + 180
        );

        // Calculate received amount
        uint256 receivedNewToken = newToken.balanceOf(address(this)) - newTokenBalanceBefore;

        // Transfer to burn address
        newToken.transfer(address(0xdead), receivedNewToken);
        return receivedNewToken;
    }

    function withdrawOldToken(
        address receiver,
        uint256 amount
    ) external onlyAuthorized {
        oldToken.transfer(receiver, amount);
    }

    function withdrawNewToken(
        address receiver,
        uint256 amount
    ) external onlyAuthorized {
        newToken.transfer(receiver, amount);
    }

    function withdrawETH() external onlyAuthorized {
        (bool success, ) = payable(msg.sender).call{value: address(this).balance}(
            ""
        );
        require(success, "Transfer failed");
    }
}

Read Contract

NEW_TOKEN_PER_OLD 0x664daa3e → uint256
authorized 0xb9181611 → bool
hasClaimed 0x73b2e80e → bool
isOpen 0x47535d7b → bool
merkleRootHash 0xddb6dfc4 → bytes32
newToken 0xc42bd05a → address
noswap4u 0x9c54a519 → bool
oldToken 0xb31c710a → address
uniswapRouter 0x735de9f7 → address
verify 0xcef028e8 → bool

Write Contract 9 functions

These functions modify contract state and require a wallet transaction to execute.

modifyAuthorized 0x63ef1605
address _address
bool _value
modifyRoot 0xdcbf137d
bytes32 _merkleRoot
noswap4uAdd 0x9a84a860
address _address
okfineucanswap 0xeb87eb38
address _address
setOpen 0x6fdca5e0
bool _value
swapExactTokensForTokens 0x476e5f45
uint256 amount
bytes32[] proof
withdrawETH 0xe086e5ec
No parameters
withdrawNewToken 0x22cb804a
address receiver
uint256 amount
withdrawOldToken 0x43156db6
address receiver
uint256 amount

Recent Transactions

No transactions found for this address