编译器
0.8.10+commit.fc410830
文件 1 的 5:AxolittlesStaking.sol
pragma solidity ^0.8.10;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
interface IBubbles {
function mint(address recipient, uint amount) external;
}
contract AxolittlesStaking is Ownable {
address public constant AXOLITTLES = 0xf36446105fF682999a442b003f2224BcB3D82067;
address public immutable TOKEN;
uint public emissionPerBlock;
mapping(uint => uint) public stakeBlock;
mapping(uint => address) public stakeOwner;
event Stake(address indexed owner, uint tokenId);
event Unstake(address indexed owner, uint tokenId);
constructor(address _token, uint _emissionPerBlock) {
TOKEN = _token;
emissionPerBlock = _emissionPerBlock;
}
function stake(uint[] memory tokenIds) external {
for (uint i = 0; i < tokenIds.length; i++) {
IERC721(AXOLITTLES).transferFrom(msg.sender, address(this), tokenIds[i]);
stakeBlock[tokenIds[i]] = block.number;
stakeOwner[tokenIds[i]] = msg.sender;
emit Stake(msg.sender, tokenIds[i]);
}
}
function claim(uint[] memory tokenIds) external {
uint totalReward = 0;
for (uint i = 0; i < tokenIds.length; i++) {
uint token = tokenIds[i];
require(msg.sender == stakeOwner[token], "Only unstake your own axolittles");
totalReward += (block.number - stakeBlock[token]) * emissionPerBlock;
stakeBlock[token] = block.number;
}
IBubbles(TOKEN).mint(msg.sender, totalReward);
}
function unstake(uint[] memory tokenIds) external {
uint totalReward = 0;
for (uint i = 0; i < tokenIds.length; i++) {
uint token = tokenIds[i];
address owner = stakeOwner[token];
require(msg.sender == owner, "Only unstake your own axolittles");
totalReward += (block.number - stakeBlock[token]) * emissionPerBlock;
delete stakeOwner[token];
delete stakeBlock[token];
IERC721(AXOLITTLES).transferFrom(address(this), owner, token);
emit Unstake(msg.sender, tokenIds[i]);
}
IBubbles(TOKEN).mint(msg.sender, totalReward);
}
function unclaimedRewards(uint[] memory tokenIds) external view returns (uint[] memory) {
uint[] memory rewards = new uint[](tokenIds.length);
for (uint i = 0; i < tokenIds.length; i++) {
uint stakeBlockNumber = stakeBlock[tokenIds[i]];
if (stakeBlockNumber == 0) {
rewards[i] = 0;
} else {
rewards[i] = (block.number - stakeBlockNumber) * emissionPerBlock;
}
}
return rewards;
}
function setEmissionPerBlock(uint _emissionPerBlock) external onlyOwner {
emissionPerBlock = _emissionPerBlock;
}
}
文件 2 的 5:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 3 的 5:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 4 的 5:IERC721.sol
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function setApprovalForAll(address operator, bool _approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
文件 5 的 5:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_setOwner(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
{
"compilationTarget": {
"contracts/AxolittlesStaking.sol": "AxolittlesStaking"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_emissionPerBlock","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Unstake","type":"event"},{"inputs":[],"name":"AXOLITTLES","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emissionPerBlock","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":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_emissionPerBlock","type":"uint256"}],"name":"setEmissionPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakeBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"stakeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"unclaimedRewards","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"}]