Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0xeafc14e2Af750FF52C13349F13fA3A1bf9061497
Balance 0 ETH
Nonce 1
Code Size 3503 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

3503 bytes
0x608080604052600436101561001357600080fd5b60003560e01c9081630f7921ed14610b34575080632e586cab14610a7a578063379607f5146108e2578063492daeac146105575780634bedf369146104c95780636aff4fbd1461034e5780638da5cb5b14610325578063b8152395146102d4578063b9ec526b146102b6578063c8972f311461027c578063e63ea408146101a8578063ef5d9ae81461016e5763f2fde38b146100ae57600080fd5b34610169576020366003190112610169576100c7610bbd565b600054906001600160a01b038216906100e1338314610c31565b6001600160a01b0316918215610128576001600160a01b031916821760009081557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09080a3005b60405162461bcd60e51b81526020600482015260196024820152784e6577206f776e6572206973207a65726f206164647265737360381b6044820152606490fd5b600080fd5b34610169576020366003190112610169576001600160a01b0361018f610bbd565b1660005260046020526020604060002054604051908152f35b34610169576060366003190112610169576101c1610bbd565b6024356001600160a01b0381169182820361016957604435916101ef60018060a01b03600054163314610c31565b83156102375781610224846020937ff24ef89f38eadc1bde50701ad6e4d6d11a2dc24f7cf834a486991f388332850495610c9a565b6040519384526001600160a01b031692a3005b60405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f7420776974686472617720746f207a65726f2061646472657373006044820152606490fd5b34610169576020366003190112610169576001600160a01b0361029d610bbd565b1660005260036020526020604060002054604051908152f35b34610169576000366003190112610169576020600154604051908152f35b3461016957602036600319011261016957602061031d6001600160a01b036102fa610bbd565b168060005260038352604060002054906000526004835260406000205490610c8d565b604051908152f35b34610169576000366003190112610169576000546040516001600160a01b039091168152602090f35b34610169576060366003190112610169576004356024356044359061037e60018060a01b03600054163314610c31565b82600052600260205260406000209060ff60048301541661046d577f8457997e1aebad9017da1580f22476860b49a185d33aa2e2b2be2a85564f91f0928260026080940192828454948260038501918254958883036103f4575b50505055604051938452602084015260408301526060820152a2005b88831115610437576104068984610c8d565b906001808060a01b0391015416600052600360205261042b6040600020918254610c24565b90555b55828a806103d8565b610441838a610c8d565b906001808060a01b039101541660005260036020526104666040600020918254610c8d565b905561042e565b60405162461bcd60e51b815260206004820152602e60248201527f416c726561647920636c61696d65642e2043616e6e6f7420757064617465206360448201526d3630b4b6b2b2103932b1b7b9321760911b6064820152608490fd5b3461016957602036600319011261016957600480356000908152600260208181526040928390208054600182015493820154600383015496830154600584015460069094015487516001600160a01b039485168152939096169483019490945294810194909452606084019490945260ff161515608083015260a082019290925260c081019190915260e090f35b34610169576080366003190112610169576004356001600160401b03811161016957610587903690600401610bd3565b6024356001600160401b038111610169576105a6903690600401610bd3565b6044356001600160401b038111610169576105c5903690600401610bd3565b9490916064356001600160401b038111610169576105e7903690600401610bd3565b9590936105ff60018060a01b03600054163314610c31565b828214806108d9575b806108d0575b156108935760005b82811061061f57005b600154600019811461087d57600101908160015561063e818a89610c69565b356212750081019283821161087d578b918a9161067f8561067861066d828d8f61066d8f849061067293610c69565b610c79565b98610c69565b9589610c69565b35936040519460e08601948686106001600160401b038711176108675760409586526001600160a01b0390811687529182166020808801918252878701928352606088018a8152600060808a0181815260a08b0182815260c08c01998a52978252600293849052989020985189549086166001600160a01b0319918216178a55925160018a01805491909616931692909217909355905191860191909155516003850155915160048401805460ff191691151560ff169190911790559051600583015551600690910155610754818b85610c69565b356001600160a01b0361076b61066d84898d610c69565b1660005260036020526107846040600020918254610c24565b90556001600160a01b0361079c61066d83878a610c69565b166000526005602052604060002091600154908354600160401b8110156108675760018101808655811015610851577f7c011f68b0ad48752bc63f93a5f632449876825ae3a0496c7e968001feb4e22160408e61082e878f9761066d8f978f8f61066d60019f610821926108279789968793600052602060002001556001549d610c69565b9b610c69565b928b610c69565b359482519586526020860152878060a01b031694878060a01b031693a401610616565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60405162461bcd60e51b8152602060048201526015602482015274082e4e4c2f240d8cadccee8d040dad2e6dac2e8c6d605b1b6044820152606490fd5b5086881461060e565b50878314610608565b3461016957602036600319011261016957600435600081815260026020526040902080546001600160a01b03163303610a445760038101544210610a085760048101805460ff81166109cf5760019060ff191617905560058101914283557f3e356ee9071ea983e847cc7da7b8b224b8f44262f7c9ce77262ea0e854a5442c60406002840194855494600181019560018060a01b03875416600052600460205261099184600020918254610c24565b9055855487546109ab9133906001600160a01b0316610c9a565b54945495549054825191825260208201526001600160a01b039586169590941693a4005b60405162461bcd60e51b815260206004820152601160248201527020b63932b0b23c903bb4ba34323930bbb760791b6044820152606490fd5b60405162461bcd60e51b81526020600482015260146024820152734e6f742074696d6520746f20776974686472617760601b6044820152606490fd5b60405162461bcd60e51b815260206004820152600e60248201526d2737ba1038bab2bab2903ab9b2b960911b6044820152606490fd5b34610169576020366003190112610169576001600160a01b03610a9b610bbd565b16600052600560205260406000206040518060208354918281520190819360005260206000209060005b818110610b1e5750505081610adb910382610c03565b6040519182916020830190602084525180915260408301919060005b818110610b05575050500390f35b8251845285945060209384019390920191600101610af7565b8254845260209093019260019283019201610ac5565b346101695760203660031901126101695760048035600090815260026020818152604092839020805460018201549382015460038301549683015460058401546006909401546001600160a01b039384168a52929095169388019390935293860191909152606085019390935260ff161515608084015260a083019190915260c082015260e090f35b600435906001600160a01b038216820361016957565b9181601f84011215610169578235916001600160401b038311610169576020808501948460051b01011161016957565b90601f801991011681019081106001600160401b0382111761086757604052565b9190820180921161087d57565b15610c3857565b60405162461bcd60e51b81526020600482015260096024820152682737ba1037bbb732b960b91b6044820152606490fd5b91908110156108515760051b0190565b356001600160a01b03811681036101695790565b9190820391821161087d57565b60405163a9059cbb60e01b81526001600160a01b039283166004820152602481019390935260209183916044918391600091165af1908115610d6d57600091610d2b575b5015610ce657565b60405162461bcd60e51b815260206004820152601d60248201527f536166655472616e736665723a207472616e73666572206661696c65640000006044820152606490fd5b6020813d602011610d65575b81610d4460209383610c03565b81010312610d615751908115158203610d5e575038610cde565b80fd5b5080fd5b3d9150610d37565b6040513d6000823e3d90fdfea2646970667358221220964205fce95a6e73c7fc9a81e63d04286939ac0401fa717f5f597e65531163ba64736f6c634300081c0033

