Skip to content

Deborah Prisca | Register for OpenGuild Sub0 Challenges #28

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

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ git clone https://github.com/openguild-labs/open-encode-challenges.git
Go to **Participant Registration** section and register to be the workshop participants. Add the below to the list, replace any placeholder with your personal information.

```
| 🦄 | Name | Github username | Your current occupation |
| 🦄 |Deborah Prisca|debbyprisca|student

|
```

- Step 5: `Commit` your code and push to the forked Github repository
Expand Down
93 changes: 89 additions & 4 deletions challenge-1-vesting/contracts/TokenVesting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,31 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard {
struct VestingSchedule {
// TODO: Define the vesting schedule struct

uint256 totalAmount;
uint256 startTime;
uint256 cliffDuration;
uint256 vestingDuration;
uint256 amountClaimed;
bool revoked;
}

// Token being vested

// TODO: Add state variables

IERC20 public token;


// Mapping from beneficiary to vesting schedule

// TODO: Add state variables

// Whitelist of beneficiaries
mapping(address => VestingSchedule) public vestingSchedules;


// TODO: Add state variables

mapping(address => bool) public whitelist;

// Events
event VestingScheduleCreated(address indexed beneficiary, uint256 amount);
event TokensClaimed(address indexed beneficiary, uint256 amount);
Expand All @@ -53,9 +66,12 @@ contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard {
constructor(address tokenAddress) {
// TODO: Initialize the contract

require(tokenAddress != address(0), "Token address cannot be zero");
token = IERC20(tokenAddress);

}

// Modifier to check if beneficiary is whitelisted

modifier onlyWhitelisted(address beneficiary) {
require(whitelist[beneficiary], "Beneficiary not whitelisted");
_;
Expand All @@ -80,21 +96,90 @@ contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard {
uint256 startTime
) external onlyOwner onlyWhitelisted(beneficiary) whenNotPaused {
// TODO: Implement vesting schedule creation

require(beneficiary != address(0), "Beneficiary cannot be zero address");
require(amount > 0, "Amount must be greater than zero");
require(vestingDuration > 0, "Vesting duration must be greater than zero");
require(vestingDuration >= cliffDuration, "Vesting duration must be greater than or equal to cliff duration");
require(vestingSchedules[beneficiary].totalAmount == 0, "Vesting schedule already exists");
}

function calculateVestedAmount(
address beneficiary
) public view returns (uint256) {
// TODO: Implement vested amount calculation

VestingSchedule storage schedule = vestingSchedules[beneficiary];

// If no schedule or revoked, return 0
if (schedule.totalAmount == 0 || schedule.revoked) {
return 0;
}
// If current time is before cliff, nothing is vested
if (block.timestamp < schedule.startTime + schedule.cliffDuration) {
return 0;
}

// If current time is after vesting duration, everything is vested
if (block.timestamp >= schedule.startTime + schedule.vestingDuration) {
return schedule.totalAmount;
}

// Otherwise, calculate vested amount based on linear vesting
uint256 timeFromStart = block.timestamp - schedule.startTime;
uint256 vestedAmount = (schedule.totalAmount * timeFromStart) / schedule.vestingDuration;

return vestedAmount;
}

function claimVestedTokens() external nonReentrant whenNotPaused {
// TODO: Implement token claiming

address beneficiary = msg.sender;
VestingSchedule storage schedule = vestingSchedules[beneficiary];

require(schedule.totalAmount > 0, "No vesting schedule found");
require(!schedule.revoked, "Vesting schedule has been revoked");

uint256 vestedAmount = calculateVestedAmount(beneficiary);
uint256 claimableAmount = vestedAmount - schedule.amountClaimed;

require(claimableAmount > 0, "No tokens available to claim");

// Update claimed amount
schedule.amountClaimed += claimableAmount;

// Transfer tokens to beneficiary
require(token.transfer(beneficiary, claimableAmount), "Token transfer failed");

emit TokensClaimed(beneficiary, claimableAmount);
}

function revokeVesting(address beneficiary) external onlyOwner {
// TODO: Implement vesting revocation

VestingSchedule storage schedule = vestingSchedules[beneficiary];

require(schedule.totalAmount > 0, "No vesting schedule found");
require(!schedule.revoked, "Vesting schedule already revoked");

// Calculate vested amount
uint256 vestedAmount = calculateVestedAmount(beneficiary);
uint256 claimedAmount = schedule.amountClaimed;

// Calculate unvested amount to return to owner
uint256 unvestedAmount = schedule.totalAmount - vestedAmount;

// Mark schedule as revoked
schedule.revoked = true;

// Transfer unvested tokens back to owner
if (unvestedAmount > 0) {
require(token.transfer(owner(), unvestedAmount), "Token transfer failed");
}

emit VestingRevoked(beneficiary);

}

function pause() external onlyOwner {
Expand Down
3 changes: 2 additions & 1 deletion challenge-1-vesting/contracts/token.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract MockERC20 is ERC20, Ownable(msg.sender) {
contract MockERC20 is ERC20, Ownable {
constructor(string memory name, string memory symbol) ERC20(name, symbol) {}

function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
}

2 changes: 1 addition & 1 deletion challenge-2-yield-farm/contracts/yeild.sol
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ contract YieldFarm is ReentrancyGuard, Ownable {
constructor(
address _lpToken,
address _rewardToken,
uint256 _rewardRate
uint256 _rewardRategit
) Ownable(msg.sender) {
// TODO: Initialize contract state
}
Expand Down