Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x7a6d98a6CC5c0f0029D6a26E987aA7e04FA5da03
Balance 0 ETH
Nonce 1
Code Size 3112 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3112 bytes
0x608060405234801561000f575f5ffd5b5060043610610090575f3560e01c80638da5cb5b116100635780638da5cb5b14610117578063c18402fa14610129578063edca76bc14610164578063f2fde38b14610177578063fc0c546a1461018a575f5ffd5b80632eb4a7ab146100945780632f48ab7d146100b05780636fe3bc08146100ef5780637cb6475914610104575b5f5ffd5b61009d60015481565b6040519081526020015b60405180910390f35b6100d77f0000000000000000000000003bef807ac66522d7759caf07b668a7eb00e1d00e81565b6040516001600160a01b0390911681526020016100a7565b6101026100fd366004610a72565b6101b1565b005b610102610112366004610a9a565b610291565b5f546100d7906001600160a01b031681565b61014f610137366004610ab1565b60026020525f90815260409020805460019091015482565b604080519283526020830191909152016100a7565b610102610172366004610ad1565b6102f5565b610102610185366004610ab1565b6106be565b6100d77f000000000000000000000000044ca854fa227e27e07652b7f6a6b578703f394581565b5f546001600160a01b031633146101e35760405162461bcd60e51b81526004016101da90610b50565b60405180910390fd5b6001600160a01b0382166102255760405162461bcd60e51b81526020600482015260096024820152683d32b9379030b2323960b91b60448201526064016101da565b5f81116102625760405162461bcd60e51b815260206004820152600b60248201526a616d6f756e74207a65726f60a81b60448201526064016101da565b61028d7f0000000000000000000000003bef807ac66522d7759caf07b668a7eb00e1d00e8383610782565b5050565b5f546001600160a01b031633146102ba5760405162461bcd60e51b81526004016101da90610b50565b60018190556040518181527f42cbc405e4dbf1b691e85b9a34b08ecfcf7a9ad9078bf4d645ccfa1fac11c10b9060200160405180910390a150565b6001546103335760405162461bcd60e51b815260206004820152600c60248201526b1c9bdbdd081b9bdd081cd95d60a21b60448201526064016101da565b6040516bffffffffffffffffffffffff193360601b16602082015260348101859052605481018490525f906074016040516020818303038152906040528051906020012090506103b98383808060200260200160405190810160405280939291908181526020018383602002808284375f9201919091525050600154915084905061088a565b6103f55760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016101da565b335f9081526002602090815260409182902082518084019093528054808452600190910154918301919091528610156104645760405162461bcd60e51b81526020600482015260116024820152701d1bdad95b951bdd185b080f081d5cd959607a1b60448201526064016101da565b80602001518510156104ab5760405162461bcd60e51b815260206004820152601060248201526f1d5cd91d151bdd185b080f081d5cd95960821b60448201526064016101da565b80515f906104b99088610b73565b90505f8260200151876104cc9190610b73565b90505f8211806104db57505f81115b61051a5760405162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b60448201526064016101da565b335f9081526002602052604090208881556001018790558115610563576105637f000000000000000000000000044ca854fa227e27e07652b7f6a6b578703f394533308561089f565b801561066a576040516370a0823160e01b815230600482015281907f0000000000000000000000003bef807ac66522d7759caf07b668a7eb00e1d00e6001600160a01b0316906370a0823190602401602060405180830381865afa1580156105cd573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105f19190610b92565b101561063f5760405162461bcd60e51b815260206004820152601d60248201527f696e73756666696369656e74205553445420696e20636f6e747261637400000060448201526064016101da565b61066a7f0000000000000000000000003bef807ac66522d7759caf07b668a7eb00e1d00e3383610782565b60408051838152602081018390529081018990526060810188905233907f40afc61aabce83a502901d9dc66b15d1ee92bfcc1f4f56923b8434dcd041e19f9060800160405180910390a25050505050505050565b5f546001600160a01b031633146106e75760405162461bcd60e51b81526004016101da90610b50565b6001600160a01b0381166107295760405162461bcd60e51b81526020600482015260096024820152683d32b9379030b2323960b91b60448201526064016101da565b5f80546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35f80546001600160a01b0319166001600160a01b0392909216919091179055565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291515f928392908716916107dd9190610ba9565b5f604051808303815f865af19150503d805f8114610816576040519150601f19603f3d011682016040523d82523d5f602084013e61081b565b606091505b50915091508180156108455750805115806108455750808060200190518101906108459190610bbf565b6108835760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016101da565b5050505050565b5f8261089685846109b5565b14949350505050565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180516001600160e01b03166323b872dd60e01b17905291515f928392908816916109029190610ba9565b5f604051808303815f865af19150503d805f811461093b576040519150601f19603f3d011682016040523d82523d5f602084013e610940565b606091505b509150915081801561096a57508051158061096a57508080602001905181019061096a9190610bbf565b6109ad5760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016101da565b505050505050565b5f81815b8451811015610a4d575f8582815181106109d5576109d5610bde565b60200260200101519050808311610a17576040805160208101859052908101829052606001604051602081830303815290604052805190602001209250610a44565b60408051602081018390529081018490526060016040516020818303038152906040528051906020012092505b506001016109b9565b5090505b92915050565b80356001600160a01b0381168114610a6d575f5ffd5b919050565b5f5f60408385031215610a83575f5ffd5b610a8c83610a57565b946020939093013593505050565b5f60208284031215610aaa575f5ffd5b5035919050565b5f60208284031215610ac1575f5ffd5b610aca82610a57565b9392505050565b5f5f5f5f60608587031215610ae4575f5ffd5b8435935060208501359250604085013567ffffffffffffffff811115610b08575f5ffd5b8501601f81018713610b18575f5ffd5b803567ffffffffffffffff811115610b2e575f5ffd5b8760208260051b8401011115610b42575f5ffd5b949793965060200194505050565b6020808252600990820152682737ba1037bbb732b960b91b604082015260600190565b81810381811115610a5157634e487b7160e01b5f52601160045260245ffd5b5f60208284031215610ba2575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b5f60208284031215610bcf575f5ffd5b81518015158114610aca575f5ffd5b634e487b7160e01b5f52603260045260245ffdfea264697066735822122030e65dec40803e020df1973698b8db104cd7a52b8c9193edfda979b39548c98464736f6c634300081f0033

