Address Contract Verified
Address
0xd09656a2EE7E5Ee3404fAce234e683D3337dA014
Balance
0 ETH
Nonce
1
Code Size
5489 bytes
Creator
0xeab8b983...1d8b at tx 0xf216a36e...f379fd
Indexed Transactions
0
Contract Bytecode
5489 bytes
0x608060405234801561001057600080fd5b50600436106101075760003560e01c80630222a2c41461010c578063068c526f14610135578063150b7a02146101555780631852e8d91461018d578063276184ae146101ae5780632c4e722e146101c157806334fcf437146101ca5780633f4ba83a146101df5780634665096d146101e7578063515a20ba146101f0578063598b8e71146102035780635c975abb146102165780635eac62391461022c578063715018a61461023f5780638456cb59146102475780638d8f2adb1461024f5780638da5cb5b14610257578063983d95ce1461025f578063b343ae1414610272578063e3a9db1a1461029d578063f2fde38b146102b0575b600080fd5b60035461011f906001600160a01b031681565b60405161012c91906113a3565b60405180910390f35b6101486101433660046111e9565b6102c3565b60405161012c9190611403565b610174610163366004611154565b630a85bd0160e11b95945050505050565b6040516001600160e01b0319909116815260200161012c565b6101a061019b3660046112bb565b61042d565b60405190815260200161012c565b60045461011f906001600160a01b031681565b6101a060065481565b6101dd6101d8366004611373565b61052f565b005b6101dd610563565b6101a060055481565b6101dd6101fe366004611373565b61059c565b6101dd6102113660046112e4565b6105db565b60025460ff16604051901515815260200161012c565b6101dd61023a3660046112e4565b610743565b6101dd6108af565b6101dd6108e8565b6101dd61091f565b61011f610a58565b6101dd61026d3660046112e4565b610a67565b6101a06102803660046112bb565b600860209081526000928352604080842090915290825290205481565b6101486102ab36600461113a565b610c6b565b6101dd6102be36600461113a565b610d42565b606081516001600160401b038111156102ec57634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610315578160200160208202803683370190505b50905060005b825181101561042557600083828151811061034657634e487b7160e01b600052603260045260246000fd5b6020026020010151905060086000866001600160a01b03166001600160a01b0316815260200190815260200160002060008281526020019081526020016000205461039343600554610de2565b61039d91906114dd565b6001600160a01b03861660009081526007602052604090206103bf9083610df8565b6103ca5760006103cd565b60015b60ff166006546103dd91906114be565b6103e791906114be565b83838151811061040757634e487b7160e01b600052603260045260246000fd5b6020908102919091010152508061041d816114f4565b91505061031b565b505b92915050565b6001600160a01b038216600090815260086020908152604080832084845290915281205460055461045f904390610de2565b116104a25760405162461bcd60e51b815260206004820152600e60248201526d496e76616c696420626c6f636b7360901b60448201526064015b60405180910390fd5b6001600160a01b03831660009081526008602090815260408083208584529091529020546005546104d4904390610de2565b6104de91906114dd565b6001600160a01b03841660009081526007602052604090206105009084610df8565b61050b57600061050e565b60015b60ff1660065461051e91906114be565b61052891906114be565b9392505050565b33610538610a58565b6001600160a01b03161461055e5760405162461bcd60e51b815260040161049990611471565b600655565b3361056c610a58565b6001600160a01b0316146105925760405162461bcd60e51b815260040161049990611471565b61059a610e04565b565b336105a5610a58565b6001600160a01b0316146105cb5760405162461bcd60e51b815260040161049990611471565b6105d581436114a6565b60055550565b60025460ff16156105fe5760405162461bcd60e51b815260040161049990611447565b6003546001600160a01b031633141561064b5760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b6044820152606401610499565b6106558282610743565b60005b8181101561073e576003546001600160a01b031663b88d4fde333086868681811061069357634e487b7160e01b600052603260045260246000fd5b905060200201356040518463ffffffff1660e01b81526004016106b8939291906113b7565b600060405180830381600087803b1580156106d257600080fd5b505af11580156106e6573d6000803e3d6000fd5b5050505061072b83838381811061070d57634e487b7160e01b600052603260045260246000fd5b33600090815260076020908152604090912093910201359050610e91565b5080610736816114f4565b915050610658565b505050565b60025460ff16156107665760405162461bcd60e51b815260040161049990611447565b60008061077543600554610de2565b905060005b8381101561081d576107b2338686848181106107a657634e487b7160e01b600052603260045260246000fd5b9050602002013561042d565b6107bc90846114a6565b3360009081526008602052604081209194508391908787858181106107f157634e487b7160e01b600052603260045260246000fd5b905060200201358152602001908152602001600020819055508080610815906114f4565b91505061077a565b5081156108a9576004805460405163a9059cbb60e01b81526001600160a01b039091169163a9059cbb916108559133918791016113ea565b602060405180830381600087803b15801561086f57600080fd5b505af1158015610883573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a79190611353565b505b50505050565b336108b8610a58565b6001600160a01b0316146108de5760405162461bcd60e51b815260040161049990611471565b61059a6000610e9d565b336108f1610a58565b6001600160a01b0316146109175760405162461bcd60e51b815260040161049990611471565b61059a610eed565b33610928610a58565b6001600160a01b03161461094e5760405162461bcd60e51b815260040161049990611471565b600480546040516370a0823160e01b81526000926001600160a01b03909216916370a0823191610980913091016113a3565b60206040518083038186803b15801561099857600080fd5b505afa1580156109ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d0919061138b565b6004805460405163a9059cbb60e01b81529293506001600160a01b03169163a9059cbb91610a029133918691016113ea565b602060405180830381600087803b158015610a1c57600080fd5b505af1158015610a30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a549190611353565b5050565b6000546001600160a01b031690565b60025460ff1615610a8a5760405162461bcd60e51b815260040161049990611447565b60026001541415610add5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610499565b6002600155610aec8282610743565b60005b81811015610c6257610b38838383818110610b1a57634e487b7160e01b600052603260045260246000fd5b33600090815260076020908152604090912093910201359050610df8565b610b835760405162461bcd60e51b815260206004820152601c60248201527b14dd185ada5b99ce881d1bdad95b881b9bdd0819195c1bdcda5d195960221b6044820152606401610499565b610bc4838383818110610ba657634e487b7160e01b600052603260045260246000fd5b33600090815260076020908152604090912093910201359050610f45565b506003546001600160a01b031663b88d4fde3033868686818110610bf857634e487b7160e01b600052603260045260246000fd5b905060200201356040518463ffffffff1660e01b8152600401610c1d939291906113b7565b600060405180830381600087803b158015610c3757600080fd5b505af1158015610c4b573d6000803e3d6000fd5b505050508080610c5a906114f4565b915050610aef565b50506001805550565b6001600160a01b0381166000908152600760205260408120606091610c8f82610f51565b6001600160401b03811115610cb457634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610cdd578160200160208202803683370190505b50905060005b610cec83610f51565b811015610d3a57610cfd8382610f5b565b828281518110610d1d57634e487b7160e01b600052603260045260246000fd5b602090810291909101015280610d32816114f4565b915050610ce3565b509392505050565b33610d4b610a58565b6001600160a01b031614610d715760405162461bcd60e51b815260040161049990611471565b6001600160a01b038116610dd65760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610499565b610ddf81610e9d565b50565b6000818310610df15781610528565b5090919050565b60006105288383610f67565b60025460ff16610e4d5760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610499565b6002805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b604051610e8791906113a3565b60405180910390a1565b60006105288383610f7f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60025460ff1615610f105760405162461bcd60e51b815260040161049990611447565b6002805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258610e7a3390565b60006105288383610fc9565b6000610427825490565b600061052883836110e6565b60009081526001919091016020526040902054151590565b6000610f8b8383610f67565b610fc157508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610427565b506000610427565b600081815260018301602052604081205480156110dc576000610fed6001836114dd565b8554909150600090611001906001906114dd565b905081811461108257600086600001828154811061102f57634e487b7160e01b600052603260045260246000fd5b906000526020600020015490508087600001848154811061106057634e487b7160e01b600052603260045260246000fd5b6000918252602080832090910192909255918252600188019052604090208390555b85548690806110a157634e487b7160e01b600052603160045260246000fd5b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610427565b6000915050610427565b600082600001828154811061110b57634e487b7160e01b600052603260045260246000fd5b9060005260206000200154905092915050565b80356001600160a01b038116811461113557600080fd5b919050565b60006020828403121561114b578081fd5b6105288261111e565b60008060008060006080868803121561116b578081fd5b6111748661111e565b94506111826020870161111e565b93506040860135925060608601356001600160401b03808211156111a4578283fd5b818801915088601f8301126111b7578283fd5b8135818111156111c5578384fd5b8960208285010111156111d6578384fd5b9699959850939650602001949392505050565b600080604083850312156111fb578182fd5b6112048361111e565b91506020838101356001600160401b0380821115611220578384fd5b818601915086601f830112611233578384fd5b81358181111561124557611245611525565b8060051b604051601f19603f8301168101818110858211171561126a5761126a611525565b604052828152858101935084860182860187018b1015611288578788fd5b8795505b838610156112aa57803585526001959095019493860193860161128c565b508096505050505050509250929050565b600080604083850312156112cd578182fd5b6112d68361111e565b946020939093013593505050565b600080602083850312156112f6578182fd5b82356001600160401b038082111561130c578384fd5b818501915085601f83011261131f578384fd5b81358181111561132d578485fd5b8660208260051b8501011115611341578485fd5b60209290920196919550909350505050565b600060208284031215611364578081fd5b81518015158114610528578182fd5b600060208284031215611384578081fd5b5035919050565b60006020828403121561139c578081fd5b5051919050565b6001600160a01b0391909116815260200190565b6001600160a01b039384168152919092166020820152604081019190915260806060820181905260009082015260a00190565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b8181101561143b5783518352928401929184019160010161141f565b50909695505050505050565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600082198211156114b9576114b961150f565b500190565b60008160001904831182151516156114d8576114d861150f565b500290565b6000828210156114ef576114ef61150f565b500390565b60006000198214156115085761150861150f565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220e3a13e49b220c03ba656327d67ef3ff41ca6a010eeca4311ad7d719865e6b6b364736f6c63430008040033
Verified Source Code Full Match
Compiler: v0.8.4+commit.c7e474f2
EVM: istanbul
Optimization: Yes (10 runs)
FishStaking.sol 181 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import '@openzeppelin/contracts/utils/math/Math.sol';
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract FishStaking is Ownable, IERC721Receiver, ReentrancyGuard, Pausable {
using EnumerableSet for EnumerableSet.UintSet;
//addresses
address nullAddress = 0x0000000000000000000000000000000000000000;
address public stakingDestinationAddress;
address public erc20Address;
//uint256's
uint256 public expiration;
//rate governs how often you receive your token
uint256 public rate;
// mappings
mapping(address => EnumerableSet.UintSet) private _deposits;
mapping(address => mapping(uint256 => uint256)) public _depositBlocks;
constructor(
address _stakingDestinationAddress,
uint256 _rate,
uint256 _expiration,
address _erc20Address
) {
stakingDestinationAddress = _stakingDestinationAddress;
rate = _rate;
expiration = block.number + _expiration;
erc20Address = _erc20Address;
_pause();
}
function pause() public onlyOwner {
_pause();
}
function unpause() public onlyOwner {
_unpause();
}
/* STAKING MECHANICS */
// Set a multiplier for how many tokens to earn each time a block passes.
function setRate(uint256 _rate) public onlyOwner() {
rate = _rate;
}
// Set this to a block to disable the ability to continue accruing tokens past that block number.
function setExpiration(uint256 _expiration) public onlyOwner() {
expiration = block.number + _expiration;
}
//check deposit amount.
function depositsOf(address account)
external
view
returns (uint256[] memory)
{
EnumerableSet.UintSet storage depositSet = _deposits[account];
uint256[] memory tokenIds = new uint256[] (depositSet.length());
for (uint256 i; i < depositSet.length(); i++) {
tokenIds[i] = depositSet.at(i);
}
return tokenIds;
}
function calculateRewards(address account, uint256[] memory tokenIds)
public
view
returns (uint256[] memory rewards)
{
rewards = new uint256[](tokenIds.length);
for (uint256 i; i < tokenIds.length; i++) {
uint256 tokenId = tokenIds[i];
rewards[i] =
rate *
(_deposits[account].contains(tokenId) ? 1 : 0) *
(Math.min(block.number, expiration) -
_depositBlocks[account][tokenId]);
}
return rewards;
}
//reward amount by address/tokenIds[]
function calculateReward(address account, uint256 tokenId)
public
view
returns (uint256)
{
require(Math.min(block.number, expiration) > _depositBlocks[account][tokenId], "Invalid blocks");
return rate *
(_deposits[account].contains(tokenId) ? 1 : 0) *
(Math.min(block.number, expiration) -
_depositBlocks[account][tokenId]);
}
//reward claim function
function claimRewards(uint256[] calldata tokenIds) public whenNotPaused {
uint256 reward;
uint256 blockCur = Math.min(block.number, expiration);
for (uint256 i; i < tokenIds.length; i++) {
reward += calculateReward(msg.sender, tokenIds[i]);
_depositBlocks[msg.sender][tokenIds[i]] = blockCur;
}
if (reward > 0) {
IERC20(erc20Address).transfer(msg.sender, reward);
}
}
//deposit function.
function deposit(uint256[] calldata tokenIds) external whenNotPaused {
require(msg.sender != stakingDestinationAddress, "Invalid address");
claimRewards(tokenIds);
for (uint256 i; i < tokenIds.length; i++) {
IERC721(stakingDestinationAddress).safeTransferFrom(
msg.sender,
address(this),
tokenIds[i],
""
);
_deposits[msg.sender].add(tokenIds[i]);
}
}
//withdrawal function.
function withdraw(uint256[] calldata tokenIds) external whenNotPaused nonReentrant() {
claimRewards(tokenIds);
for (uint256 i; i < tokenIds.length; i++) {
require(
_deposits[msg.sender].contains(tokenIds[i]),
"Staking: token not deposited"
);
_deposits[msg.sender].remove(tokenIds[i]);
IERC721(stakingDestinationAddress).safeTransferFrom(
address(this),
msg.sender,
tokenIds[i],
""
);
}
}
//withdrawal function.
function withdrawTokens() external onlyOwner {
uint256 tokenSupply = IERC20(erc20Address).balanceOf(address(this));
IERC20(erc20Address).transfer(msg.sender, tokenSupply);
}
function onERC721Received(
address,
address,
uint256,
bytes calldata
) external pure override returns (bytes4) {
return IERC721Receiver.onERC721Received.selector;
}
}
Context.sol 23 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
Ownable.sol 71 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_setOwner(_msgSender());
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
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);
}
}
Math.sol 42 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a >= b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a / b + (a % b == 0 ? 0 : 1);
}
}
Pausable.sol 90 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
IERC20.sol 81 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
SafeMath.sol 226 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// CAUTION
// This version of SafeMath should only be used with Solidity 0.8 or later,
// because it relies on the compiler's built in overflow checks.
/**
* @dev Wrappers over Solidity's arithmetic operations.
*
* NOTE: `SafeMath` is no longer needed starting with Solidity 0.8. The compiler
* now has built in overflow checking.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator.
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
IERC721.sol 142 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/
function balanceOf(address owner) external view returns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 tokenId
) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/
function approve(address to, uint256 tokenId) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/
function getApproved(uint256 tokenId) external view returns (address operator);
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/
function setApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/
function isApprovedForAll(address owner, address operator) external view returns (bool);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes calldata data
) external;
}
ReentrancyGuard.sol 62 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}
IERC165.sol 24 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
EnumerableSet.sol 356 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = valueIndex; // Replace lastvalue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
return _values(set._inner);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
IERC721Receiver.sol 26 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
IERC721Enumerable.sol 28 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "../IERC721.sol";
/**
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
* @dev See https://eips.ethereum.org/EIPS/eip-721
*/
interface IERC721Enumerable is IERC721 {
/**
* @dev Returns the total amount of tokens stored by the contract.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns a token ID owned by `owner` at a given `index` of its token list.
* Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
*/
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256 tokenId);
/**
* @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
* Use along with {totalSupply} to enumerate all tokens.
*/
function tokenByIndex(uint256 index) external view returns (uint256);
}
Read Contract
_depositBlocks 0xb343ae14 → uint256
calculateReward 0x1852e8d9 → uint256
calculateRewards 0x068c526f → uint256[]
depositsOf 0xe3a9db1a → uint256[]
erc20Address 0x276184ae → address
expiration 0x4665096d → uint256
onERC721Received 0x150b7a02 → bytes4
owner 0x8da5cb5b → address
paused 0x5c975abb → bool
rate 0x2c4e722e → uint256
stakingDestinationAddress 0x0222a2c4 → address
Write Contract 10 functions
These functions modify contract state and require a wallet transaction to execute.
claimRewards 0x5eac6239
uint256[] tokenIds
deposit 0x598b8e71
uint256[] tokenIds
pause 0x8456cb59
No parameters
renounceOwnership 0x715018a6
No parameters
setExpiration 0x515a20ba
uint256 _expiration
setRate 0x34fcf437
uint256 _rate
transferOwnership 0xf2fde38b
address newOwner
unpause 0x3f4ba83a
No parameters
withdraw 0x983d95ce
uint256[] tokenIds
withdrawTokens 0x8d8f2adb
No parameters
Recent Transactions
No transactions found for this address