Skip to content

Commit

Permalink
update liquidity mining
Browse files Browse the repository at this point in the history
  • Loading branch information
jklepatch committed Dec 18, 2020
1 parent 76dda79 commit 2e1d317
Show file tree
Hide file tree
Showing 11 changed files with 5,046 additions and 71 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
pragma solidity ^0.7.2;
pragma solidity ^0.7.3;

import '@openzeppelin/contracts/token/ERC20/ERC20.sol';
import '@openzeppelin/contracts/access/Ownable.sol';

contract BonusToken is ERC20, Ownable {
constructor() ERC20('Bonus Token', 'BTK') Ownable() {}
contract GovernanceToken is ERC20, Ownable {
constructor() ERC20('Governance Token', 'GTK') Ownable() {}

function mint(address to, uint amount) external onlyOwner() {
_mint(to, amount);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
pragma solidity ^0.7.3;

import './UnderlyingToken.sol';
import './LpToken.sol';
import './GovernanceToken.sol';

contract LiquidityPool is LpToken {
mapping(address => uint) public checkpoints;
UnderlyingToken public underlyingToken;
GovernanceToken public governanceToken;
uint constant public REWARD_PER_BLOCK = 1;

constructor(address _underlyingToken, address _governanceToken) {
underlyingToken = UnderlyingToken(_underlyingToken);
governanceToken = GovernanceToken(_governanceToken);
}

function deposit(uint amount) external {
if(checkpoints[msg.sender] == 0) {
checkpoints[msg.sender] = block.number;
}
_distributeRewards(msg.sender);
underlyingToken.transferFrom(msg.sender, address(this), amount);
_mint(msg.sender, amount);
}

function withdraw(uint amount) external {
require(balanceOf(msg.sender) >= amount, 'not enough lp token');
_distributeRewards(msg.sender);
underlyingToken.transfer(msg.sender, amount);
_burn(msg.sender, amount);
}

function _distributeRewards(address beneficiary) internal {
uint checkpoint = checkpoints[beneficiary];
if(block.number - checkpoint > 0) {
uint distributionAmount = (balanceOf(beneficiary) * (block.number - checkpoint) * REWARD_PER_BLOCK);
governanceToken.mint(beneficiary, distributionAmount);
checkpoints[beneficiary] = block.number;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
pragma solidity ^0.7.3;

import './UnderlyingToken.sol';
import './LpToken.sol';
import './GovernanceToken.sol';

//More advanced distribution mechanism with a fixed amount of reward per block
//for the whole contract
//WIP
contract LiquidityPool2 is LpToken {
struct Checkpoint {
uint blockNumber;
uint avgTotalBalance;
}

mapping(address => Checkpoint) public checkpoints;
Checkpoint public globalCheckpoint;

uint constant public REWARD_PER_BLOCK = 1000 * 10 ** 18;

UnderlyingToken public underlyingToken;
GovernanceToken public governanceToken;
uint public genesisBlock;

constructor(address _underlyingToken, address _governanceToken) {
underlyingToken = UnderlyingToken(_underlyingToken);
governanceToken = GovernanceToken(_governanceToken);
globalCheckpoint.blockNumber = block.number;
genesisBlock = block.number;
}

function deposit(uint amount) external {
globalCheckpoint.avgTotalBalance = _getAvgTotalBalance();
globalCheckpoint.blockNumber = block.number;

_distributeRewards(msg.sender);

underlyingToken.transferFrom(msg.sender, address(this), amount);
_mint(msg.sender, amount);

globalCheckpoint.avgTotalBalance = _getAvgTotalBalance();
checkpoints[msg.sender].avgTotalBalance = globalCheckpoint.avgTotalBalance;
checkpoints[msg.sender].blockNumber = block.number;
}

function withdraw(uint amount) external {
require(balanceOf(msg.sender) >= amount, 'not enough lp token');

globalCheckpoint.avgTotalBalance = _getAvgTotalBalance();
globalCheckpoint.blockNumber = block.number;

_distributeRewards(msg.sender);

checkpoints[msg.sender].avgTotalBalance = globalCheckpoint.avgTotalBalance;
checkpoints[msg.sender].blockNumber = block.number;

underlyingToken.transfer(msg.sender, amount);
_burn(msg.sender, amount);

globalCheckpoint.avgTotalBalance = _getAvgTotalBalance();
checkpoints[msg.sender].avgTotalBalance = globalCheckpoint.avgTotalBalance;
checkpoints[msg.sender].blockNumber = block.number;
}

function _getAvgTotalBalance() public view returns(uint) {
if(block.number - genesisBlock == 0) {
return totalSupply();
}
return (globalCheckpoint.avgTotalBalance * (globalCheckpoint.blockNumber - genesisBlock) + totalSupply() * (block.number - globalCheckpoint.blockNumber)) / (block.number - genesisBlock);
}

function _distributeRewards(address beneficiary) internal {
Checkpoint storage userCheckpoint = checkpoints[beneficiary];
if(block.number - userCheckpoint.blockNumber > 0) {
uint avgTotalBalanceRewardPeriod = (globalCheckpoint.avgTotalBalance * globalCheckpoint.blockNumber - userCheckpoint.avgTotalBalance * userCheckpoint.blockNumber) / (block.number - userCheckpoint.blockNumber);
if(avgTotalBalanceRewardPeriod > 0) {
uint distributionAmount = (balanceOf(beneficiary) * (block.number - userCheckpoint.blockNumber) * REWARD_PER_BLOCK) / avgTotalBalanceRewardPeriod;
governanceToken.mint(beneficiary, distributionAmount);
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pragma solidity ^0.7.2;
pragma solidity ^0.7.3;

import '@openzeppelin/contracts/token/ERC20/ERC20.sol';

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pragma solidity ^0.7.3;

import '@openzeppelin/contracts/token/ERC20/ERC20.sol';

contract UnderlyingToken is ERC20 {
constructor() ERC20('Underlying Token', 'UTK') {}

function faucet(address to, uint amount) external {
_mint(to, amount);
}
}

This file was deleted.

Loading

0 comments on commit 2e1d317

Please sign in to comment.