Skip to content

Commit 1fb2365

Browse files
committed
generate periodic tranches
1 parent 711a84a commit 1fb2365

File tree

3 files changed

+38
-136
lines changed

3 files changed

+38
-136
lines changed
Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,50 @@
11
// SPDX-License-Identifier: MIT
2-
pragma solidity 0.8.21;
2+
pragma solidity ^0.8.0;
33

44
contract TrancheVesting {
5+
56
struct Tranche {
6-
uint256 time;
7-
uint256 vestedFraction;
8-
uint256 date;
7+
uint128 time; // Timestamp upon which the tranche vests
8+
uint128 vestedFraction; // Fraction of tokens unlockable as basis points
99
}
1010

11-
function generatePeriodicTranches(uint256 startTime, uint256 cliffTime, uint256 endTime, string memory units) external pure returns (Tranche[] memory) {
12-
uint256 totalTranches = getDifference(startTime, endTime, units);
11+
// Generate an array of tranches based on input parameters
12+
function generateTranches(uint256 start, uint256 end, uint256 cliff) public pure returns (Tranche[] memory) {
13+
require(end > start, "End must be greater than start");
14+
require(cliff >= start && cliff <= end, "Cliff must be between start and end");
1315

14-
Tranche[] memory tranches = new Tranche[](totalTranches);
16+
uint256 vestingStart = cliff > start ? cliff : start;
17+
uint256 vestingDuration = end - vestingStart;
1518

16-
uint256 currentIndex = 0;
19+
// Calculate the number of periods as months between vestingStart and end
20+
// 30.44 days per month, is this accurate?
21+
uint256 secondsPerMonth = 30.44 days;
22+
uint256 periods = vestingDuration / secondsPerMonth;
1723

18-
for (uint256 i = 0; i < totalTranches; i++) {
19-
uint256 trancheStartTime = addToDateTime(startTime, i, units);
24+
// Ensure there is at least one period
25+
if (periods == 0) {
26+
periods = 1;
27+
}
2028

21-
if (trancheStartTime < cliffTime) {
22-
continue;
23-
}
29+
Tranche[] memory tranches = new Tranche[](periods);
30+
uint256 periodDuration = vestingDuration / periods;
31+
uint256 totalVestedFraction = 0;
2432

25-
uint256 vestedFraction = ((i + 1) * (100 / totalTranches)) * 100;
33+
for (uint256 i = 0; i < periods; i++) {
34+
uint256 trancheTime = vestingStart + (periodDuration * (i + 1));
35+
// What value should we use instead of 10,000?
36+
uint256 fractionPerPeriod = (i + 1) * (10000 / periods);
37+
uint128 vestedFraction = uint128(fractionPerPeriod - totalVestedFraction);
38+
totalVestedFraction += vestedFraction;
2639

27-
tranches[currentIndex] = Tranche({
28-
time: trancheStartTime,
29-
vestedFraction: vestedFraction,
30-
date: trancheStartTime
31-
});
40+
// Adjust the last tranche to ensure total vested fraction equals 10000
41+
if (i == periods - 1 && totalVestedFraction != 10000) {
42+
vestedFraction += (10000 - uint128(totalVestedFraction));
43+
}
3244

33-
currentIndex++;
45+
tranches[i] = Tranche(uint128(trancheTime), vestedFraction);
3446
}
3547

3648
return tranches;
3749
}
38-
39-
// Function to calculate the difference between two timestamps
40-
function getDifference(uint256 startTime, uint256 endTime, string memory units) internal pure returns (uint256) {
41-
// Implementation of getDifference based on units
42-
// You need to implement this function according to your requirements
43-
}
44-
45-
// Function to add time to a given timestamp
46-
function addToDateTime(uint256 timestamp, uint256 amount, string memory units) internal pure returns (uint256) {
47-
// Implementation of addToDateTime based on units
48-
// You need to implement this function according to your requirements
49-
}
5050
}

packages/hardhat/contracts/claim/abstract/PerAddressTrancheVesting.sol

Lines changed: 3 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ pragma solidity 0.8.21;
44
import { PerAddressAdvancedDistributor } from './PerAddressAdvancedDistributor.sol';
55
import { IPerAddressTrancheVesting, Tranche } from '../../interfaces/IPerAddressTrancheVesting.sol';
66
import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
7+
import { TrancheVesting } from '../GeneratePeriodicTranches.sol';
78
import "hardhat/console.sol";
89

910
/**
1011
* @title TrancheVesting
1112
* @notice Distributes funds to beneficiaries over time in tranches.
1213
*/
13-
abstract contract PerAddressTrancheVesting is PerAddressAdvancedDistributor, IPerAddressTrancheVesting {
14+
abstract contract PerAddressTrancheVesting is PerAddressAdvancedDistributor, IPerAddressTrancheVesting, TrancheVesting {
1415
// time and vested fraction must monotonically increase in the tranche array
1516

1617
constructor(
@@ -41,6 +42,7 @@ abstract contract PerAddressTrancheVesting is PerAddressAdvancedDistributor, IPe
4142
// calculateTranche(beneficiary, record);
4243

4344
// TODO: calculate tranches with start, end, cliff
45+
Tranche[] memory tranches = generateTranches(start, end, cliff);
4446

4547
uint256 delay = getFairDelayTime(beneficiary);
4648
for (uint256 i = tranches.length; i != 0; ) {
@@ -54,57 +56,5 @@ abstract contract PerAddressTrancheVesting is PerAddressAdvancedDistributor, IPe
5456
}
5557

5658
return 0;
57-
}
58-
59-
// Get a single tranche
60-
function getTranche(uint256 i) public view returns (Tranche memory) {
61-
return tranches[i];
62-
}
63-
64-
// Get all tranches
65-
function getTranches() public view returns (Tranche[] memory) {
66-
return tranches;
67-
}
68-
69-
/**
70-
* @dev Tranches can be updated at any time. The quantity of tokens a user can claim is based on the
71-
* claimable quantity at the time of the claim and the quantity of tokens already claimed by the user.
72-
*/
73-
function _setTranches(Tranche[] memory _tranches) private {
74-
require(_tranches.length != 0, 'tranches required');
75-
76-
delete tranches;
77-
78-
uint128 lastTime = 0;
79-
uint128 lastVestedFraction = 0;
80-
81-
for (uint256 i = 0; i < _tranches.length; ) {
82-
require(_tranches[i].vestedFraction != 0, 'tranche vested fraction == 0');
83-
require(_tranches[i].time > lastTime, 'tranche time must increase');
84-
require(
85-
_tranches[i].vestedFraction > lastVestedFraction,
86-
'tranche vested fraction must increase'
87-
);
88-
lastTime = _tranches[i].time;
89-
lastVestedFraction = _tranches[i].vestedFraction;
90-
tranches.push(_tranches[i]);
91-
92-
emit SetTranche(i, lastTime, lastVestedFraction);
93-
94-
unchecked {
95-
++i;
96-
}
97-
}
98-
99-
require(lastTime <= 4102444800, 'vesting ends after 4102444800 (Jan 1 2100)');
100-
require(lastVestedFraction == fractionDenominator, 'last tranche must vest all tokens');
101-
}
102-
103-
/**
104-
* @notice Set the vesting tranches. Tranches must be sorted by time and vested fraction must monotonically increase.
105-
* The last tranche must vest all tokens (vestedFraction == fractionDenominator)
106-
*/
107-
function setTranches(Tranche[] memory _tranches) external onlyOwner {
108-
_setTranches(_tranches);
10959
}
11060
}

packages/hardhat/contracts/claim/factory/PerAddressTrancheVestingInitializable.sol

Lines changed: 3 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
66

77
import "./PerAddressAdvancedDistributorInitializable.sol";
88
import {IPerAddressTrancheVesting, Tranche} from "../../interfaces/IPerAddressTrancheVesting.sol";
9+
import { TrancheVesting } from '../GeneratePeriodicTranches.sol';
910

10-
abstract contract PerAddressTrancheVestingInitializable is Initializable, PerAddressAdvancedDistributorInitializable, IPerAddressTrancheVesting {
11+
abstract contract PerAddressTrancheVestingInitializable is Initializable, PerAddressAdvancedDistributorInitializable, IPerAddressTrancheVesting, TrancheVesting {
1112

1213
function __TrancheVesting_init(
1314
IERC20 _token,
@@ -38,7 +39,7 @@ abstract contract PerAddressTrancheVestingInitializable is Initializable, PerAdd
3839
function getVestedFraction(address beneficiary, uint256 time, uint256 start, uint256 end, uint256 cliff) public view override returns (uint256) {
3940

4041
// tranches = calculate the the tranche from start, end, cliff from record, record.start, record.end, record.cliff,
41-
Tranche[] tranches = [];
42+
Tranche[] memory tranches = generateTranches(start, end, cliff);
4243
uint256 delay = getFairDelayTime(beneficiary);
4344
for (uint256 i = tranches.length; i != 0;) {
4445
unchecked {
@@ -52,53 +53,4 @@ abstract contract PerAddressTrancheVestingInitializable is Initializable, PerAdd
5253

5354
return 0;
5455
}
55-
56-
// Get a single tranche
57-
function getTranche(uint256 i) public view returns (Tranche memory) {
58-
// return tranches[i];
59-
}
60-
61-
// TODO: get tranche for address
62-
function getTranches() public view returns (Tranche[] memory) {
63-
// return tranches;
64-
}
65-
66-
/**
67-
* @dev Tranches can be updated at any time. The quantity of tokens a user can claim is based on the
68-
* claimable quantity at the time of the claim and the quantity of tokens already claimed by the user.
69-
*/
70-
function _setTranches(Tranche[] memory _tranches) private {
71-
require(_tranches.length != 0, "tranches required");
72-
73-
// delete tranches;
74-
75-
uint128 lastTime = 0;
76-
uint128 lastVestedFraction = 0;
77-
78-
for (uint256 i = 0; i < _tranches.length;) {
79-
require(_tranches[i].vestedFraction != 0, "tranche vested fraction == 0");
80-
require(_tranches[i].time > lastTime, "tranche time must increase");
81-
require(_tranches[i].vestedFraction > lastVestedFraction, "tranche vested fraction must increase");
82-
lastTime = _tranches[i].time;
83-
lastVestedFraction = _tranches[i].vestedFraction;
84-
tranches.push(_tranches[i]);
85-
86-
emit SetTranche(i, lastTime, lastVestedFraction);
87-
88-
unchecked {
89-
++i;
90-
}
91-
}
92-
93-
require(lastTime <= 4102444800, "vesting ends after 4102444800 (Jan 1 2100)");
94-
require(lastVestedFraction == fractionDenominator, "last tranche must vest all tokens");
95-
}
96-
97-
/**
98-
* @notice Set the vesting tranches. Tranches must be sorted by time and vested fraction must monotonically increase.
99-
* The last tranche must vest all tokens (vestedFraction == fractionDenominator)
100-
*/
101-
function setTranches(Tranche[] memory _tranches) external onlyOwner {
102-
_setTranches(_tranches);
103-
}
10456
}

0 commit comments

Comments
 (0)