本文合约部署步骤:https://blog.csdn.net/wonderBlock/article/details/109903310
本文环境:以太坊POA联盟链 + chrome浏览器 + metamask + remix
本文内容:本文介绍通过质押底层币(以太坊)资产获取收益的一般逻辑及其实现方法,该方案在很多 defi 项目得到应用;本文中的收益为ERC20通证,收益获取也可以理解为挖矿行为;
1.质押挖矿合约源码
1.1 SafeMath.sol
-
pragma solidity
0.5
.8;
-
-
library SafeMath {
-
function add(uint256 a, uint256 b) internal pure returns (uint256) {
-
uint256 c = a + b;
-
require(c >= a,
"SafeMath: addition overflow");
-
return c;
-
}
-
-
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
-
return sub(a, b,
"SafeMath: subtraction overflow");
-
}
-
-
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
-
require(b <= a, errorMessage);
-
uint256 c = a - b;
-
return c;
-
}
-
-
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
-
if (a ==
0) {
-
return
0;
-
}
-
uint256 c = a * b;
-
require(c / a == b,
"SafeMath: multiplication overflow");
-
return c;
-
}
-
-
function div(uint256 a, uint256 b) internal pure returns (uint256) {
-
return div(a, b,
"SafeMath: division by zero");
-
}
-
-
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
-
require(b >
0, errorMessage);
-
uint256 c = a / b;
-
return c;
-
}
-
-
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
-
return mod(a, b,
"SafeMath: modulo by zero");
-
}
-
-
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
-
require(b !=
0, errorMessage);
-
return a % b;
-
}
-
}
它提供了数学函数来保护您的合约不受溢出和下溢的影响,以达到更安全的计算目的;使用该库可以消除没有检测的计算类错误;因此建议始终使用它;
1.2 Address.sol
-
pragma solidity
0.5
.8;
-
-
library Address {
-
function isContract(address account) internal view returns (bool) {
-
bytes32 codehash;
-
// 空字符串hash值
-
bytes32 accountHash =
0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
-
//内联编译(inline assembly)语言,是用一种非常底层的方式来访问EVM
-
assembly { codehash := extcodehash(account) }
-
return (codehash != accountHash && codehash !=
0x0);
-
}
-
-
function sendValue(address payable recipient, uint256 amount) internal {
-
require(address(this).balance >= amount,
"Address: insufficient balance");
-
(
bool success, ) = recipient.call.value(amount)(
"");
-
require(success,
"Address: unable to send value, recipient may have reverted");
-
}
-
}
与地址类型相关的函数集合;
功能主要包括判断地址类型(合约地址 or 账号地址),限定地址调用合约功能(比如限定余额充足)等;
1.3 SafeERC20.sol
-
pragma solidity
0.5
.8;
-
-
import
"./Address.sol";
-
import
"./SafeMath.sol";
-
-
library SafeERC20 {
-
using SafeMath
for uint256;
-
using Address
for address;
-
-
function safeTransfer(ERC20 token, address to, uint256 value) internal {
-
callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
-
}
-
-
function safeTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
-
callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector,
from, to, value));
-
}
-
-
function safeApprove(ERC20 token, address spender, uint256 value) internal {
-
require((value ==
0) || (token.allowance(address(this), spender) ==
0),
"SafeERC20: approve from non-zero to non-zero allowance");
-
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
-
}
-
-
function safeIncreaseAllowance(ERC20 token, address spender, uint256 value) internal {
-
uint256 newAllowance = token.allowance(address(this), spender).add(value);
-
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
-
}
-
-
function safeDecreaseAllowance(ERC20 token, address spender, uint256 value) internal {
-
uint256 newAllowance = token.allowance(address(this), spender).sub(value,
"SafeERC20: decreased allowance below zero");
-
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
-
}
-
-
function callOptionalReturn(ERC20 token, bytes memory data) private {
-
require(address(token).isContract(),
"SafeERC20: call to non-contract");
-
(
bool success, bytes memory returndata) = address(token).call(data);
-
require(success,
"SafeERC20: low-level call failed");
-
if (returndata.length >
0) {
-
require(abi.decode(returndata, (
bool)),
"SafeERC20: ERC20 operation did not succeed");
-
}
-
}
-
}
-
-
interface ERC20 {
-
function totalSupply() external view returns (uint256);
-
function balanceOf(address account) external view returns (uint256);
-
function transfer(address recipient, uint256 amount) external returns (bool);
-
function allowance(address owner, address spender) external view returns (uint256);
-
function approve(address spender, uint256 amount) external returns (bool);
-
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
-
event Transfer(address indexed
from, address indexed to, uint256 value);
-
event Approval(address indexed owner, address indexed spender, uint256 value);
-
}
标准ERC20接口,本文中的质押收益使用ERC20支付,也可以认为是质押挖矿的标的;
1.4 ProfitToken.sol
-
pragma solidity ^
0.4
.25;
-
-
library SafeMath {
-
/**
-
* @dev Multiplies two numbers, reverts on overflow.
-
*/
-
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
-
if (a ==
0) {
-
return
0;
-
}
-
uint256 c = a * b;
-
require(c / a == b);
-
return c;
-
}
-
-
/**
-
* @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
-
*/
-
function div(uint256 a, uint256 b) internal pure returns (uint256) {
-
require(b >
0);
// Solidity only automatically asserts when dividing by 0
-
uint256 c = a / b;
-
return c;
-
}
-
-
/**
-
* @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
-
*/
-
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
-
require(b <= a);
-
uint256 c = a - b;
-
return c;
-
}
-
-
/**
-
* @dev Adds two numbers, reverts on overflow.
-
*/
-
function add(uint256 a, uint256 b) internal pure returns (uint256) {
-
uint256 c = a + b;
-
require(c >= a);
-
return c;
-
}
-
-
/**
-
* @dev Divides two numbers and returns the remainder (unsigned integer modulo),
-
* reverts when dividing by zero.
-
*/
-
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
-
require(b !=
0);
-
return a % b;
-
}
-
}
-
-
interface IERC20 {
-
function totalSupply() external view returns (uint256);
-
function balanceOf(address who) external view returns (uint256);
-
function allowance(address owner, address spender) external view returns (uint256);
-
function transfer(address to, uint256 value) external returns (bool);
-
function approve(address spender, uint256 value) external returns (bool);
-
function transferFrom(address from, address to, uint256 value) external returns (bool);
-
event Transfer(address indexed
from,address indexed to,uint256 value);
-
event Approval(address indexed owner,address indexed spender,uint256 value);
-
}
-
-
contract ERC20 is IERC20 {
-
using SafeMath
for uint256;
-
mapping (address => uint256)
public _balances;
-
mapping (address => mapping (address => uint256))
private _allowed;
-
uint256
public _totalSupply;
-
-
/**
-
* @dev Total number of tokens in existence
-
*/
-
function totalSupply() public view returns (uint256) {
-
return _totalSupply;
-
}
-
-
function balanceOf(address owner) public view returns (uint256) {
-
return _balances[owner];
-
}
-
-
function allowance(address owner,address spender) public view returns (uint256) {
-
return _allowed[owner][spender];
-
}
-
-
function transfer(address to, uint256 value) public returns (bool) {
-
_transfer(msg.sender, to, value);
-
return
true;
-
}
-
-
function approve(address spender, uint256 value) public returns (bool) {
-
require(spender != address(
0));
-
_allowed[msg.sender][spender] = value;
-
emit Approval(msg.sender, spender, value);
-
return
true;
-
}
-
-
function transferFrom(address from,address to,uint256 value) public returns (bool) {
-
require(value <= _allowed[
from][msg.sender]);
-
_allowed[
from][msg.sender] = _allowed[
from][msg.sender].sub(value);
-
_transfer(
from, to, value);
-
return
true;
-
}
-
-
function increaseAllowance(address spender,uint256 addedValue) public returns (bool) {
-
require(spender != address(
0));
-
_allowed[msg.sender][spender] = (_allowed[msg.sender][spender].add(addedValue));
-
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
-
return
true;
-
}
-
-
function decreaseAllowance(address spender,uint256 subtractedValue) public returns (bool) {
-
require(spender != address(
0));
-
_allowed[msg.sender][spender] = (_allowed[msg.sender][spender].sub(subtractedValue));
-
emit Approval(msg.sender, spender, _allowed[msg.sender][spender]);
-
return
true;
-
}
-
-
function _transfer(address from, address to, uint256 value) internal {
-
require(to != address(
0));
-
require(value <= _balances[
from]);
-
_balances[
from] = _balances[
from].sub(value);
-
_balances[to] = _balances[to].add(value);
-
emit Transfer(
from, to, value);
-
}
-
}
-
-
contract ProfitToken is ERC20 {
-
string
private _name;
-
string
private _symbol;
-
uint8
private _decimals;
-
-
constructor (uint256 _initialAmount,
string name, uint8 decimals,
string symbol)
public {
-
_name = name;
-
_symbol = symbol;
-
_decimals = decimals;
-
_totalSupply = _initialAmount.mul(
10 ** uint256(_decimals));
-
_balances[msg.sender] = _initialAmount.mul(
10 ** uint256(_decimals));
-
}
-
-
/**
-
* @return the name of the token.
-
*/
-
function name() public view returns (string) {
-
return _name;
-
}
-
-
/**
-
* @return the symbol of the token.
-
*/
-
function symbol() public view returns (string) {
-
return _symbol;
-
}
-
-
/**
-
* @return the number of decimals of the token.
-
*/
-
function decimals() public view returns (uint8) {
-
return _decimals;
-
}
-
-
}
独立实现的、符合ERC20标准的资产合约,用于分发质押收益,用户也可以使用任何符合ERC20标准的资产合约(参考第21、22篇文档);
1.5 GinPledge.sol
-
pragma solidity
0.5
.8;
-
-
import
"./SafeMath.sol";
-
import
"./SafeERC20.sol";
-
-
contract GinPledge {
-
using SafeMath
for uint256;
-
using SafeERC20
for ERC20;
-
-
address
private owner;
-
address
private profitor;
-
bool _isDIS =
false;
-
-
mapping(address => PledgeOrder) _orders;
-
mapping(address => uint256) _takeProfitTime;
-
-
ERC20 _Token;
-
KeyFlag[] keys;
-
-
uint256 size;
-
uint256 _maxPledgeAmount;
-
uint256 _maxMiningAmount;
-
uint256 _leftMiningAmount;
-
uint256 _minAmount;
-
uint256 _totalPledegAmount;
-
uint256 _maxPreMiningAmount;
-
uint256 _startTime;
-
uint256 _endTime;
-
uint256 _precentUp=
100;
-
uint256 _precentDown=
100;
-
-
struct PledgeOrder {
-
bool isExist;
-
uint256 token;
-
uint256 profitToken;
-
uint256 time;
-
uint256 index;
-
}
-
-
struct KeyFlag {
-
address key;
-
bool isExist;
-
}
-
-
constructor (
-
address tokenAddress,
-
address paramProfitor,
-
uint256 maxPledgeAmount,
-
uint256 minAmount,
-
uint256 maxMiningAmount,
-
uint256 maxPreMiningAmount,
-
uint256 startTime,
-
uint256 endTime
-
)
-
public
-
{
-
_Token = ERC20(tokenAddress);
-
owner = msg.sender;
-
profitor = paramProfitor;
-
_maxPledgeAmount = maxPledgeAmount;
-
_minAmount = minAmount;
-
_maxMiningAmount = maxMiningAmount;
-
_maxPreMiningAmount = maxPreMiningAmount;
-
_startTime = startTime;
-
_endTime = endTime;
-
_leftMiningAmount = maxMiningAmount;
-
}
-
-
function pledgeToken() public payable{
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
require(_isDIS,
"is disable");
-
require(_leftMiningAmount>
0,
"less token");
-
require(msg.value>=_minAmount,
"less token");
-
require(_totalPledegAmount.add(msg.value)<=_maxPledgeAmount,
"more token");
-
require(block.timestamp>=_startTime&&block.timestamp<=_endTime,
"is disable");
-
-
if(_orders[msg.sender].isExist==
false){
-
keys.push(KeyFlag(msg.sender,
true));
-
size++;
-
createOrder(msg.value,keys.length.sub(
1));
-
}
else{
-
PledgeOrder storage order=_orders[msg.sender];
-
order.token=order.token.add(msg.value);
-
keys[order.index].isExist=
true;
-
}
-
_totalPledegAmount=_totalPledegAmount.add(msg.value);
-
}
-
-
function createOrder(uint256 trcAmount,uint256 index) private {
-
_orders[msg.sender]=PledgeOrder(
-
true,
-
trcAmount,
-
0,
-
block.timestamp,
-
index
-
);
-
}
-
-
function profit() public onlyProfitor{
-
require(_leftMiningAmount>
0,
"less token");
-
require(_totalPledegAmount>
0,
"no pledge");
-
uint256 preToken=_maxPreMiningAmount;
-
if(_leftMiningAmount<_maxPreMiningAmount){
-
preToken=_leftMiningAmount;
-
}
-
for(uint i =
0; i < keys.length; i++) {
-
if(keys[i].isExist==
true){
-
PledgeOrder storage order=_orders[keys[i].key];
-
order.profitToken=order.profitToken.add(order.token.mul(preToken).div(_totalPledegAmount));
-
}
-
}
-
_leftMiningAmount=_leftMiningAmount.sub(preToken);
-
}
-
-
function takeProfit() public {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
require(_orders[msg.sender].profitToken>
0,
"less token");
-
uint256 time=block.timestamp;
-
uint256 diff=time.sub(_takeProfitTime[msg.sender]);
-
require(diff>
86400,
"less time");
-
PledgeOrder storage order=_orders[msg.sender];
-
uint256 takeToken=order.profitToken.mul(_precentUp).div(_precentDown);
-
order.profitToken=order.profitToken.sub(takeToken);
-
_takeProfitTime[msg.sender]=time;
-
_Token.safeTransfer(address(msg.sender),takeToken);
-
}
-
-
function takeToken(uint256 amount) public {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
PledgeOrder storage order=_orders[msg.sender];
-
require(order.token>
0,
"no order");
-
require(amount<=order.token,
"less token");
-
_totalPledegAmount=_totalPledegAmount.sub(amount);
-
if(order.token==amount){
-
order.token=
0;
-
keys[order.index].isExist=
false;
-
}
else{
-
order.token=order.token.sub(amount);
-
}
-
address payable addr = getPayable(msg.sender);
-
addr.transfer(amount);
-
}
-
-
function takeAllToken() public {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
PledgeOrder storage order=_orders[msg.sender];
-
require(order.token>
0,
"no order");
-
keys[order.index].isExist=
false;
-
uint256 takeAmount=order.token;
-
order.token=
0;
-
_totalPledegAmount=_totalPledegAmount.sub(takeAmount);
-
uint256 time=block.timestamp;
-
uint256 diff=time.sub(_takeProfitTime[msg.sender]);
-
if(diff>=
86400){
-
uint256 profitPart=order.profitToken.mul(_precentUp).div(_precentDown);
-
keys[order.index].isExist =
false;
-
order.profitToken=order.profitToken.sub(profitPart);
-
_takeProfitTime[msg.sender]=time;
-
_Token.safeTransfer(address(msg.sender),profitPart);
-
}
-
address payable addr = getPayable(msg.sender);
-
addr.transfer(takeAmount);
-
}
-
-
function getPledgeToken(address tokenAddress) public view returns(uint256) {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
PledgeOrder memory order=_orders[tokenAddress];
-
return order.token;
-
}
-
-
function getProfitToken(address tokenAddress) public view returns(uint256) {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
PledgeOrder memory order=_orders[tokenAddress];
-
return order.profitToken;
-
}
-
-
function getTotalPledge() public view returns(uint256) {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
return _totalPledegAmount;
-
}
-
-
function getPayable(address tokenAddress) private pure returns (address payable) {
-
return address(uint168(tokenAddress));
-
}
-
-
function getTakeProfitTime(address tokenAddress) public view returns(uint256) {
-
return _takeProfitTime[tokenAddress];
-
}
-
-
function changeIsDIS(bool flag) public onlyOwner {
-
_isDIS= flag;
-
}
-
-
function changeOwner(address paramOwner) public onlyOwner {
-
require(paramOwner != address(
0));
-
owner= paramOwner;
-
}
-
-
function changeProfitor(address paramProfitor) public onlyOwner {
-
profitor= paramProfitor;
-
}
-
-
modifier onlyOwner(){
-
require(msg.sender == owner);
-
_;
-
}
-
-
modifier onlyProfitor(){
-
require(msg.sender == profitor);
-
_;
-
}
-
-
function getOwner() public view returns (address) {
-
return owner;
-
}
-
-
function getProfitor() public view returns (address) {
-
return profitor;
-
}
-
-
function getsize() public view returns (uint256) {
-
return size;
-
}
-
-
function maxPledgeAmount() public view returns (uint256) {
-
return _maxPledgeAmount;
-
}
-
-
function maxMiningAmount() public view returns (uint256) {
-
return _maxMiningAmount;
-
}
-
-
function leftMiningAmount() public view returns (uint256) {
-
return _leftMiningAmount;
-
}
-
-
function minAmount() public view returns (uint256) {
-
return _minAmount;
-
}
-
-
function maxPreMiningAmount() public view returns (uint256) {
-
return _maxPreMiningAmount;
-
}
-
-
function startTime() public view returns (uint256) {
-
return _startTime;
-
}
-
-
function endTime() public view returns (uint256) {
-
return _endTime;
-
}
-
-
function nowTime() public view returns (uint256) {
-
return block.timestamp;
-
}
-
-
function isDIS() public view returns (bool) {
-
return _isDIS;
-
}
-
-
}
质押挖矿合约;
2.合约主要功能函数介绍
本节介绍质押挖矿合约 GinPledge.sol 的主要功能:
2.1 主要参数
-
address
private owner;
//合约部署(拥有者)账号地址
-
address
private profitor;
//收益分配者账号地址,仅该地址有权分配收益
-
bool _isDIS =
false;
//质押合约功能状态,true才可以进行质押
-
-
ERC20 _Token;
//用于分配收益的ERC20资产
-
KeyFlag[] keys;
//用于标记用户地址的质押状态
-
-
uint256 size;
//质押者地址(用户)数量
-
uint256 _maxPledgeAmount;
//最大质押(底层币)额度
-
uint256 _maxMiningAmount;
//最大挖矿(ERC20收益分配)额度
-
uint256 _leftMiningAmount;
//剩余挖矿额度
-
uint256 _minAmount;
//单次最少质押额度
-
uint256 _totalPledegAmount;
//已质押总额度
-
uint256 _maxPreMiningAmount;
//最大单次分配额度
-
uint256 _startTime;
//开始时间,单位“秒”
-
uint256 _endTime;
//结束时间,单位“秒”
-
uint256 _precentUp=
100;
//与_precentDown一起设定每次收益提取比例
-
uint256 _precentDown=
100;
//与_precentUp一起设定每次收益提取比例
-
-
struct PledgeOrder {
//结构体,用于标记质押用户的各类状态
-
bool isExist;
//质押状态
-
uint256 token;
//质押额度
-
uint256 profitToken;
//收益额度
-
uint256 time;
//最近一次提取收益时间
-
uint256 index;
//质押地址序号
-
}
-
-
struct KeyFlag {
//结构体,用于标记用户地址的质押状态
-
address key;
//地址
-
bool isExist;
//质押状态
-
}
部署合约时,构造函数内的参数需要用户输入,以完成相应的参数设置并实现相应功能;
2.1 质押函数pledgeToken
-
function pledgeToken() public payable{
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
require(_isDIS,
"is disable");
-
require(_leftMiningAmount>
0,
"less token");
-
require(msg.value>=_minAmount,
"less token");
-
require(_totalPledegAmount.add(msg.value)<=_maxPledgeAmount,
"more token");
-
require(block.timestamp>=_startTime&&block.timestamp<=_endTime,
"is disable");
-
-
if(_orders[msg.sender].isExist==
false){
-
keys.push(KeyFlag(msg.sender,
true));
-
size++;
-
createOrder(msg.value,keys.length.
sub(
1));
-
}
else{
-
PledgeOrder storage order=_orders[msg.sender];
-
order.token=order.token.add(msg.value);
-
keys[order.index].isExist=
true;
-
}
-
_totalPledegAmount=_totalPledegAmount.add(msg.value);
-
}
功能说明:
- 明显的,该函数具有接收底层币功能(payable);
- 质押地址必须是账号地址,不能是合约地址;
- 需要合约质押功能已经开始,且在活动限定时间内;
- 剩余挖矿额度大于0;
- 进行质押的底层币额度不能少于最小值,质押后也不能超过限定的最大质押额度;
- 如果该用户之前没有质押过,则建立档案(createOrder),否则仅修改档案;
1.3 收益分配函数profit
-
function profit() public onlyProfitor{
-
require(_leftMiningAmount>
0,
"less token");
-
require(_totalPledegAmount>
0,
"no pledge");
-
uint256 preToken=_maxPreMiningAmount;
-
if(_leftMiningAmount<_maxPreMiningAmount){
-
preToken=_leftMiningAmount;
-
}
-
for(uint i =
0; i < keys.length; i++) {
-
if(keys[i].isExist==
true){
-
PledgeOrder storage order=_orders[keys[i].key];
-
order.profitToken=order.profitToken.add(order.token.mul(preToken).div(_totalPledegAmount));
-
}
-
}
-
_leftMiningAmount=_leftMiningAmount.
sub(preToken);
-
}
功能说明:
- 必须尚有剩余挖矿额度可供分配;
- 当前质押总额必须大于0;
- 如果剩余挖矿额度足够,则按规则分配设定的每次最大分配额度(_maxPreMiningAmount);
- 如果剩余挖矿额度小于每次最大分配额度,则将剩余额度全部进行分配;
- 根据用户质押数量,平均分配所有额度;即质押余额越多,收益越多;
1.4收益提取函数takeProfit
-
function takeProfit() public {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
require(_orders[msg.sender].profitToken>
0,
"less token");
-
uint256
time=block.timestamp;
-
uint256 diff=
time.
sub(_takeProfitTime[msg.sender]);
-
require(diff>
86400,
"less time");
-
PledgeOrder storage order=_orders[msg.sender];
-
uint256 takeToken=order.profitToken.mul(_precentUp).div(_precentDown);
-
order.profitToken=order.profitToken.
sub(takeToken);
-
_takeProfitTime[msg.sender]=
time;
-
_Token.safeTransfer(address(msg.sender),takeToken);
-
}
功能说明:
- 质押地址必须是账号地址,不能是合约地址;
- 质押地址必须有尚未提取的ERC20收益;
- 必须距离上次提取时间超过一天(86400秒,该值可以在部署时修改);
- 通过_precentUp和_precentDown可以设置提取比例,本文示例为100%;
- 记录本次提取时间并完成资产转账;
- 注意:必须提前给合约地址转账足够的ERC20资产,否则用户无法成功提取收益;
1.5 本金提取函数takeToken
-
function takeToken(uint256 amount)
public {
-
require(address(msg.sender) == address(tx.origin),
"no contract");
-
PledgeOrder storage order=_orders[msg.sender];
-
require(order.token>
0,
"no order");
-
require(amount<=order.token,
"less token");
-
_totalPledegAmount=_totalPledegAmount.sub(amount);
-
if(order.token==amount){
-
order.token=
0;
-
keys[order.index].isExist=
false;
-
}
else{
-
order.token=order.token.sub(amount);
-
}
-
address
payable
addr = getPayable(msg.sender);
-
addr.transfer(amount);
-
}
功能说明:
- 质押地址必须是账号地址,不能是合约地址;
- 质押地址必须有尚未提取的本金;
- 用户可以随时提取本金;
- 用户可以确定提取本金的额度(少于或等于本人的质押金额度);
- 完成资产转账;
1.6 其它功能函数
-
//获取用户质押本金余额
-
function getPledgeToken(address tokenAddress) public view returns(uint256) {}
-
-
//获取用户收益余额
-
function getProfitToken(address tokenAddress) public view returns(uint256) {}
-
-
//获取当前质押总额
-
function getTotalPledge() public view returns(uint256) {}
-
-
//地址转换,允许地址接收资产
-
function getPayable(address tokenAddress) private pure returns (address payable) {}
-
-
//设置项目开始状态
-
function changeIsDIS(bool flag) public onlyOwner {}