-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMetaTokenDistributor.sol
More file actions
112 lines (85 loc) · 3.69 KB
/
MetaTokenDistributor.sol
File metadata and controls
112 lines (85 loc) · 3.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {MetaToken} from "src/MetaToken.sol";
import {IMetaTokenDistributor} from "./interfaces/IMetaTokenDistributor.sol";
import {IVesting} from "./vesting/Vesting.sol";
import {IVestingParams} from "./vesting/interfaces/IVestingParams.sol";
import {Schedule, Beneficiary, VestingType} from "./utils/Common.sol";
/**
* @title Distributor of MetaLamp token
* @author Pavel Naydanov
* @notice Deploy vesting contract, which based on vesting params.
* At the time of contract deployment, an instance of the meta token is created.
* Any account can start vesting after the start time.
*/
contract MetaTokenDistributor is IMetaTokenDistributor {
using SafeERC20 for IERC20;
/// @notice Implementation of vesting contract for using in Clone
address private _vestingImpl;
/// @notice MetaLamp token for distribution
IERC20 private _meta;
/// @notice A smart contract that stores vesting parameters (allocation, schedule, etc.)
IVestingParams private _vestingParams;
/// @notice Stores addresses of created vestings
mapping(VestingType vestingType => address vesting) private _vestingAddresses;
/// @dev Validate start vesting time
modifier validateTime() {
_validateTime();
_;
}
constructor(address vestingParams, address vestingImpl) {
if (address(vestingParams) == address(0)) {
revert ZeroAddress();
}
_vestingParams = IVestingParams(vestingParams);
_vestingImpl = vestingImpl;
_meta = IERC20(address(new MetaToken(address(this))));
assert(_meta.balanceOf(address(this)) == _meta.totalSupply());
emit MetaTokenDeployed(address(_meta));
}
/**
* @notice Start vesting
* @param vestingType Type of vesting (Team, Liquidity, etc.)
* @return vesting Address of created vesting contract
* @dev Any can start vesting after start time
*/
function startVesting(VestingType vestingType) external validateTime returns (address vesting) {
if (_vestingAddresses[vestingType] != address(0)) {
revert VestingHasAlreadyStarted();
}
(Schedule memory schedule, Beneficiary[] memory beneficiaries, uint256 vestingTotalAmount) =
_vestingParams.getVestingParams(vestingType);
vesting = Clones.clone(_vestingImpl);
_meta.safeTransfer(vesting, vestingTotalAmount);
IVesting(vesting).initialize(_meta, schedule, beneficiaries);
_vestingAddresses[vestingType] = vesting;
emit VestingStarted(vesting);
}
/// @notice Returns address of MetaLamp token
function getMetaAddress() external view returns (address) {
return address(_meta);
}
/**
* @notice Returns address of created vesting contract
* @param vestingType Type of vesting (Team, Liquidity, etc.)
*/
function getVestingAddress(VestingType vestingType) external view returns (address) {
return _vestingAddresses[vestingType];
}
/// @notice Returns address of VestingParams contract
function getVestingParamsAddress() external view returns (address) {
return address(_vestingParams);
}
/// @notice Returns address of VestingImpl contract
function getVestingImplAddress() external view returns (address) {
return _vestingImpl;
}
function _validateTime() private view {
uint64 startTime = _vestingParams.getStartTime();
if (block.timestamp < startTime) {
revert VestingStartTimeHasNotArrived();
}
}
}