账户
0xaf...907b
0xaf...907B

0xaf...907B

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.4+commit.c7e474f2
语言
Solidity
合同源代码
文件 1 的 4:ApeXPool3.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import "./interfaces/IApeXPool3.sol";
import "../utils/Ownable.sol";
import "../libraries/TransferHelper.sol";

contract ApeXPool3 is IApeXPool3, Ownable {
    address public override apeX;
    address public override esApeX;

    struct stakingInfo{
        address lockToken;
        address owner;
        uint256 accountId;
        uint256 amount;
        uint256 lockPeriod;
        uint256 lockStart;
        bool unlocked;
    }

    mapping(uint256 => stakingInfo) public stakingAPEX;
    mapping(uint256 => stakingInfo) public stakingEsAPEX;

    uint256 public globalStakeId;
    bool public override paused;

    constructor(address _apeX, address _esApeX, address _owner) {
        apeX = _apeX;
        esApeX = _esApeX;
        owner = _owner;
    }

    function setPaused(bool newState) external override onlyOwner {
        require(paused != newState, "same state");
        paused = newState;
        emit PausedStateChanged(newState);
    }

    function setApex(address _newApex) external override onlyOwner {
        require(_newApex != address(0));
        apeX = _newApex;
        emit ApexChanged(_newApex);
    }

    function setEsApex(address _newEsApex) external override onlyOwner {
        require(_newEsApex != address(0));
        esApeX = _newEsApex;
        emit EsApexChanged(_newEsApex);
    }

    function stakeAPEX(uint256 accountId, uint256 amount,uint256 lockPeriod) external override {
        require(!paused, "paused");
        require(apeX != address(0));
        TransferHelper.safeTransferFrom(apeX, msg.sender, address(this), amount);

        globalStakeId++;
        stakingAPEX[globalStakeId] = stakingInfo({
            lockToken: apeX,
            owner: msg.sender,
            accountId: accountId,
            amount: amount,
            lockPeriod: lockPeriod,
            lockStart: block.timestamp,
            unlocked: false
        });

        emit Staked(apeX, msg.sender, globalStakeId, accountId, amount,lockPeriod);
    }

    function stakeEsAPEX(uint256 accountId, uint256 amount,uint256 lockPeriod) external override {
        require(!paused, "paused");
        require(esApeX != address(0));
        TransferHelper.safeTransferFrom(esApeX, msg.sender, address(this), amount);
       
        globalStakeId++;
        stakingEsAPEX[globalStakeId] = stakingInfo({
            lockToken: esApeX,
            owner: msg.sender,
            accountId: accountId,
            amount: amount,
            lockPeriod: lockPeriod,
            lockStart: block.timestamp,
            unlocked: false
        });

        emit Staked(esApeX, msg.sender, globalStakeId, accountId, amount,lockPeriod);
    }

    function unstakeAPEX(uint256 stakeId) external override {
       _unstakeAPEX(stakeId);
    }

    function _unstakeAPEX(uint256 stakeId) private {
        stakingInfo memory info = stakingAPEX[stakeId];
        require(info.owner == msg.sender, "not allowed");
        require(info.lockStart+info.lockPeriod <= block.timestamp,"in lock period");
        require(info.lockToken == apeX, "apeX token mismatch");
        require(!info.unlocked,"already unlocked");

        TransferHelper.safeTransfer(apeX, info.owner, info.amount);
        stakingAPEX[stakeId].unlocked = true;
        emit Unstaked(stakeId);
    }

    function batchUnstakeAPEX(uint256[] calldata stakeIds) external  {
        for (uint i = 0; i < stakeIds.length; i++) {
            _unstakeAPEX(stakeIds[i]);
        }
    }

    function _unstakeEsAPEX(uint256 stakeId) private{
        stakingInfo memory info = stakingEsAPEX[stakeId];
        require(info.owner == msg.sender, "not allowed");
        require(info.lockStart+info.lockPeriod <= block.timestamp,"in lock period");
        require(info.lockToken == esApeX, "esApeX token mismatch");
        require(!info.unlocked,"already unlocked");

        TransferHelper.safeTransfer(esApeX, info.owner, info.amount);
        stakingEsAPEX[stakeId].unlocked = true;
        emit Unstaked(stakeId);
    }

    function unstakeEsAPEX(uint256 stakeId) external override {
        _unstakeEsAPEX(stakeId);
    }

    function batchUnstakeEsAPEX(uint256[] calldata stakeIds) external  {
        for (uint i = 0; i < stakeIds.length; i++) {
            _unstakeEsAPEX(stakeIds[i]);
        }
    }
}
合同源代码
文件 2 的 4:IApeXPool3.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

