// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/// @title LinkedInuVesting
/// @notice One per launched token. Holds the reserved slice of supply (default
/// 20%) and releases it to a beneficiary on a fixed schedule:
/// `releasePerPeriod` tokens unlock every `periodSeconds`, until
/// `totalAmount` is fully vested. The default schedule is 1% of total
/// supply per 30 days over 20 months. The beneficiary is fixed at the
/// moment the token is created and can never be changed.
/// @dev Every parameter is IMMUTABLE: once a token launches its schedule is
/// locked forever. No admin, no early release, no rug path — tokens can
/// only leave on schedule, and only ever to the immutable beneficiary.
contract LinkedInuVesting is ReentrancyGuard {
using SafeERC20 for IERC20;
address public immutable token;
address public immutable beneficiary;
/// @notice Total amount to vest (e.g. 20% of supply).
uint256 public immutable totalAmount;
/// @notice Amount unlocked each period (e.g. 1% of supply).
uint256 public immutable releasePerPeriod;
/// @notice Period length in seconds (e.g. 30 days).
uint256 public immutable periodSeconds;
uint256 public immutable startTime;
uint256 public claimed;
event Claimed(address indexed beneficiary, uint256 amount);
error ZeroAddress();
error BadSchedule();
error NothingToClaim();
constructor(
address token_,
address beneficiary_,
uint256 totalAmount_,
uint256 releasePerPeriod_,
uint256 periodSeconds_
) {
if (token_ == address(0) || beneficiary_ == address(0)) revert ZeroAddress();
if (totalAmount_ == 0 || releasePerPeriod_ == 0 || periodSeconds_ == 0) {
revert BadSchedule();
}
token = token_;
beneficiary = beneficiary_;
totalAmount = totalAmount_;
releasePerPeriod = releasePerPeriod_;
periodSeconds = periodSeconds_;
startTime = block.timestamp;
}
/// @notice Cumulative amount unlocked so far, capped at totalAmount. The
/// first period unlocks only after one full `periodSeconds`, so
/// there is no day-zero cliff bypass.
function vested() public view returns (uint256) {
uint256 periods = (block.timestamp - startTime) / periodSeconds;
uint256 amount = periods * releasePerPeriod;
return amount > totalAmount ? totalAmount : amount;
}
/// @notice Unlocked but not-yet-claimed amount.
function claimable() public view returns (uint256) {
return vested() - claimed;
}
/// @notice Timestamp of the next unlock, or 0 once fully vested. UI helper.
function nextUnlockAt() external view returns (uint256) {
if (vested() >= totalAmount) return 0;
uint256 elapsedPeriods = (block.timestamp - startTime) / periodSeconds;
return startTime + (elapsedPeriods + 1) * periodSeconds;
}
/// @notice Total number of periods in the schedule (rounded up). UI helper.
function totalPeriods() external view returns (uint256) {
return (totalAmount + releasePerPeriod - 1) / releasePerPeriod;
}
/// @notice Claim all currently-unlocked tokens. Permissionless, because the
/// funds can only ever go to the immutable beneficiary.
function claim() external nonReentrant returns (uint256 amount) {
amount = claimable();
if (amount == 0) revert NothingToClaim();
claimed += amount;
IERC20(token).safeTransfer(beneficiary, amount);
emit Claimed(beneficiary, amount);
}
}[
{
"type": "constructor",
"inputs": [
{
"name": "token_",
"type": "address",
"internalType": "address"
},
{
"name": "beneficiary_",
"type": "address",
"internalType": "address"
},
{
"name": "totalAmount_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "releasePerPeriod_",
"type": "uint256",
"internalType": "uint256"
},
{
"name": "periodSeconds_",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "BadSchedule",
"type": "error",
"inputs": []
},
{
"name": "NothingToClaim",
"type": "error",
"inputs": []
},
{
"name": "ReentrancyGuardReentrantCall",
"type": "error",
"inputs": []
},
{
"name": "SafeERC20FailedOperation",
"type": "error",
"inputs": [
{
"name": "token",
"type": "address",
"internalType": "address"
}
]
},
{
"name": "ZeroAddress",
"type": "error",
"inputs": []
},
{
"name": "Claimed",
"type": "event",
"inputs": [
{
"name": "beneficiary",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "amount",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"name": "beneficiary",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "claim",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "amount",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "nonpayable"
},
{
"name": "claimable",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "claimed",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "nextUnlockAt",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "periodSeconds",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "releasePerPeriod",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "startTime",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "token",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "address",
"internalType": "address"
}
],
"stateMutability": "view"
},
{
"name": "totalAmount",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "totalPeriods",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
},
{
"name": "vested",
"type": "function",
"inputs": [],
"outputs": [
{
"name": "",
"type": "uint256",
"internalType": "uint256"
}
],
"stateMutability": "view"
}
]0x60806040526004361015610011575f80fd5b5f3560e01c8063193ba56b146104af5780631a39d8ef1461047557806338af3eed146104315780634e71d92d1461027c57806378e9792514610242578063af38d7571461021d578063e5808f78146101e3578063e834a834146101c7578063f4514fa31461018d578063fc0c546a14610149578063fea5657c1461012f5763fea708f61461009d575f80fd5b3461012b575f36600319011261012b577f000000000000000000000000000000000000000000a56fa5b99019a5c80000006100f8817f000000000000000000000000000000000000000000a56fa5b99019a5c80000006104f4565b5f1981019081116101175760209161010f916104d6565b604051908152f35b634e487b7160e01b5f52601160045260245ffd5b5f80fd5b3461012b575f36600319011261012b57602061010f6105bf565b3461012b575f36600319011261012b576040517f000000000000000000000000b9bacef45aa2f34a7dd33d47880f2939fe73498f6001600160a01b03168152602090f35b3461012b575f36600319011261012b5760206040517f00000000000000000000000000000000000000000000000000000000000000018152f35b3461012b575f36600319011261012b5760205f54604051908152f35b3461012b575f36600319011261012b5760206040517f000000000000000000000000000000000000000000a56fa5b99019a5c80000008152f35b3461012b575f36600319011261012b57602061010f61023a6105bf565b5f54906104c9565b3461012b575f36600319011261012b5760206040517f000000000000000000000000000000000000000000000000000000006a78e16c8152f35b3461012b575f36600319011261012b5760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0054146104225760027f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00556102e16105bf565b6102ed5f5480926104c9565b90811561041357816102fe916104f4565b5f90815560405163a9059cbb60e01b82526001600160a01b037f000000000000000000000000899ef37d3efacf5c073b3a723ee20f338a159add8116600481905260248590529193927f000000000000000000000000b9bacef45aa2f34a7dd33d47880f2939fe73498f9091169060209060448180855af160015f51148116156103f4575b84604052156103e257507fd8138f8a3f377c5259ca548e70e4c2de94f129f5a11036a15b69513cba2b426a60208484829652a260017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055604051908152f35b635274afe760e01b5f5260045260245ffd5b600181151661040a57813b15153d151616610383565b843d5f823e3d90fd5b6312d37ee560e31b5f5260045ffd5b633ee5aeb560e01b5f5260045ffd5b3461012b575f36600319011261012b576040517f000000000000000000000000899ef37d3efacf5c073b3a723ee20f338a159add6001600160a01b03168152602090f35b3461012b575f36600319011261012b5760206040517f000000000000000000000000000000000000000000a56fa5b99019a5c80000008152f35b3461012b575f36600319011261012b57602061010f610514565b9190820391821161011757565b81156104e0570490565b634e487b7160e01b5f52601260045260245ffd5b9190820180921161011757565b8181029291811591840414171561011757565b61051c6105bf565b7f000000000000000000000000000000000000000000a56fa5b99019a5c800000011156105bb577f000000000000000000000000000000000000000000000000000000006a78e16c61056e81426104c9565b9061059a7f000000000000000000000000000000000000000000000000000000000000000180936104d6565b60018101809111610117576105b8926105b291610501565b906104f4565b90565b5f90565b61063d6106166105ef7f000000000000000000000000000000000000000000000000000000006a78e16c426104c9565b7f0000000000000000000000000000000000000000000000000000000000000001906104d6565b7f000000000000000000000000000000000000000000a56fa5b99019a5c800000090610501565b7f000000000000000000000000000000000000000000a56fa5b99019a5c8000000908181111561066b575090565b90509056fea26469706673582212205bd5e341bc661be127ee76c63901d847b4d6871f10e307bb3b03aa967c8f7f6a64736f6c634300081c0033
| Token | Symbol | Balance | Price | Value |
|---|---|---|---|---|
| LinkedInu (LINKEDINU) | LINKEDINU | 200,000,000 | — | — |
| Type | Age | Block | Details |
|---|---|---|---|
| no cross-chain L1↔L2 transactions for this address | |||
| Transaction Hash | Method | Block | Age | From | To | Type | Item | ||
|---|---|---|---|---|---|---|---|---|---|
| no NFT transfers for this address yet | |||||||||
| Txn Hash | Age | Event | Topics / Data |
|---|---|---|---|
| no event logs emitted by this address | |||
| Transaction Hash | Method ? | Block | Age | From | To | Amount | Txn Fee ? | ||
|---|---|---|---|---|---|---|---|---|---|
| No direct transactions — this address is only ever reached via internal calls (common for a contract only invoked through a router or proxy). View Internal Transactions → | |||||||||
| Transaction Hash | Method | Block | Age | From | To | Amount | Token | ||
|---|---|---|---|---|---|---|---|---|---|
| 0xfaf6d320…6d0f3a | Transfer | 32,219,682 | 8 days agoSun, 09 Aug 2026 20:22:04 UTC | 0x8abc…5e8e | IN | 0x66dc…4d21 | 200,000,000.000000 LINKEDINU | LinkedInu (LINKEDINU) |
| Block | Age | Parent Transaction Hash | Type | Method | From | To | Value | |
|---|---|---|---|---|---|---|---|---|
| 32,219,682 | 8 days agoSun, 09 Aug 2026 20:22:04 UTC | 0xfaf6d3…6d0f3a | CREATE | createCoin | 0x8abc…5e8e | IN | 0x66dc…4d21 | 0 ETH |