-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathTimelock.sol
More file actions
98 lines (77 loc) · 2.46 KB
/
Timelock.sol
File metadata and controls
98 lines (77 loc) · 2.46 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
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.9;
import './Token.sol';
contract Timelock {
address public _deployer;
address[] public _owners;
Token _token = Token(0x5EF6b5ABaA7e9b75Fa4DaEBF0Fc722f9AFF12B40);
struct Lock {
uint256 amount;
uint256 unlockedAt;
string description;
}
Lock[] public _lock;
constructor(address[] memory owners) {
_deployer = msg.sender;
_owners = owners;
}
function lock(uint256[] memory amounts, uint256[] memory daysToUnlock, string[] memory descriptions) public {
require(daysToUnlock.length == amounts.length, 'arrays should have the same length');
uint256 total = 0;
for (uint256 i = 0; i < amounts.length; i++) {
total += amounts[i];
}
require(total <= _token.balanceOf(address(this)), 'contract balance too low');
for (uint256 i = 0; i < amounts.length; i++) {
_lock.push(Lock(amounts[i], block.timestamp + daysToUnlock[i] * 1 days, descriptions[i]));
}
}
function withdrawAll() public {
require(isOwner(msg.sender), 'owner only');
uint256 unlocked = unlockedAmount();
require(unlocked > 0, 'nothing to withdraw');
withdraw(unlocked);
}
function withdraw(uint256 amount) public {
uint256 balance = _token.balanceOf(address(this));
uint256 locked = lockedAmount();
uint256 unlocked = unlockedAmount();
require(unlocked > 0, 'nothing to withdraw');
require(isOwner(msg.sender), 'owner only');
require(amount > 0, 'amount should be larger than 0');
require(amount <= unlockedAmount(), 'amount too large');
require(balance > locked, 'nothing to withdraw');
require(balance - locked >= amount, 'amount too large');
_token.transfer(msg.sender, amount);
}
function lockedAmount() public view returns (uint256) {
uint256 amount = 0;
for (uint256 i = 0; i < _lock.length; i++) {
if (_lock[i].unlockedAt < block.timestamp) continue;
amount += _lock[i].amount;
}
return amount;
}
function unlockedAmount() public view returns (uint256) {
uint256 balance = _token.balanceOf(address(this));
uint256 locked = lockedAmount();
if (balance > locked) return (balance - locked);
return 0;
}
function isOwner(address account) public view returns (bool) {
bool owner = account == _deployer;
if (!owner) {
for (uint256 i = 0; i < _owners.length; i++) {
if (_owners[i] == account) {
owner = true;
break;
}
}
}
return owner;
}
function setOwners(address[] memory owners) public {
require(isOwner(msg.sender), 'owner only');
_owners = owners;
}
}