Address Contract Verified
Address
0x46E7007d6515B4f260f3CbC82f4672622eace802
Balance
0 ETH
Nonce
1
Code Size
5557 bytes
Creator
0x25b3ea33...0137 at tx 0x5ecc9af9...917c1e
Indexed Transactions
0
Contract Bytecode
5557 bytes
0x608060405234801561000f575f80fd5b506004361061009c575f3560e01c80637b0472f0116100645780637b0472f0146101475780638da5cb5b14610163578063999ffd9714610181578063cf57ee69146101b1578063f2fde38b146101e15761009c565b8063379607f5146100a05780634a84c9ee146100bc578063584b62a1146100ec57806369a6d6b91461011f578063715018a61461013d575b5f80fd5b6100ba60048036038101906100b59190610de0565b6101fd565b005b6100d660048036038101906100d19190610e65565b6104f0565b6040516100e39190610eb2565b60405180910390f35b61010660048036038101906101019190610e65565b610546565b6040516101169493929190610ee5565b60405180910390f35b610127610598565b6040516101349190610f83565b60405180910390f35b6101456105bd565b005b610161600480360381019061015c9190610f9c565b6105d0565b005b61016b61092e565b6040516101789190610fe9565b60405180910390f35b61019b60048036038101906101969190610e65565b610955565b6040516101a89190610eb2565b60405180910390f35b6101cb60048036038101906101c69190611002565b610a5a565b6040516101d89190610eb2565b60405180910390f35b6101fb60048036038101906101f69190611002565b610aa3565b005b60025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2080549050811061027f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161027690611087565b60405180910390fd5b5f60025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2082815481106102cf576102ce6110a5565b5b905f5260205f2090600402019050806003015f9054906101000a900460ff161561032e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016103259061111c565b60405180910390fd5b806002015481600101546103429190611167565b421015610384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161037b906111e4565b60405180910390fd5b6001816003015f6101000a81548160ff0219169083151502179055505f6103b2825f01548360020154610b27565b905060015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb3383855f01546104019190611167565b6040518363ffffffff1660e01b815260040161041e929190611202565b6020604051808303815f875af115801561043a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045e9190611253565b61049d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610494906112c8565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff167fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a846040516104e39190610eb2565b60405180910390a2505050565b5f60035f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f2054905092915050565b6002602052815f5260405f20818154811061055f575f80fd5b905f5260205f2090600402015f9150915050805f015490806001015490806002015490806003015f9054906101000a900460ff16905084565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6105c5610bb9565b6105ce5f610c40565b565b5f8211610612576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161060990611330565b60405180910390fd5b621baf8081148061062557506276a70081145b80610632575062ed4e0081145b8061064057506301da9c0081145b61067f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161067690611398565b60405180910390fd5b61068a338383610d01565b60015f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b81526004016106e8939291906113b6565b6020604051808303815f875af1158015610704573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107289190611253565b610767576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161075e906112c8565b60405180910390fd5b60025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2060405180608001604052808481526020014281526020018381526020015f1515815250908060018154018082558091505060019003905f5260205f2090600402015f909190919091505f820151815f015560208201518160010155604082015181600201556060820151816003015f6101000a81548160ff02191690831515021790555050508160035f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8381526020019081526020015f205f8282546108859190611167565b925050819055503373ffffffffffffffffffffffffffffffffffffffff167fb4caaf29adda3eefee3ad552a8e85058589bf834c7466cae4ee58787f70589ed8383600160025f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054905061091391906113eb565b6040516109229392919061141e565b60405180910390a25050565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b5f60025f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f208054905082106109a5575f9050610a54565b5f60025f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2083815481106109f5576109f46110a5565b5b905f5260205f2090600402019050806003015f9054906101000a900460ff1680610a31575080600201548160010154610a2e9190611167565b42105b15610a3f575f915050610a54565b610a50815f01548260020154610b27565b9150505b92915050565b5f60025f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20805490509050919050565b610aab610bb9565b5f73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610b1b575f6040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600401610b129190610fe9565b60405180910390fd5b610b2481610c40565b50565b5f8062010f9090505f621baf808403610b435760019050610b8a565b6276a7008403610b565760049050610b89565b62ed4e008403610b695760089050610b88565b6301da9c008403610b7d5760109050610b87565b5f92505050610bb3565b5b5b5b612710818387610b9a9190611453565b610ba49190611453565b610bae91906114c1565b925050505b92915050565b610bc1610da2565b73ffffffffffffffffffffffffffffffffffffffff16610bdf61092e565b73ffffffffffffffffffffffffffffffffffffffff1614610c3e57610c02610da2565b6040517f118cdaa7000000000000000000000000000000000000000000000000000000008152600401610c359190610fe9565b60405180910390fd5b565b5f805f9054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050815f806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35050565b6101f48260035f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8481526020019081526020015f2054610d5c9190611167565b1115610d9d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d9490611561565b60405180910390fd5b505050565b5f33905090565b5f80fd5b5f819050919050565b610dbf81610dad565b8114610dc9575f80fd5b50565b5f81359050610dda81610db6565b92915050565b5f60208284031215610df557610df4610da9565b5b5f610e0284828501610dcc565b91505092915050565b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f610e3482610e0b565b9050919050565b610e4481610e2a565b8114610e4e575f80fd5b50565b5f81359050610e5f81610e3b565b92915050565b5f8060408385031215610e7b57610e7a610da9565b5b5f610e8885828601610e51565b9250506020610e9985828601610dcc565b9150509250929050565b610eac81610dad565b82525050565b5f602082019050610ec55f830184610ea3565b92915050565b5f8115159050919050565b610edf81610ecb565b82525050565b5f608082019050610ef85f830187610ea3565b610f056020830186610ea3565b610f126040830185610ea3565b610f1f6060830184610ed6565b95945050505050565b5f819050919050565b5f610f4b610f46610f4184610e0b565b610f28565b610e0b565b9050919050565b5f610f5c82610f31565b9050919050565b5f610f6d82610f52565b9050919050565b610f7d81610f63565b82525050565b5f602082019050610f965f830184610f74565b92915050565b5f8060408385031215610fb257610fb1610da9565b5b5f610fbf85828601610dcc565b9250506020610fd085828601610dcc565b9150509250929050565b610fe381610e2a565b82525050565b5f602082019050610ffc5f830184610fda565b92915050565b5f6020828403121561101757611016610da9565b5b5f61102484828501610e51565b91505092915050565b5f82825260208201905092915050565b7f496e76616c696420696e646578000000000000000000000000000000000000005f82015250565b5f611071600d8361102d565b915061107c8261103d565b602082019050919050565b5f6020820190508181035f83015261109e81611065565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b7f416c726561647920636c61696d656400000000000000000000000000000000005f82015250565b5f611106600f8361102d565b9150611111826110d2565b602082019050919050565b5f6020820190508181035f830152611133816110fa565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61117182610dad565b915061117c83610dad565b92508282019050808211156111945761119361113a565b5b92915050565b7f4e6f742079657420756e6c6f636b6564000000000000000000000000000000005f82015250565b5f6111ce60108361102d565b91506111d98261119a565b602082019050919050565b5f6020820190508181035f8301526111fb816111c2565b9050919050565b5f6040820190506112155f830185610fda565b6112226020830184610ea3565b9392505050565b61123281610ecb565b811461123c575f80fd5b50565b5f8151905061124d81611229565b92915050565b5f6020828403121561126857611267610da9565b5b5f6112758482850161123f565b91505092915050565b7f5472616e73666572206661696c656400000000000000000000000000000000005f82015250565b5f6112b2600f8361102d565b91506112bd8261127e565b602082019050919050565b5f6020820190508181035f8301526112df816112a6565b9050919050565b7f416d6f756e74206d757374206265203e203000000000000000000000000000005f82015250565b5f61131a60128361102d565b9150611325826112e6565b602082019050919050565b5f6020820190508181035f8301526113478161130e565b9050919050565b7f496e76616c6964206475726174696f6e000000000000000000000000000000005f82015250565b5f61138260108361102d565b915061138d8261134e565b602082019050919050565b5f6020820190508181035f8301526113af81611376565b9050919050565b5f6060820190506113c95f830186610fda565b6113d66020830185610fda565b6113e36040830184610ea3565b949350505050565b5f6113f582610dad565b915061140083610dad565b92508282039050818111156114185761141761113a565b5b92915050565b5f6060820190506114315f830186610ea3565b61143e6020830185610ea3565b61144b6040830184610ea3565b949350505050565b5f61145d82610dad565b915061146883610dad565b925082820261147681610dad565b9150828204841483151761148d5761148c61113a565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f6114cb82610dad565b91506114d683610dad565b9250826114e6576114e5611494565b5b828204905092915050565b7f4d617820353030204846562070657220706572696f64207065722077616c6c655f8201527f7400000000000000000000000000000000000000000000000000000000000000602082015250565b5f61154b60218361102d565b9150611556826114f1565b604082019050919050565b5f6020820190508181035f8301526115788161153f565b905091905056fea26469706673582212207f36b3b461783bb83239ed2dbda0585928ccbcb13be5dfe6c5526aad52a9046764736f6c63430008140033
Verified Source Code Full Match
Compiler: v0.8.20+commit.a1b79de6
EVM: shanghai
Optimization: No
Ownable.sol 100 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @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);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) 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 a `value` amount of tokens 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 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
HFVStakingProtocol.sol 115 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract HFVStaking is Ownable {
IERC20 public hfvToken;
struct StakeInfo {
uint256 amount;
uint256 startTimestamp;
uint256 duration;
bool claimed;
}
mapping(address => StakeInfo[]) public stakes;
// ✅ NEW: Track how much each user has staked per duration
mapping(address => mapping(uint256 => uint256)) private _userStakedPerPeriod;
event Staked(address indexed user, uint256 amount, uint256 duration, uint256 index);
event Claimed(address indexed user, uint256 index);
constructor(address tokenAddress) Ownable(msg.sender) {
require(tokenAddress != address(0), "Invalid token address");
hfvToken = IERC20(tokenAddress);
}
function stake(uint256 amount, uint256 duration) external {
require(amount > 0, "Amount must be > 0");
require(
duration == 1814400 || // 21 days
duration == 7776000 || // 3 months
duration == 15552000 || // 6 months
duration == 31104000, // 12 months
"Invalid duration"
);
// ✅ NEW: Check that wallet has not exceeded 500 HFV for this period
_enforceMaxStakePerPeriod(msg.sender, amount, duration);
require(hfvToken.transferFrom(msg.sender, address(this), amount), "Transfer failed");
stakes[msg.sender].push(StakeInfo({
amount: amount,
startTimestamp: block.timestamp,
duration: duration,
claimed: false
}));
// ✅ NEW: Update user's total staked for this duration
_userStakedPerPeriod[msg.sender][duration] += amount;
emit Staked(msg.sender, amount, duration, stakes[msg.sender].length - 1);
}
function claim(uint256 index) external {
require(index < stakes[msg.sender].length, "Invalid index");
StakeInfo storage info = stakes[msg.sender][index];
require(!info.claimed, "Already claimed");
require(block.timestamp >= info.startTimestamp + info.duration, "Not yet unlocked");
info.claimed = true;
uint256 reward = _calculateReward(info.amount, info.duration);
require(hfvToken.transfer(msg.sender, info.amount + reward), "Transfer failed");
emit Claimed(msg.sender, index);
}
// ✅ NEW: Enforces 500 HFV limit per wallet per duration
function _enforceMaxStakePerPeriod(address user, uint256 amount, uint256 duration) internal view {
require(
_userStakedPerPeriod[user][duration] + amount <= 500,
"Max 500 HFV per period per wallet"
);
}
// ✅ Original reward formula: HFV × 0.4 × 17.38 × Tier Multiplier
function _calculateReward(uint256 amount, uint256 duration) internal pure returns (uint256) {
// 0.4 * 17.38 = 6.952 → use fixed-point math with 4 decimals: 6.952 * 10000 = 69520
uint256 base = 69520;
uint256 multiplier;
if (duration == 1814400) {
multiplier = 1;
} else if (duration == 7776000) {
multiplier = 4;
} else if (duration == 15552000) {
multiplier = 8;
} else if (duration == 31104000) {
multiplier = 16;
} else {
return 0;
}
return (amount * base * multiplier) / 10000;
}
function getStakeCount(address user) external view returns (uint256) {
return stakes[user].length;
}
function getPendingReward(address user, uint256 index) external view returns (uint256) {
if (index >= stakes[user].length) return 0;
StakeInfo storage info = stakes[user][index];
if (info.claimed || block.timestamp < info.startTimestamp + info.duration) return 0;
return _calculateReward(info.amount, info.duration);
}
function getStakedAmount(address user, uint256 duration) external view returns (uint256) {
return _userStakedPerPeriod[user][duration];
}
}
Read Contract
getPendingReward 0x999ffd97 → uint256
getStakeCount 0xcf57ee69 → uint256
getStakedAmount 0x4a84c9ee → uint256
hfvToken 0x69a6d6b9 → address
owner 0x8da5cb5b → address
stakes 0x584b62a1 → uint256, uint256, uint256, bool
Write Contract 4 functions
These functions modify contract state and require a wallet transaction to execute.
claim 0x379607f5
uint256 index
renounceOwnership 0x715018a6
No parameters
stake 0x7b0472f0
uint256 amount
uint256 duration
transferOwnership 0xf2fde38b
address newOwner
Recent Transactions
No transactions found for this address