|
@@ -75,19 +75,71 @@ contract VestedToken is StandardToken, TransferableToken {
|
|
|
Transfer(_holder, receiver, nonVested);
|
|
|
}
|
|
|
|
|
|
- function transferableTokens(address holder, uint64 time) constant public returns (uint256 nonVested) {
|
|
|
+ function transferableTokens(address holder, uint64 time) constant public returns (uint256) {
|
|
|
uint256 grantIndex = tokenGrantsCount(holder);
|
|
|
+
|
|
|
+ if (grantIndex == 0) return balanceOf(holder); // shortcut for holder without grants
|
|
|
+
|
|
|
+ // Iterate through all the grants the holder has, and add all non-vested tokens
|
|
|
+ uint256 nonVested = 0;
|
|
|
for (uint256 i = 0; i < grantIndex; i++) {
|
|
|
nonVested = safeAdd(nonVested, nonVestedTokens(grants[holder][i], time));
|
|
|
}
|
|
|
|
|
|
- return min256(safeSub(balances[holder], nonVested), super.transferableTokens(holder, time));
|
|
|
+ // Balance - totalNonVested is the amount of tokens a holder can transfer at any given time
|
|
|
+ uint256 vestedTransferable = safeSub(balanceOf(holder), nonVested);
|
|
|
+
|
|
|
+ // Return the minimum of how many vested can transfer and other value
|
|
|
+ // in case there are other limiting transferability factors (default is balanceOf)
|
|
|
+ return min256(vestedTransferable, super.transferableTokens(holder, time));
|
|
|
}
|
|
|
|
|
|
function tokenGrantsCount(address _holder) constant returns (uint index) {
|
|
|
return grants[_holder].length;
|
|
|
}
|
|
|
|
|
|
+ // transferableTokens
|
|
|
+ // | _/-------- vestedTokens rect
|
|
|
+ // | _/
|
|
|
+ // | _/
|
|
|
+ // | _/
|
|
|
+ // | _/
|
|
|
+ // | /
|
|
|
+ // | .|
|
|
|
+ // | . |
|
|
|
+ // | . |
|
|
|
+ // | . |
|
|
|
+ // | . |
|
|
|
+ // | . |
|
|
|
+ // +===+===========+---------+----------> time
|
|
|
+ // Start Clift Vesting
|
|
|
+ function calculateVestedTokens(
|
|
|
+ uint256 tokens,
|
|
|
+ uint256 time,
|
|
|
+ uint256 start,
|
|
|
+ uint256 cliff,
|
|
|
+ uint256 vesting) constant returns (uint256)
|
|
|
+ {
|
|
|
+ // Shortcuts for before cliff and after vesting cases.
|
|
|
+ if (time < cliff) return 0;
|
|
|
+ if (time >= vesting) return tokens;
|
|
|
+
|
|
|
+ // Interpolate all vested tokens.
|
|
|
+ // As before cliff the shortcut returns 0, we can use just calculate a value
|
|
|
+ // in the vesting rect (as shown in above's figure)
|
|
|
+
|
|
|
+ // vestedTokens = tokens * (time - start) / (vesting - start)
|
|
|
+ uint256 vestedTokens = safeDiv(
|
|
|
+ safeMul(
|
|
|
+ tokens,
|
|
|
+ safeSub(time, start)
|
|
|
+ ),
|
|
|
+ safeSub(vesting, start)
|
|
|
+ );
|
|
|
+
|
|
|
+ return vestedTokens;
|
|
|
+ }
|
|
|
+
|
|
|
function tokenGrant(address _holder, uint _grantId) constant returns (address granter, uint256 value, uint256 vested, uint64 start, uint64 cliff, uint64 vesting, bool revokable, bool burnsOnRevoke) {
|
|
|
TokenGrant grant = grants[_holder][_grantId];
|
|
|
|
|
@@ -112,29 +164,6 @@ contract VestedToken is StandardToken, TransferableToken {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- function calculateVestedTokens(
|
|
|
- uint256 tokens,
|
|
|
- uint256 time,
|
|
|
- uint256 start,
|
|
|
- uint256 cliff,
|
|
|
- uint256 vesting) constant returns (uint256 vestedTokens)
|
|
|
- {
|
|
|
-
|
|
|
- if (time < cliff) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (time > vesting) {
|
|
|
- return tokens;
|
|
|
- }
|
|
|
-
|
|
|
- uint256 cliffTokens = safeDiv(safeMul(tokens, safeSub(cliff, start)), safeSub(vesting, start));
|
|
|
- vestedTokens = cliffTokens;
|
|
|
-
|
|
|
- uint256 vestingTokens = safeSub(tokens, cliffTokens);
|
|
|
-
|
|
|
- vestedTokens = safeAdd(vestedTokens, safeDiv(safeMul(vestingTokens, safeSub(time, cliff)), safeSub(vesting, start)));
|
|
|
- }
|
|
|
-
|
|
|
function nonVestedTokens(TokenGrant grant, uint64 time) private constant returns (uint256) {
|
|
|
return safeSub(grant.value, vestedTokens(grant, time));
|
|
|
}
|