interface IApeXPool3 {
    event ApexChanged(address newApex);
    event EsApexChanged(address newEsApex);
    event PausedStateChanged(bool newState);
    event Staked(address indexed token, address indexed user, uint256 stakeId, uint256 accountId, uint256 amount, uint256 lockPeriod);
    event Unstaked(uint256 stakeId);

    function apeX() external view returns (address);

    function esApeX() external view returns (address);

    function paused() external view returns (bool);

    function setPaused(bool newState) external;

    function setApex(address newApex) external;

    function setEsApex(address newEsApex) external;

    function stakeAPEX(uint256 accountId, uint256 amount,uint256 lockPeriod) external;

    function stakeEsAPEX(uint256 accountId, uint256 amount,uint256 lockPeriod) external;

    function unstakeAPEX(uint256 stakeId) external;

    function unstakeEsAPEX(uint256 stakeId) external;
}
合同源代码
文件 3 的 4:Ownable.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

abstract contract Ownable {
    address public owner;
    address public pendingOwner;

    event NewOwner(address indexed oldOwner, address indexed newOwner);
    event NewPendingOwner(address indexed oldPendingOwner, address indexed newPendingOwner);

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

    function setPendingOwner(address newPendingOwner) external onlyOwner {
        require(pendingOwner != newPendingOwner, "Ownable: ALREADY_SET");
        emit NewPendingOwner(pendingOwner, newPendingOwner);
        pendingOwner = newPendingOwner;
    }

    function acceptOwner() external {
        require(msg.sender == pendingOwner, "Ownable: REQUIRE_PENDING_OWNER");
        address oldOwner = owner;
        address oldPendingOwner = pendingOwner;
        owner = pendingOwner;
        pendingOwner = address(0);
        emit NewOwner(oldOwner, owner);
        emit NewPendingOwner(oldPendingOwner, pendingOwner);
    }
}
合同源代码
文件 4 的 4:TransferHelper.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TransferHelper::safeApprove: approve failed"
        );
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TransferHelper::safeTransfer: transfer failed"
        );
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(
            success && (data.length == 0 || abi.decode(data, (bool))),
            "TransferHelper::transferFrom: transferFrom failed"
        );
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
    }
}
设置
{
  "compilationTarget": {
    "contracts/stakingV2/ApeXPool3.sol": "ApeXPool3"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"_apeX","type":"address"},{"internalType":"address","name":"_esApeX","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newApex","type":"address"}],"name":"ApexChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newEsApex","type":"address"}],"name":"EsApexChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"newState","type":"bool"}],"name":"PausedStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"accountId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"apeX","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"stakeIds","type":"uint256[]"}],"name":"batchUnstakeAPEX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"stakeIds","type":"uint256[]"}],"name":"batchUnstakeEsAPEX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"esApeX","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalStakeId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newApex","type":"address"}],"name":"setApex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newEsApex","type":"address"}],"name":"setEsApex","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"newState","type":"bool"}],"name":"setPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"accountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"stakeAPEX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"accountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"}],"name":"stakeEsAPEX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakingAPEX","outputs":[{"internalType":"address","name":"lockToken","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"accountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"lockStart","type":"uint256"},{"internalType":"bool","name":"unlocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakingEsAPEX","outputs":[{"internalType":"address","name":"lockToken","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"accountId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"lockPeriod","type":"uint256"},{"internalType":"uint256","name":"lockStart","type":"uint256"},{"internalType":"bool","name":"unlocked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"unstakeAPEX","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakeId","type":"uint256"}],"name":"unstakeEsAPEX","outputs":[],"stateMutability":"nonpayable","type":"function"}]