-
Notifications
You must be signed in to change notification settings - Fork 4
/
wstKSM.sol
104 lines (92 loc) · 3.49 KB
/
wstKSM.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../interfaces/ILido.sol";
contract WstKSM is ERC20 {
// LIDO contract
ILido public LIDO;
// vKSM precompile
IERC20 public VKSM;
// Token decimals
uint8 internal _decimals;
/**
* @param _lido address of the StKSM token to wrap
*/
constructor(ILido _lido, IERC20 _vKSM, uint8 __decimals) ERC20("Wrapped liquid staked KSM", "wstKSM") {
require(__decimals > 0, "WSTKSM: INCORRECT_DECIMALS");
LIDO = _lido;
VKSM = _vKSM;
_decimals = __decimals;
}
/**
* @notice Stub fallback for native token, always reverting
*/
fallback() external {
revert("WSTKSM: FORBIDDEN");
}
/**
* @return the number of decimals for getting user representation of a token amount.
*/
function decimals() public view override returns (uint8) {
return _decimals;
}
/**
* @notice Stake vKSM to stKSM and wrap stKSM to wstKSM
* @param _vKSMAmount amount of vKSM
* @return Amount of wstKSM for a given vKSM amount
*/
function submit(uint256 _vKSMAmount) external returns (uint256) {
require(_vKSMAmount > 0, "WSTKSM: ZERO_VKSM");
VKSM.transferFrom(msg.sender, address(this), _vKSMAmount);
if (VKSM.allowance(address(this), address(LIDO)) < _vKSMAmount) {
VKSM.approve(address(LIDO), type(uint256).max);
}
uint256 shares = LIDO.deposit(_vKSMAmount);
require(shares > 0, "WSTKSM: ZERO_SHARES");
_mint(msg.sender, shares);
return shares;
}
/**
* @notice Wrap stKSM to wstKSM
* @param _stKSMAmount amount of stKSM
* @return Amount of wstKSM for a given stKSM amount
*/
function wrap(uint256 _stKSMAmount) external returns (uint256) {
require(_stKSMAmount > 0, "WSTKSM: ZERO_STKSM");
uint256 wstKSMAmount = LIDO.getSharesByPooledKSM(_stKSMAmount);
require(wstKSMAmount > 0, "WSTKSM: MINT_ZERO_AMOUNT");
_mint(msg.sender, wstKSMAmount);
require(LIDO.transferFrom(msg.sender, address(this), _stKSMAmount), "WSTKSM: TRANSFER_FROM_REVERT");
return wstKSMAmount;
}
/**
* @notice Unwrap wstKSM to stKSM
* @param _wstKSMAmount amount of wstKSM
* @return Amount of stKSM for a given wstKSM amount
*/
function unwrap(uint256 _wstKSMAmount) external returns (uint256) {
require(_wstKSMAmount > 0, "WSTKSM: ZERO_WSTKSM");
uint256 stKSMAmount = LIDO.getPooledKSMByShares(_wstKSMAmount);
require(stKSMAmount > 0, "WSTKSM: BURN_ZERO_AMOUNT");
_burn(msg.sender, _wstKSMAmount);
require(LIDO.transfer(msg.sender, stKSMAmount), "WSTKSM: TRANSFER_REVERT");
return stKSMAmount;
}
/**
* @notice Get amount of wstKSM for a given amount of stKSM
* @param _stKSMAmount amount of stKSM
* @return Amount of wstKSM for a given stKSM amount
*/
function getWstKSMByStKSM(uint256 _stKSMAmount) external view returns (uint256) {
return LIDO.getSharesByPooledKSM(_stKSMAmount);
}
/**
* @notice Get amount of stKSM for a given amount of wstKSM
* @param _wstKSMAmount amount of wstKSM
* @return Amount of stKSM for a given wstKSM amount
*/
function getStKSMByWstKSM(uint256 _wstKSMAmount) external view returns (uint256) {
return LIDO.getPooledKSMByShares(_wstKSMAmount);
}
}