Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol): enable strike price to token grants #15522

Merged
merged 5 commits into from
Jan 19, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 36 additions & 16 deletions packages/protocol/contracts/team/TimelockTokenPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ contract TimelockTokenPool is EssentialContract {

struct Grant {
uint128 amount;
// If non-zero, each TKO (1E18) will need some USD stable to purchase.
uint128 costPerToken;
// If non-zero, indicates the start time for the recipient to receive
// tokens, subject to an unlocking schedule.
uint64 grantStart;
Expand All @@ -61,35 +63,48 @@ contract TimelockTokenPool is EssentialContract {

struct Recipient {
uint128 amountWithdrawn;
uint128 costPaid;
Grant[] grants;
}

uint256 public constant MAX_GRANTS_PER_ADDRESS = 8;

address public taikoToken;
address public costToken;
address public sharedVault;
uint128 public totalAmountGranted;
uint128 public totalAmountVoided;
uint128 public totalAmountWithdrawn;
uint128 public totalCostPaid;
mapping(address recipient => Recipient) public recipients;
uint128[44] private __gap;

event Granted(address indexed recipient, Grant grant);
event Voided(address indexed recipient, uint128 amount);
event Withdrawn(address indexed recipient, address to, uint128 amount);
event Withdrawn(address indexed recipient, address to, uint128 amount, uint128 cost);

error INVALID_GRANT();
error INVALID_PARAM();
error NOTHING_TO_VOID();
error NOTHING_TO_WITHDRAW();
error TOO_MANY();

function init(address _taikoToken, address _sharedVault) external initializer {
function init(
address _taikoToken,
address _costToken,
address _sharedVault
)
external
initializer
{
__Essential_init();

if (_taikoToken == address(0)) revert INVALID_PARAM();
taikoToken = _taikoToken;

if (_costToken == address(0)) revert INVALID_PARAM();
costToken = _costToken;

if (_sharedVault == address(0)) revert INVALID_PARAM();
sharedVault = _sharedVault;
}
Expand Down Expand Up @@ -148,18 +163,25 @@ contract TimelockTokenPool is EssentialContract {
uint128 amountOwned,
uint128 amountUnlocked,
uint128 amountWithdrawn,
uint128 amountWithdrawable
uint128 amountToWithdraw,
uint128 costToWithdraw
)
{
Recipient storage r = recipients[recipient];
uint256 rGrantsLength = r.grants.length;
uint128 totalCost;
for (uint128 i; i < rGrantsLength; ++i) {
amountOwned += _getAmountOwned(r.grants[i]);
amountUnlocked += _getAmountUnlocked(r.grants[i]);

uint128 _amountUnlocked = _getAmountUnlocked(r.grants[i]);
amountUnlocked += _amountUnlocked;

totalCost += _amountUnlocked / 1e18 * r.grants[i].costPerToken;
}

amountWithdrawn = r.amountWithdrawn;
amountWithdrawable = amountUnlocked - amountWithdrawn;
amountToWithdraw = amountUnlocked - amountWithdrawn;
costToWithdraw = totalCost - r.costPaid;
}

function getMyGrants(address recipient) public view returns (Grant[] memory) {
Expand All @@ -168,21 +190,19 @@ contract TimelockTokenPool is EssentialContract {

function _withdraw(address recipient, address to) private {
Recipient storage r = recipients[recipient];
uint128 amount;

uint256 rGrantsLength = r.grants.length;
for (uint128 i; i < rGrantsLength; ++i) {
amount += _getAmountUnlocked(r.grants[i]);
}
(,,, uint128 amountToWithdraw, uint128 costToWithdraw) = getMyGrantSummary(recipient);

r.amountWithdrawn += amountToWithdraw;
r.costPaid += costToWithdraw;

amount -= r.amountWithdrawn;
if (amount == 0) revert NOTHING_TO_WITHDRAW();
totalAmountWithdrawn += amountToWithdraw;
totalCostPaid += costToWithdraw;

r.amountWithdrawn += amount;
totalAmountWithdrawn += amount;
IERC20(taikoToken).transferFrom(sharedVault, to, amount);
IERC20(taikoToken).transferFrom(sharedVault, to, amountToWithdraw);
IERC20(costToken).transferFrom(recipient, sharedVault, costToWithdraw);

emit Withdrawn(recipient, to, amount);
emit Withdrawn(recipient, to, amountToWithdraw, costToWithdraw);
}

function _voidGrant(Grant storage g) private returns (uint128 amountVoided) {
Expand Down
Loading
Loading