编译器
0.8.11+commit.d7f03943
文件 1 的 6:AdventurerStaking.sol
pragma solidity ^0.8.11;
import "./IAdventurerStaking.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
interface IAdventurer {
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
}
interface IChronos {
function grantChronos(address to, uint256 amount) external;
}
contract AdventurerStaking is IAdventurerStaking, Ownable, ERC721Holder {
IAdventurer public adventurerContract;
IChronos public chronosContract;
mapping(uint64 => StakedToken) public stakes;
uint64 private constant NINETY_DAYS = 7776000;
uint64 public LOCK_IN = 0;
bool grantChronos = true;
uint256 public constant BASE_RATE = 5 ether;
constructor(
address _adventurerContract,
address _chronosContract,
address _ownerAddress
) {
require(
_adventurerContract != address(0),
"nft contract cannot be 0x0"
);
require(
_chronosContract != address(0),
"chronos contract cannot be 0x0"
);
adventurerContract = IAdventurer(_adventurerContract);
chronosContract = IChronos(_chronosContract);
if (_ownerAddress != msg.sender) {
transferOwnership(_ownerAddress);
}
}
function viewStakes(address _address)
external
view
returns (uint256[] memory)
{
uint256[] memory _tokens = new uint256[](7500);
uint256 tookCount = 0;
for (uint64 i = 0; i < 7500; i++) {
if (stakes[i].user == _address) {
_tokens[tookCount] = i;
tookCount++;
}
}
uint256[] memory trimmedResult = new uint256[](tookCount);
for (uint256 j = 0; j < trimmedResult.length; j++) {
trimmedResult[j] = _tokens[j];
}
return trimmedResult;
}
function stake(uint64 tokenId) public override {
stakes[tokenId] = StakedToken(msg.sender, uint64(block.timestamp));
emit StartStake(msg.sender, tokenId);
adventurerContract.safeTransferFrom(
msg.sender,
address(this),
uint256(tokenId)
);
}
function groupStake(uint64[] memory tokenIds) external override {
for (uint64 i = 0; i < tokenIds.length; ++i) {
stake(tokenIds[i]);
}
}
function unstake(uint64 tokenId) public override {
require(stakes[tokenId].user != address(0), "tokenId not staked");
require(
stakes[tokenId].user == msg.sender,
"sender didn't stake token"
);
uint64 stakeLength = uint64(block.timestamp) -
stakes[tokenId].timeStaked;
require(
stakeLength > LOCK_IN, "can not remove token until lock-in period is over"
);
if (grantChronos) {
uint256 calcrew = (BASE_RATE * uint256(stakeLength)) /86400;
chronosContract.grantChronos(msg.sender, calcrew);
}
emit Unstake(
msg.sender,
tokenId,
stakeLength > NINETY_DAYS,
stakeLength
);
delete stakes[tokenId];
adventurerContract.safeTransferFrom(
address(this),
msg.sender,
uint256(tokenId)
);
}
function groupUnstake(uint64[] memory tokenIds) external override {
for (uint64 i = 0; i < tokenIds.length; ++i) {
unstake(tokenIds[i]);
}
}
function setGrantChronos(bool _grant) external onlyOwner {
grantChronos = _grant;
}
function setLockIn(uint64 lockin) external onlyOwner {
LOCK_IN = lockin;
}
}
文件 2 的 6: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 的 6:ERC721Holder.sol
pragma solidity ^0.8.0;
import "../IERC721Receiver.sol";
contract ERC721Holder is IERC721Receiver {
function onERC721Received(
address,
address,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}
文件 4 的 6:IAdventurerStaking.sol
pragma solidity ^0.8.11;
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
interface IAdventurerStaking is IERC721Receiver {
struct StakedToken {
address user;
uint64 timeStaked;
}
event StartStake(address indexed owner, uint64 tokenId);
event Unstake(
address indexed owner,
uint64 tokenId,
bool success,
uint64 duration
);
function stake(uint64 tokenId) external;
function groupStake(uint64[] memory tokenIds) external;
function unstake(uint64 tokenId) external;
function groupUnstake(uint64[] memory tokenIds) external;
}
文件 5 的 6:IERC721Receiver.sol
pragma solidity ^0.8.0;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 6 的 6: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() {
_transferOwnership(_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 {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
{
"compilationTarget": {
"contracts/AdventurerStaking.sol": "AdventurerStaking"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"_adventurerContract","type":"address"},{"internalType":"address","name":"_chronosContract","type":"address"},{"internalType":"address","name":"_ownerAddress","type":"address"}],"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":"uint64","name":"tokenId","type":"uint64"}],"name":"StartStake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint64","name":"tokenId","type":"uint64"},{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint64","name":"duration","type":"uint64"}],"name":"Unstake","type":"event"},{"inputs":[],"name":"BASE_RATE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LOCK_IN","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adventurerContract","outputs":[{"internalType":"contract IAdventurer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chronosContract","outputs":[{"internalType":"contract IChronos","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"tokenIds","type":"uint64[]"}],"name":"groupStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"tokenIds","type":"uint64[]"}],"name":"groupUnstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","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":"bool","name":"_grant","type":"bool"}],"name":"setGrantChronos","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"lockin","type":"uint64"}],"name":"setLockIn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"","type":"uint64"}],"name":"stakes","outputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint64","name":"timeStaked","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"tokenId","type":"uint64"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"viewStakes","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"}]