Skip to content

Commit

Permalink
fea: add psm
Browse files Browse the repository at this point in the history
  • Loading branch information
ricklista committed Oct 30, 2024
1 parent e5bfd29 commit ff78a68
Show file tree
Hide file tree
Showing 38 changed files with 2,322 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "lib/forge-std"]
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
10 changes: 9 additions & 1 deletion contracts/hMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ library hMath {

uint256 constant ONE = 10 ** 27;

function rpow(uint x, uint n, uint b) internal pure returns (uint z) {
function rpow(uint256 x, uint256 n, uint256 b) internal pure returns (uint256 z) {
assembly {
switch x case 0 {switch n case 0 {z := b} default {z := 0}}
default {
Expand All @@ -28,4 +28,12 @@ library hMath {
}
}
}

function rmul(uint x, uint y) internal pure returns (uint z) {
unchecked {
z = x * y;
require(y == 0 || z / y == x);
z = z / hMath.ONE;
}
}
}
4 changes: 4 additions & 0 deletions contracts/interfaces/HayLike.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ interface HayLike is IERC20{
function transferFrom(address, address, uint256) external returns (bool);

function approve(address, uint256) external returns (bool);

function mint(address, uint256) external;

function burn(address, uint256) external;
}
11 changes: 11 additions & 0 deletions contracts/interfaces/IAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
pragma solidity ^0.8.10;

interface IAdapter {
function deposit(uint256 amount) external;

function withdraw(address account, uint256 amount) external;

function totalAvailableAmount() external returns (uint256);

function withdrawAll() external returns (uint256);
}
9 changes: 9 additions & 0 deletions contracts/interfaces/IEarnPool.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pragma solidity ^0.8.10;

interface IEarnPool {
function deposit(address account, uint256 gemAmount, uint256 lisUSDAmount) external;

function withdrawLisUSD(address account, uint256 amount) external returns (uint256);

function withdrawGem(address account, uint256 amount) external returns (uint256);
}
5 changes: 5 additions & 0 deletions contracts/interfaces/ILisUSDPool.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma solidity ^0.8.10;

interface ILisUSDPool {
function depositFor(address pool, address account, uint256 amount) external;
}
7 changes: 7 additions & 0 deletions contracts/interfaces/IPSM.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pragma solidity ^0.8.10;

interface IPSM {
function buy(uint256 amount) external;

function sell(uint256 amount) external;
}
15 changes: 15 additions & 0 deletions contracts/interfaces/IVBep20Delegate.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
pragma solidity ^0.8.10;

interface IVBep20Delegate {
function mint(uint256 mintAmount) external returns (uint256);

function redeem(uint256 redeemTokens) external returns (uint256);

function exchangeRateStored() external view returns (uint256);

function accrueInterest() external returns (uint256);

function borrow(uint256 borrowAmount) external returns (uint256);

function repayBorrow(uint256 repayAmount) external returns (uint256);
}
7 changes: 7 additions & 0 deletions contracts/interfaces/IVaultManager.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pragma solidity ^0.8.10;

interface IVaultManager {
function deposit(uint256 amount) external;

function withdraw(address receiver, uint256 amount) external;
}
2 changes: 2 additions & 0 deletions contracts/interfaces/VatLike.sol
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ interface VatLike {
function cage() external;

function uncage() external;

function debt() external view returns (uint256);
}
11 changes: 11 additions & 0 deletions contracts/mock/MockUSDC.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.10;

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

contract MockUSDC is ERC20 {
constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
uint256 initialSupply = 1e18 * 1e9;
_mint(msg.sender, initialSupply);
}
}
120 changes: 120 additions & 0 deletions contracts/psm/EarnPool.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
pragma solidity ^0.8.10;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "../interfaces/ILisUSDPool.sol";
import "../interfaces/IPSM.sol";
import "../interfaces/IStakeLisUSDListaDistributor.sol";

contract EarnPool is AccessControlUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable {
using SafeERC20 for IERC20;

// token => psm
mapping(address => address) public psm;

address public lisUSDPool; // lisUSD pool address
address public lisUSD; // lisUSD address

bytes32 public constant MANAGER = keccak256("MANAGER"); // manager role
bytes32 public constant PAUSE = keccak256("PAUSE"); // pause role

event SetLisUSDPool(address lisUSDPool);
event SetLisUSD(address lisUSD);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

/**
* @dev initialize contract
* @param _lisUSDPool lisUSD pool address
* @param _lisUSD lisUSD address
*/
function initialize(
address _lisUSDPool,
address _lisUSD
) public initializer {
require(_lisUSDPool != address(0), "lisUSDPool cannot be zero address");
require(_lisUSD != address(0), "lisUSD cannot be zero address");
__AccessControl_init();
__ReentrancyGuard_init();
__Pausable_init();

_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
_setupRole(MANAGER, msg.sender);

lisUSDPool = _lisUSDPool;
lisUSD = _lisUSD;

emit SetLisUSDPool(_lisUSDPool);
emit SetLisUSD(_lisUSD);
}

/**
* @dev deposit token to earn pool
* @param amount token amount
*/
function deposit(address token, uint256 amount) external nonReentrant whenNotPaused {
require(amount > 0, "amount must be greater than zero");
require(psm[token] != address(0), "psm not set");

address account = msg.sender;
// transfer token to earn pool
IERC20(token).safeTransferFrom(account, address(this), amount);

// convert token to lisUSD by psm
IERC20(token).safeIncreaseAllowance(psm[token], amount);
uint256 before = IERC20(lisUSD).balanceOf(address(this));
IPSM(psm[token]).sell(amount);
uint256 lisUSDAmount = IERC20(lisUSD).balanceOf(address(this)) - before;

// deposit lisUSD to lisUSD pool
IERC20(lisUSD).safeIncreaseAllowance(lisUSDPool, lisUSDAmount);
ILisUSDPool(lisUSDPool).depositFor(token, account, lisUSDAmount);
}


/**
* @dev pause contract
*/
function pause() external onlyRole(PAUSE) {
_pause();
}

/**
* @dev toggle pause contract
*/
function togglePause() external onlyRole(DEFAULT_ADMIN_ROLE) {
if (paused()) {
_unpause();
} else {
_pause();
}
}

/**
* @dev set psm
* @param _token token address
* @param _psm psm address
*/
function setPSM(address _token, address _psm) external onlyRole(MANAGER) {
require(_token != address(0), "token cannot be zero address");
require(_psm != address(0), "psm cannot be zero address");
require(psm[_token] == address(0), "psm already set");
psm[_token] = _psm;
}

/**
* @dev remove psm
* @param _token token address
*/
function removePSM(address _token) external onlyRole(MANAGER) {
delete psm[_token];
}


}
Loading

0 comments on commit ff78a68

Please sign in to comment.