Verified Source Code Full Match

Compiler: v0.8.28+commit.7893614a EVM: paris Optimization: Yes (20 runs)
WithdrawalQueue.sol 245 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.28;

/**
 * @dev 与标准 ERC20 类似,但仅包含 transfer,供演示用
 */
interface IERC20 {
    function transfer(address recipient, uint256 amount) external returns (bool);
}

contract WithdrawalQueue {

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

    event QueueAdded(
        uint256 indexed queueId,
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 earliestWithdrawal
    );

    event Claimed(
        uint256 indexed queueId,
        address indexed user,
        address indexed token,
        uint256 amount,
        uint256 claimTime
    );

    event QueueUpdated(
        uint256 indexed queueId,
        uint256 oldAmount,
        uint256 newAmount,
        uint256 oldEarliestWithdrawal,
        uint256 newEarliestWithdrawal
    );

    event EmergencyWithdraw(address indexed token, address indexed to, uint256 amount);

    address public owner;

    /**
     * @dev 提款队列信息
     */
    struct QueueInfo {
        address user;
        address token;
        uint256 amount;
        uint256 earliestWithdrawal; // = requestTime + 14 days
        bool claimed;
        uint256 claimTime;
        uint256 requestTime;
    }

    uint256 public currentQueueId;

    // 队列ID => 队列信息
    mapping(uint256 => QueueInfo) public queues;

    // 统计每个 Token:
    //   totalAdded[token]   = 通过 addWithdrawalQueueBatch() 添加的总量
    //   totalClaimed[token] = 已经被 claim() 领取的总量
    mapping(address => uint256) public totalAdded;
    mapping(address => uint256) public totalClaimed;

    // 每个用户对应的所有队列 ID
    mapping(address => uint256[]) private userQueueIds;

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

    constructor() {
        owner = msg.sender;
    }

    function claim(uint256 claimId) external {
        QueueInfo storage qInfo = queues[claimId];

        require(qInfo.user == msg.sender, "Not queue user");
        require(block.timestamp >= qInfo.earliestWithdrawal, "Not time to withdraw");
        require(!qInfo.claimed, "Already withdrawn");

        qInfo.claimed = true;
        qInfo.claimTime = block.timestamp;

        totalClaimed[qInfo.token] += qInfo.amount;

        _safeTransfer(qInfo.token, msg.sender, qInfo.amount);

        emit Claimed(
            claimId,
            qInfo.user,
            qInfo.token,
            qInfo.amount,
            qInfo.claimTime
        );
    }

    /**
     * @dev 批量添加取款队列
     * @param users   用户地址数组
     * @param tokens  Token 地址数组
     * @param amounts 金额数组
     * @param times   请求发起时间数组
     *
     * 注意:最早可提款时间 = 请求时间 + 14 days
     */
    function addWithdrawalQueueBatch(
        address[] calldata users,
        address[] calldata tokens,
        uint256[] calldata amounts,
        uint256[] calldata times
    ) external onlyOwner {
        require(
            users.length == tokens.length &&
            tokens.length == amounts.length &&
            amounts.length == times.length,
            "Array length mismatch"
        );

        for (uint256 i = 0; i < users.length; i++) {
            currentQueueId++;

            uint256 requestTime = times[i];
            uint256 earliest = requestTime + 14 days;

            queues[currentQueueId] = QueueInfo({
                user: users[i],
                token: tokens[i],
                amount: amounts[i],
                earliestWithdrawal: earliest,
                claimed: false,
                claimTime: 0,
                requestTime: requestTime
            });

            totalAdded[tokens[i]] += amounts[i];
            userQueueIds[users[i]].push(currentQueueId);

            emit QueueAdded(
                currentQueueId,
                users[i],
                tokens[i],
                amounts[i],
                earliest
            );
        }
    }

    function emergencyWithdraw(address token, address to, uint256 amount) external onlyOwner {
        require(to != address(0), "Cannot withdraw to zero address");
        
        _safeTransfer(token, to, amount);

        emit EmergencyWithdraw(token, to, amount);
    }

    function updateQueueInfo(
        uint256 claimId,
        uint256 newAmount,
        uint256 newEarliestWithdrawal
    ) external onlyOwner {
        QueueInfo storage qInfo = queues[claimId];
        require(!qInfo.claimed, "Already claimed. Cannot update claimed record.");

        uint256 oldAmount = qInfo.amount;
        uint256 oldEarliestWithdrawal = qInfo.earliestWithdrawal;

        // 更新金额
        if (newAmount != oldAmount) {
            if (newAmount > oldAmount) {
                totalAdded[qInfo.token] += (newAmount - oldAmount);
            } else {
                totalAdded[qInfo.token] -= (oldAmount - newAmount);
            }
            qInfo.amount = newAmount;
        }

        // 更新最早可领取时间
        qInfo.earliestWithdrawal = newEarliestWithdrawal;

        emit QueueUpdated(
            claimId,
            oldAmount,
            newAmount,
            oldEarliestWithdrawal,
            newEarliestWithdrawal
        );
    }

    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "New owner is zero address");
        address oldOwner = owner;
        owner = newOwner;

        emit OwnershipTransferred(oldOwner, newOwner);
    }

    function getUserQueueIds(address user) external view returns (uint256[] memory) {
        return userQueueIds[user];
    }

    /**
     * @dev 获取某个 Token 剩余待领取的数量
     */
    function getUnclaimedAmount(address token) external view returns (uint256) {
        return totalAdded[token] - totalClaimed[token];
    }

    /**
     * @dev 获取某个队列的详细信息
     */
    function getQueueInfo(uint256 claimId)
        external
        view
        returns (
            address user,
            address token,
            uint256 amount,
            uint256 earliestWithdrawal,
            bool claimed,
            uint256 claimTime,
            uint256 requestTime
        )
    {
        QueueInfo storage qInfo = queues[claimId];
        return (
            qInfo.user,
            qInfo.token,
            qInfo.amount,
            qInfo.earliestWithdrawal,
            qInfo.claimed,
            qInfo.claimTime,
            qInfo.requestTime
        );
    }

    function _safeTransfer(address token, address to, uint256 amount) internal {
        bool success = IERC20(token).transfer(to, amount);
        require(success, "SafeTransfer: transfer failed");
    }
}

Read Contract

currentQueueId 0xb9ec526b → uint256
getQueueInfo 0x4bedf369 → address, address, uint256, uint256, bool, uint256, uint256
getUnclaimedAmount 0xb8152395 → uint256
getUserQueueIds 0x2e586cab → uint256[]
owner 0x8da5cb5b → address
queues 0x0f7921ed → address, address, uint256, uint256, bool, uint256, uint256
totalAdded 0xc8972f31 → uint256
totalClaimed 0xef5d9ae8 → uint256

Write Contract 5 functions

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

addWithdrawalQueueBatch 0x492daeac
address[] users
address[] tokens
uint256[] amounts
uint256[] times
claim 0x379607f5
uint256 claimId
emergencyWithdraw 0xe63ea408
address token
address to
uint256 amount
transferOwnership 0xf2fde38b
address newOwner
updateQueueInfo 0x6aff4fbd
uint256 claimId
uint256 newAmount
uint256 newEarliestWithdrawal

Recent Transactions

No transactions found for this address