欢迎订阅专栏:3分钟Solidity--智能合约--Web3区块链技术必学
“代币锁定”指将加密代币在智能合约中暂时冻结,使其无法被转移或交易的行为。 代币锁定是建立信任的关键机制。一个清晰、合理的锁仓计划能有效协调项目方、投资者和用户的长期利益,是评估项目可靠性的重要指标。
代币锁定
一个锁定代币并在特定时间段内线性释放的合约示例。
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;
import {IERC20} from "./IERC20.sol";
contract Auth {
mapping(address => bool) public authorized;
modifier auth() {
require(authorized[msg.sender], "not authorized");
_;
}
constructor() {
authorized[msg.sender] = true;
}
function allow(address user) external auth {
authorized[user] = true;
}
function deny(address user) external auth {
authorized[user] = false;
}
}
contract TokenLock is Auth {
struct Lock {
// Locked amount
uint256 amount;
// Last lock timestamp
uint32 updatedAt;
// Lock expiry timestamp
uint32 expiresAt;
// Lock duration
uint32 duration;
}
mapping(address => Lock) public locks;
mapping(address => uint256) public freed;
function get(address token) external view returns (Lock memory) {
return locks[token];
}
function set(address token, uint32 duration) external auth {
locks[token].duration = duration;
}
function unlocked(address token) public view returns (uint256) {
Lock memory l = locks[token];
// block.timestamp >= expiresAt >= updatedAt
// block.timestamp >= updateAt >= expiresAt
if (block.timestamp >= l.expiresAt) {
return l.amount;
}
// expiresAt > block.timestamp >= updateAt
return l.amount * (block.timestamp - uint256(l.updatedAt))
/ uint256(l.expiresAt - l.updatedAt);
}
function claimable(address token) public view returns (uint256) {
return freed[token] + unlocked(token);
}
function lock(address token, uint256 amount) external auth {
uint256 free = unlocked(token);
Lock storage l = locks[token];
l.amount -= free;
l.updatedAt = uint32(block.timestamp);
l.expiresAt = uint32(block.timestamp) + l.duration;
freed[token] += free;
if (amount > 0) {
IERC20(token).transferFrom(msg.sender, address(this), amount);
l.amount += amount;
}
}
function unlock(address token) external auth returns (uint256 amount) {
uint256 free = unlocked(token);
Lock storage l = locks[token];
l.amount -= free;
l.updatedAt = uint32(block.timestamp);
amount = freed[token] + free;
freed[token] = 0;
if (amount > 0) {
IERC20(token).transfer(msg.sender, amount);
}
}
function sync(address token) external auth {
uint256 reserved = freed[token] + locks[token].amount;
uint256 bal = IERC20(token).balanceOf(address(this));
if (bal > reserved) {
IERC20(token).transfer(msg.sender, bal - reserved);
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount)
external
returns (bool);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount)
external
returns (bool);
}