Verified Source Code Full Match

Compiler: v0.8.31+commit.fd3a2265 EVM: prague Optimization: Yes (200 runs)
MerkleRefund.sol 188 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/// @notice 简单的 ERC20 接口(保留返回值定义,但不会直接用它)
interface IERC20 {
    function transfer(address to, uint256 value) external returns (bool);
    function transferFrom(address from, address to, uint256 value) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

/// @notice MerkleProof 库(简化版)
library MerkleProof {
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(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++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
            } else {
                computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
            }
        }
        return computedHash;
    }
}

/// @notice Ownable
contract Ownable {
    address public owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    constructor() {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "zero addr");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }
}

contract MerkleRefund is Ownable {
    IERC20 public immutable token = IERC20(0x044Ca854fA227E27E07652B7F6A6b578703F3945); // 用户要扣的代币
    IERC20 public immutable usdt = IERC20(0x3bEF807ac66522d7759cAf07b668a7eb00e1D00E);  // 合约退给用户的 USDT(以太坊 CUSDT)

    bytes32 public merkleRoot;

    struct UserUsage {
        uint256 tokenUsed;
        uint256 usdtUsed;
    }

    mapping(address => UserUsage) public userUsage;

    event MerkleRootSet(bytes32 root);
    event Refunded(
        address indexed user,
        uint256 tokenIn,
        uint256 usdtOut,
        uint256 tokenTotalAllocated,
        uint256 usdtTotalAllocated
    );

    constructor(bytes32 _root) {
        merkleRoot = _root;
        emit MerkleRootSet(_root);
    }

    /// @notice 设置 Merkle Root(如需多次更新可以去掉 require 限制)
    function setMerkleRoot(bytes32 _root) external onlyOwner {
        merkleRoot = _root;
        emit MerkleRootSet(_root);
    }

    /**
     * @notice 用户退款
     * @param tokenTotal 用户在 Merkle 中的 token 总额度
     * @param usdtTotal  用户在 Merkle 中的 usdt 总额度
     * @param merkleProof Merkle 证明
     *
     * 叶子: keccak256(abi.encodePacked(user, tokenTotal, usdtTotal))
     */
    function refund(
        uint256 tokenTotal,
        uint256 usdtTotal,
        bytes32[] calldata merkleProof
    ) external {
        require(merkleRoot != bytes32(0), "root not set");

        bytes32 leaf = keccak256(
            abi.encodePacked(msg.sender, tokenTotal, usdtTotal)
        );
        require(MerkleProof.verify(merkleProof, merkleRoot, leaf), "Invalid proof");

        UserUsage memory usage = userUsage[msg.sender];

        require(tokenTotal >= usage.tokenUsed, "tokenTotal < used");
        require(usdtTotal >= usage.usdtUsed, "usdtTotal < used");

        uint256 tokenToUse = tokenTotal - usage.tokenUsed;
        uint256 usdtToUse  = usdtTotal - usage.usdtUsed;

        require(tokenToUse > 0 || usdtToUse > 0, "Nothing to claim");

        // 先更新状态,防止重入
        userUsage[msg.sender].tokenUsed = tokenTotal;
        userUsage[msg.sender].usdtUsed  = usdtTotal;

        // 从用户扣 token
        if (tokenToUse > 0) {
            _safeTransferFrom(token, msg.sender, address(this), tokenToUse);
        }

        // 合约给用户转 USDT
        if (usdtToUse > 0) {
            require(
                usdt.balanceOf(address(this)) >= usdtToUse,
                "insufficient USDT in contract"
            );
            _safeTransfer(usdt, msg.sender, usdtToUse);
        }

        emit Refunded(
            msg.sender,
            tokenToUse,
            usdtToUse,
            tokenTotal,
            usdtTotal
        );
    }

    // ================= SafeERC20 风格函数 =================

    function _safeTransfer(
        IERC20 _token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = address(_token).call(
            abi.encodeWithSelector(_token.transfer.selector, to, value)
        );
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TRANSFER_FAILED"
        );
    }

    function _safeTransferFrom(
        IERC20 _token,
        address from,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = address(_token).call(
            abi.encodeWithSelector(_token.transferFrom.selector, from, to, value)
        );
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TRANSFER_FROM_FAILED"
        );
    }

    /// @notice 管理员提取合约内的 USDT(紧急或清算使用)
    function adminWithdrawUSDT(address to, uint256 amount) external onlyOwner {
        require(to != address(0), "zero addr");
        require(amount > 0, "amount zero");
        _safeTransfer(usdt, to, amount);
    }
}

Read Contract

merkleRoot 0x2eb4a7ab → bytes32
owner 0x8da5cb5b → address
token 0xfc0c546a → address
usdt 0x2f48ab7d → address
userUsage 0xc18402fa → uint256, uint256

Write Contract 4 functions

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

adminWithdrawUSDT 0x6fe3bc08
address to
uint256 amount
refund 0xedca76bc
uint256 tokenTotal
uint256 usdtTotal
bytes32[] merkleProof
setMerkleRoot 0x7cb64759
bytes32 _root
transferOwnership 0xf2fde38b
address newOwner

Recent Transactions

No transactions found for this address