账户
0xc8...068e
0xc8...068E

0xc8...068E

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.22+commit.4fc1097e
语言
Solidity
合同源代码
文件 1 的 1:PIKASTAKE.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.22;

interface IPIKA {
    function transfer(address, uint256) external returns(bool);
    function transferFrom(address, address, uint256) external returns(bool);
}

contract PIKASTAKE {

    address public constant PIKA = 0xa9D54F37EbB99f83B603Cc95fc1a5f3907AacCfd;

    uint256 public constant blockReward = 1600000 * (10 ** 18);

    uint256 public constant SCALE = 10 ** 18;

    mapping(address => uint256) public balances;
    mapping(address => uint256) public accruedInitialPIKA;

    uint256 public accruedPIKA;
    uint256 public totalStaked;

    uint256 public blockLastUpdate;
    uint256 public blockLastReward;

    event Stake(address indexed staker, uint256 amount);
    event Unstake(address indexed staker, uint256 amount);
    event Restake(address indexed staker, uint256 reward);
    event Claim(address indexed staker, uint256 reward);

    event Accrue(uint256 accruedPIKA);

    constructor() {
        accruedPIKA = 10 ** 18;
        totalStaked = 10 ** 18;

        blockLastUpdate = block.number + 100800;
        blockLastReward = block.number + 7988736;
    }

    function stake(uint256 amount) public {
        restake();

        balances[msg.sender] += amount;

        totalStaked += amount;

        IPIKA(PIKA).transferFrom(msg.sender, address(this), amount);

        emit Stake(msg.sender, amount);
    }

    function unstake(uint256 amount) public {
        restake();

        balances[msg.sender] -= amount;

        totalStaked -= amount;

        IPIKA(PIKA).transfer(msg.sender, amount);

        emit Unstake(msg.sender, amount);
    }

    function unstakeAll() public {
        unstake(balances[msg.sender] + unclaimed(msg.sender));
    }

    function restake() public {
        accrue();

        uint256 accruedProfit = accruedPIKA - accruedInitialPIKA[msg.sender];

        uint256 reward = (accruedProfit * balances[msg.sender]) / SCALE;

        balances[msg.sender] += reward;

        totalStaked += reward;

        accruedInitialPIKA[msg.sender] = accruedPIKA;

        emit Restake(msg.sender, reward);
    }

    function claim() public {
        accrue();

        uint256 accruedProfit = accruedPIKA - accruedInitialPIKA[msg.sender];

        uint256 reward = (accruedProfit * balances[msg.sender]) / SCALE;

        accruedInitialPIKA[msg.sender] = accruedPIKA;

        IPIKA(PIKA).transfer(msg.sender, reward);

        emit Claim(msg.sender, reward);
    }

    function accrue() public {

        if (blockLastUpdate < block.number) {

            uint256 blockDistance;

            if (block.number < blockLastReward) {
                blockDistance = block.number - blockLastUpdate;
                blockLastUpdate = block.number;
            } else {
                blockDistance = blockLastReward - blockLastUpdate;
                blockLastUpdate = type(uint256).max;
            }

            accruedPIKA += (blockReward * blockDistance * SCALE) / totalStaked;

            emit Accrue(accruedPIKA);
        }
    }

    function unclaimed(address staker) public view returns(uint256 reward) {

        uint256 accruedHypotheticalPIKA = accruedPIKA;

        if (blockLastUpdate < block.number) {

            uint256 blockDistance;

            if (block.number < blockLastReward) {
                blockDistance = block.number - blockLastUpdate;
            } else {
                blockDistance = blockLastReward - blockLastUpdate;
            }

            accruedHypotheticalPIKA += (blockReward * blockDistance * SCALE) / totalStaked;
        }

        uint256 accruedProfit = accruedHypotheticalPIKA - accruedInitialPIKA[staker];

        reward = (accruedProfit * balances[staker]) / SCALE;

        return reward;
    }

    function apr() public view returns(uint256 rate) {
        return (420690000000000 * (10 ** 18)) / totalStaked;
    }
}
设置
{
  "compilationTarget": {
    "PIKASTAKE.sol": "PIKASTAKE"
  },
  "evmVersion": "shanghai",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"accruedPIKA","type":"uint256"}],"name":"Accrue","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"Restake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstake","type":"event"},{"inputs":[],"name":"PIKA","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SCALE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accrue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accruedInitialPIKA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accruedPIKA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"apr","outputs":[{"internalType":"uint256","name":"rate","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockLastReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockLastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"blockReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"restake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"unclaimed","outputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakeAll","outputs":[],"stateMutability":"nonpayable","type":"function"}]