Skip to content

Instantly share code, notes, and snippets.

@FoobarProtocol
Created May 22, 2023 10:37
Show Gist options
  • Save FoobarProtocol/56ce6e8a59af13a00b93797d96a8977c to your computer and use it in GitHub Desktop.
Save FoobarProtocol/56ce6e8a59af13a00b93797d96a8977c to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
contract MyToken is ERC20 {
uint256 public immutable precision;
uint256 public immutable vestingPeriod;
uint256 public vestingPeriodFinish;
uint256 public issuanceRate;
uint256 public lastIssuanceTime;
address public asset;
constructor(
string memory name,
string memory symbol,
uint256 _precision,
uint256 _vestingPeriod,
address _asset
) ERC20(name, symbol) {
precision = _precision;
vestingPeriod = _vestingPeriod;
asset = _asset;
lastIssuanceTime = block.timestamp;
issuanceRate = 0;
vestingPeriodFinish = block.timestamp + vestingPeriod;
}
function deposit(uint256 amount, address receiver) external returns (uint256) {
require(amount > 0, "Amount must be greater than zero");
require(receiver != address(0), "Invalid receiver address");
// Transfer the underlying asset to the contract
require(
IERC20(asset).transferFrom(msg.sender, address(this), amount),
"Failed to transfer asset to contract"
);
// Calculate the new issuance rate based on the amount deposited
uint256 timeElapsed = block.timestamp - lastIssuanceTime;
issuanceRate += (amount * precision) / (timeElapsed * 1e18);
// Mint the tokens to the receiver
uint256 shares = (amount * precision) / issuanceRate;
_mint(receiver, shares);
// Update the last issuance time
lastIssuanceTime = block.timestamp;
return shares;
}
function mint(uint256 shares, address receiver) external returns (uint256) {
require(shares > 0, "Shares must be greater than zero");
require(receiver != address(0), "Invalid receiver address");
// Calculate the amount of underlying asset to mint
uint256 timeElapsed = block.timestamp - lastIssuanceTime;
uint256 amount = (shares * issuanceRate) / precision;
// Check that enough time has elapsed since last issuance
require(block.timestamp >= vestingPeriodFinish || timeElapsed >= vestingPeriod, "Vesting period not finished");
// Burn the tokens from the sender
_burn(msg.sender, shares);
// Transfer the underlying asset to the receiver
require(IERC20(asset).transfer(receiver, amount), "Failed to transfer asset to receiver");
// Update the last issuance time if the vesting period is finished
if (block.timestamp >= vestingPeriodFinish) {
lastIssuanceTime = block.timestamp;
issuanceRate = 0;
vestingPeriodFinish = block.timestamp + vestingPeriod;
}
return amount;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment