编译器
0.6.12+commit.27d51765
文件 1 的 9:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
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");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 9:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 9:FundRaisingGuild.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
contract FundRaisingGuild {
using SafeERC20 for IERC20;
address public stakingContract;
constructor(address _stakingContract) public {
stakingContract = _stakingContract;
}
function withdrawTo(IERC20 _token, address _recipient, uint256 _amount) external {
require(msg.sender == stakingContract, "Guild.withdrawTo: Only staking contract");
_token.safeTransfer(_recipient, _amount);
}
function tokenBalance(IERC20 _token) external returns (uint256) {
return _token.balanceOf(address(this));
}
}
文件 4 的 9:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
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);
}
文件 5 的 9:LaunchPoolERC20FundRaisingWithDelayedVesting.sol
pragma solidity 0.6.12;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import { FundRaisingGuild } from "./FundRaisingGuild.sol";
contract LaunchPoolERC20FundRaisingWithDelayedVesting is Ownable, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
struct UserInfo {
uint256 amount;
uint256 pledgeFundingAmount;
uint256 rewardDebtRewards;
uint256 tokenAllocDebt;
}
struct PoolInfo {
IERC20 rewardToken;
IERC20 fundRaisingToken;
uint256 tokenAllocationStartBlock;
uint256 stakingEndBlock;
uint256 pledgeFundingEndBlock;
uint256 targetRaise;
uint256 maxStakingAmountPerUser;
}
IERC20 public stakingToken;
FundRaisingGuild public rewardGuildBank;
PoolInfo[] public poolInfo;
mapping(uint256 => uint256) public poolIdToAccPercentagePerShare;
mapping(uint256 => uint256) public poolIdToLastPercentageAllocBlock;
mapping(uint256 => uint256) public poolIdToRewardPerBlock;
mapping(uint256 => uint256) public poolIdToLastRewardBlock;
mapping(uint256 => uint256) public poolIdToRewardStartBlock;
mapping(uint256 => uint256) public poolIdToRewardCliffEndBlock;
mapping(uint256 => uint256) public poolIdToRewardEndBlock;
mapping(uint256 => uint256) public poolIdToAccRewardPerShareVesting;
mapping(uint256 => uint256) public poolIdToMaxRewardTokensAvailableForVesting;
mapping(uint256 => uint256) public poolIdToTotalStaked;
mapping(uint256 => uint256) public poolIdToTotalRaised;
mapping(uint256 => uint256) public poolIdToTotalFundedPercentageOfTargetRaise;
mapping(uint256 => bool) public poolIdToFundsClaimed;
mapping(uint256 => mapping(address => UserInfo)) public userInfo;
uint256 public constant TOTAL_TOKEN_ALLOCATION_POINTS = (100 * (10 ** 18));
event ContractDeployed(address indexed guildBank);
event PoolAdded(uint256 indexed pid);
event PoolRewardTokenAdded(uint256 indexed pid, address rewardToken);
event Pledge(address indexed user, uint256 indexed pid, uint256 amount);
event PledgeFunded(address indexed user, uint256 indexed pid, uint256 amount);
event RewardsSetUp(uint256 indexed pid, uint256 amount, uint256 rewardEndBlock);
event RewardClaimed(address indexed user, uint256 indexed pid, uint256 amount);
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount);
event FundRaisingClaimed(uint256 indexed pid, address indexed recipient, uint256 amount);
constructor(IERC20 _stakingToken) public {
require(address(_stakingToken) != address(0), "constructor: _stakingToken must not be zero address");
stakingToken = _stakingToken;
rewardGuildBank = new FundRaisingGuild(address(this));
emit ContractDeployed(address(rewardGuildBank));
}
function numberOfPools() external view returns (uint256) {
return poolInfo.length;
}
function add(
IERC20 _rewardToken,
IERC20 _fundRaisingToken,
uint256 _tokenAllocationStartBlock,
uint256 _stakingEndBlock,
uint256 _pledgeFundingEndBlock,
uint256 _targetRaise,
uint256 _maxStakingAmountPerUser,
bool _withUpdate
) public onlyOwner {
address fundRaisingTokenAddress = address(_fundRaisingToken);
require(fundRaisingTokenAddress != address(0), "add: _fundRaisingToken is zero address");
require(_tokenAllocationStartBlock < _stakingEndBlock, "add: _tokenAllocationStartBlock must be before staking end");
require(_stakingEndBlock < _pledgeFundingEndBlock, "add: staking end must be before funding end");
require(_targetRaise > 0, "add: Invalid raise amount");
if (_withUpdate) {
massUpdatePools();
}
poolInfo.push(PoolInfo({
rewardToken : _rewardToken,
fundRaisingToken : _fundRaisingToken,
tokenAllocationStartBlock: _tokenAllocationStartBlock,
stakingEndBlock: _stakingEndBlock,
pledgeFundingEndBlock: _pledgeFundingEndBlock,
targetRaise: _targetRaise,
maxStakingAmountPerUser: _maxStakingAmountPerUser
}));
poolIdToLastPercentageAllocBlock[poolInfo.length.sub(1)] = _tokenAllocationStartBlock;
emit PoolAdded(poolInfo.length.sub(1));
}
function pledge(uint256 _pid, uint256 _amount) external nonReentrant {
require(_pid < poolInfo.length, "pledge: Invalid PID");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(_amount > 0, "pledge: No pledge specified");
require(block.number <= pool.stakingEndBlock, "pledge: Staking no longer permitted");
require(user.amount.add(_amount) <= pool.maxStakingAmountPerUser, "pledge: can not exceed max staking amount per user");
updatePool(_pid);
user.amount = user.amount.add(_amount);
user.tokenAllocDebt = user.tokenAllocDebt.add(_amount.mul(poolIdToAccPercentagePerShare[_pid]).div(1e18));
poolIdToTotalStaked[_pid] = poolIdToTotalStaked[_pid].add(_amount);
stakingToken.safeTransferFrom(address(msg.sender), address(this), _amount);
emit Pledge(msg.sender, _pid, _amount);
}
function getPledgeFundingAmount(uint256 _pid) public view returns (uint256) {
require(_pid < poolInfo.length, "getPledgeFundingAmount: Invalid PID");
PoolInfo memory pool = poolInfo[_pid];
UserInfo memory user = userInfo[_pid][msg.sender];
(uint256 accPercentPerShare,) = getAccPercentagePerShareAndLastAllocBlock(_pid);
uint256 userPercentageAllocated = user.amount.mul(accPercentPerShare).div(1e18).sub(user.tokenAllocDebt);
return userPercentageAllocated.mul(pool.targetRaise).div(TOTAL_TOKEN_ALLOCATION_POINTS);
}
function fundPledge(uint256 _pid) external nonReentrant {
require(_pid < poolInfo.length, "fundPledge: Invalid PID");
updatePool(_pid);
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.pledgeFundingAmount == 0, "fundPledge: Pledge has already been funded");
require(block.number > pool.stakingEndBlock, "fundPledge: Staking is still taking place");
require(block.number <= pool.pledgeFundingEndBlock, "fundPledge: Deadline has passed to fund your pledge");
require(user.amount > 0, "fundPledge: Must have staked");
uint256 pledgeFundingAmount = getPledgeFundingAmount(_pid);
require(pledgeFundingAmount > 0, "fundPledge: must have positive pledge amount");
pool.fundRaisingToken.safeTransferFrom(msg.sender, address(this), pledgeFundingAmount);
poolIdToTotalRaised[_pid] = poolIdToTotalRaised[_pid].add(pledgeFundingAmount);
(uint256 accPercentPerShare,) = getAccPercentagePerShareAndLastAllocBlock(_pid);
uint256 userPercentageAllocated = user.amount.mul(accPercentPerShare).div(1e18).sub(user.tokenAllocDebt);
poolIdToTotalFundedPercentageOfTargetRaise[_pid] = poolIdToTotalFundedPercentageOfTargetRaise[_pid].add(userPercentageAllocated);
user.pledgeFundingAmount = pledgeFundingAmount;
stakingToken.safeTransfer(address(msg.sender), user.amount);
emit PledgeFunded(msg.sender, _pid, pledgeFundingAmount);
}
function getTotalRaisedVsTarget(uint256 _pid) external view returns (uint256 raised, uint256 target) {
return (poolIdToTotalRaised[_pid], poolInfo[_pid].targetRaise);
}
function setRewardTokenOnPool(uint256 _pid, IERC20 _rewardToken) external onlyOwner {
require(_pid < poolInfo.length, "setRewardTokenOnPool: Invalid PID");
address rewardTokenAddress = address(_rewardToken);
require(rewardTokenAddress != address(0), "setRewardTokenOnPool: _rewardToken is zero address");
PoolInfo storage pool = poolInfo[_pid];
require(address(pool.rewardToken) == address(0), "setRewardTokenOnPool: rewardToken already set");
pool.rewardToken = _rewardToken;
emit PoolRewardTokenAdded(_pid, rewardTokenAddress);
}
function setupVestingRewards(uint256 _pid, uint256 _rewardAmount, uint256 _rewardStartBlock, uint256 _rewardCliffEndBlock, uint256 _rewardEndBlock)
external nonReentrant onlyOwner {
require(_pid < poolInfo.length, "setupVestingRewards: Invalid PID");
require(_rewardStartBlock > block.number, "setupVestingRewards: start block in the past");
require(_rewardCliffEndBlock >= _rewardStartBlock, "setupVestingRewards: Cliff must be after or equal to start block");
require(_rewardEndBlock > _rewardCliffEndBlock, "setupVestingRewards: end block must be after cliff block");
PoolInfo storage pool = poolInfo[_pid];
address rewardTokenAddress = address(pool.rewardToken);
require(rewardTokenAddress != address(0), "setupVestingRewards: rewardToken is zero address");
require(block.number > pool.pledgeFundingEndBlock, "setupVestingRewards: Stakers are still pledging");
uint256 vestingLength = _rewardEndBlock.sub(_rewardStartBlock);
poolIdToMaxRewardTokensAvailableForVesting[_pid] = _rewardAmount;
poolIdToRewardPerBlock[_pid] = _rewardAmount.div(vestingLength);
poolIdToRewardStartBlock[_pid] = _rewardStartBlock;
poolIdToLastRewardBlock[_pid] = _rewardStartBlock;
poolIdToRewardCliffEndBlock[_pid] = _rewardCliffEndBlock;
poolIdToRewardEndBlock[_pid] = _rewardEndBlock;
pool.rewardToken.safeTransferFrom(msg.sender, address(rewardGuildBank), _rewardAmount);
emit RewardsSetUp(_pid, _rewardAmount, _rewardEndBlock);
}
function pendingRewards(uint256 _pid, address _user) external view returns (uint256) {
require(_pid < poolInfo.length, "pendingRewards: invalid _pid");
UserInfo memory user = userInfo[_pid][_user];
if (user.pledgeFundingAmount == 0) {
return 0;
}
uint256 accRewardPerShare = poolIdToAccRewardPerShareVesting[_pid];
uint256 rewardEndBlock = poolIdToRewardEndBlock[_pid];
uint256 lastRewardBlock = poolIdToLastRewardBlock[_pid];
uint256 rewardPerBlock = poolIdToRewardPerBlock[_pid];
if (block.number > lastRewardBlock && rewardEndBlock != 0 && poolIdToTotalStaked[_pid] != 0) {
uint256 maxEndBlock = block.number <= rewardEndBlock ? block.number : rewardEndBlock;
uint256 multiplier = getMultiplier(lastRewardBlock, maxEndBlock);
uint256 reward = multiplier.mul(rewardPerBlock);
accRewardPerShare = accRewardPerShare.add(reward.mul(1e18).div(poolIdToTotalFundedPercentageOfTargetRaise[_pid]));
}
(uint256 accPercentPerShare,) = getAccPercentagePerShareAndLastAllocBlock(_pid);
uint256 userPercentageAllocated = user.amount.mul(accPercentPerShare).div(1e18).sub(user.tokenAllocDebt);
return userPercentageAllocated.mul(accRewardPerShare).div(1e18).sub(user.rewardDebtRewards);
}
function massUpdatePools() public {
for (uint256 pid = 0; pid < poolInfo.length; pid++) {
updatePool(pid);
}
}
function updatePool(uint256 _pid) public {
require(_pid < poolInfo.length, "updatePool: invalid _pid");
PoolInfo storage poolInfo = poolInfo[_pid];
if (block.number < poolInfo.tokenAllocationStartBlock) {
return;
}
if (poolIdToTotalStaked[_pid] == 0) {
poolIdToLastPercentageAllocBlock[_pid] = block.number;
return;
}
uint256 maxEndBlockForPercentAlloc = block.number <= poolInfo.stakingEndBlock ? block.number : poolInfo.stakingEndBlock;
uint256 blocksSinceLastPercentAlloc = getMultiplier(poolIdToLastPercentageAllocBlock[_pid], maxEndBlockForPercentAlloc);
if (poolIdToRewardEndBlock[_pid] == 0 && blocksSinceLastPercentAlloc > 0) {
(uint256 accPercentPerShare, uint256 lastAllocBlock) = getAccPercentagePerShareAndLastAllocBlock(_pid);
poolIdToAccPercentagePerShare[_pid] = accPercentPerShare;
poolIdToLastPercentageAllocBlock[_pid] = lastAllocBlock;
}
if (poolIdToRewardEndBlock[_pid] == 0) {
return;
}
if (block.number < poolIdToRewardCliffEndBlock[_pid]) {
return;
}
uint256 rewardEndBlock = poolIdToRewardEndBlock[_pid];
uint256 lastRewardBlock = poolIdToLastRewardBlock[_pid];
uint256 maxEndBlock = block.number <= rewardEndBlock ? block.number : rewardEndBlock;
uint256 multiplier = getMultiplier(lastRewardBlock, maxEndBlock);
if (multiplier == 0) {
return;
}
uint256 rewardPerBlock = poolIdToRewardPerBlock[_pid];
uint256 reward = multiplier.mul(rewardPerBlock);
poolIdToAccRewardPerShareVesting[_pid] = poolIdToAccRewardPerShareVesting[_pid].add(reward.mul(1e18).div(poolIdToTotalFundedPercentageOfTargetRaise[_pid]));
poolIdToLastRewardBlock[_pid] = maxEndBlock;
}
function getAccPercentagePerShareAndLastAllocBlock(uint256 _pid) internal view returns (uint256 accPercentPerShare, uint256 lastAllocBlock) {
PoolInfo memory poolInfo = poolInfo[_pid];
uint256 tokenAllocationPeriodInBlocks = poolInfo.stakingEndBlock.sub(poolInfo.tokenAllocationStartBlock);
uint256 allocationAvailablePerBlock = TOTAL_TOKEN_ALLOCATION_POINTS.div(tokenAllocationPeriodInBlocks);
uint256 maxEndBlockForPercentAlloc = block.number <= poolInfo.stakingEndBlock ? block.number : poolInfo.stakingEndBlock;
uint256 multiplier = getMultiplier(poolIdToLastPercentageAllocBlock[_pid], maxEndBlockForPercentAlloc);
uint256 totalPercentageUnlocked = multiplier.mul(allocationAvailablePerBlock);
return (
poolIdToAccPercentagePerShare[_pid].add(totalPercentageUnlocked.mul(1e18).div(poolIdToTotalStaked[_pid])),
maxEndBlockForPercentAlloc
);
}
function claimReward(uint256 _pid) public nonReentrant {
updatePool(_pid);
require(block.number >= poolIdToRewardCliffEndBlock[_pid], "claimReward: Not past cliff");
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.pledgeFundingAmount > 0, "claimReward: Nice try pal");
PoolInfo storage pool = poolInfo[_pid];
address rewardTokenAddress = address(pool.rewardToken);
require(rewardTokenAddress != address(0), "claimReward: rewardToken is zero address");
uint256 accRewardPerShare = poolIdToAccRewardPerShareVesting[_pid];
(uint256 accPercentPerShare,) = getAccPercentagePerShareAndLastAllocBlock(_pid);
uint256 userPercentageAllocated = user.amount.mul(accPercentPerShare).div(1e18).sub(user.tokenAllocDebt);
uint256 pending = userPercentageAllocated.mul(accRewardPerShare).div(1e18).sub(user.rewardDebtRewards);
if (pending > 0) {
user.rewardDebtRewards = userPercentageAllocated.mul(accRewardPerShare).div(1e18);
safeRewardTransfer(pool.rewardToken, msg.sender, pending);
emit RewardClaimed(msg.sender, _pid, pending);
}
}
function withdraw(uint256 _pid) external nonReentrant {
require(_pid < poolInfo.length, "withdraw: invalid _pid");
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
require(user.amount > 0, "withdraw: No stake to withdraw");
require(user.pledgeFundingAmount == 0, "withdraw: Only allow non-funders to withdraw");
require(block.number > pool.pledgeFundingEndBlock, "withdraw: Not yet permitted");
uint256 withdrawAmount = user.amount;
delete userInfo[_pid][msg.sender];
stakingToken.safeTransfer(msg.sender, withdrawAmount);
emit Withdraw(msg.sender, _pid, withdrawAmount);
}
function claimFundRaising(uint256 _pid) external nonReentrant onlyOwner {
require(_pid < poolInfo.length, "claimFundRaising: invalid _pid");
PoolInfo storage pool = poolInfo[_pid];
uint256 rewardPerBlock = poolIdToRewardPerBlock[_pid];
require(rewardPerBlock != 0, "claimFundRaising: rewards not yet sent");
require(poolIdToFundsClaimed[_pid] == false, "claimFundRaising: Already claimed funds");
poolIdToFundsClaimed[_pid] = true;
pool.fundRaisingToken.transfer(owner(), poolIdToTotalRaised[_pid]);
emit FundRaisingClaimed(_pid, owner(), poolIdToTotalRaised[_pid]);
}
function safeRewardTransfer(IERC20 _rewardToken, address _to, uint256 _amount) private {
uint256 bal = rewardGuildBank.tokenBalance(_rewardToken);
if (_amount > bal) {
rewardGuildBank.withdrawTo(_rewardToken, _to, bal);
} else {
rewardGuildBank.withdrawTo(_rewardToken, _to, _amount);
}
}
function getMultiplier(uint256 _from, uint256 _to) private view returns (uint256) {
return _to.sub(_from);
}
}
文件 6 的 9:Ownable.sol
pragma solidity >=0.6.0 <0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 7 的 9:ReentrancyGuard.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor () internal {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 8 的 9:SafeERC20.sol
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
library SafeERC20 {
using SafeMath for uint256;
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 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(IERC20 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(IERC20 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(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 9 的 9:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
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) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
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) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/LaunchPoolERC20FundRaisingWithDelayedVesting.sol": "LaunchPoolERC20FundRaisingWithDelayedVesting"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"_stakingToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"guildBank","type":"address"}],"name":"ContractDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundRaisingClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Pledge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PledgeFunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"}],"name":"PoolAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"address","name":"rewardToken","type":"address"}],"name":"PoolRewardTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"rewardEndBlock","type":"uint256"}],"name":"RewardsSetUp","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"TOTAL_TOKEN_ALLOCATION_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_rewardToken","type":"address"},{"internalType":"contract IERC20","name":"_fundRaisingToken","type":"address"},{"internalType":"uint256","name":"_tokenAllocationStartBlock","type":"uint256"},{"internalType":"uint256","name":"_stakingEndBlock","type":"uint256"},{"internalType":"uint256","name":"_pledgeFundingEndBlock","type":"uint256"},{"internalType":"uint256","name":"_targetRaise","type":"uint256"},{"internalType":"uint256","name":"_maxStakingAmountPerUser","type":"uint256"},{"internalType":"bool","name":"_withUpdate","type":"bool"}],"name":"add","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"claimFundRaising","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"fundPledge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getPledgeFundingAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getTotalRaisedVsTarget","outputs":[{"internalType":"uint256","name":"raised","type":"uint256"},{"internalType":"uint256","name":"target","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"numberOfPools","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"pledge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToAccPercentagePerShare","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToAccRewardPerShareVesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToFundsClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToLastPercentageAllocBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToLastRewardBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToMaxRewardTokensAvailableForVesting","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToRewardCliffEndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToRewardEndBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToRewardPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToRewardStartBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToTotalFundedPercentageOfTargetRaise","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToTotalRaised","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolIdToTotalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"rewardToken","type":"address"},{"internalType":"contract IERC20","name":"fundRaisingToken","type":"address"},{"internalType":"uint256","name":"tokenAllocationStartBlock","type":"uint256"},{"internalType":"uint256","name":"stakingEndBlock","type":"uint256"},{"internalType":"uint256","name":"pledgeFundingEndBlock","type":"uint256"},{"internalType":"uint256","name":"targetRaise","type":"uint256"},{"internalType":"uint256","name":"maxStakingAmountPerUser","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardGuildBank","outputs":[{"internalType":"contract FundRaisingGuild","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"contract IERC20","name":"_rewardToken","type":"address"}],"name":"setRewardTokenOnPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_rewardAmount","type":"uint256"},{"internalType":"uint256","name":"_rewardStartBlock","type":"uint256"},{"internalType":"uint256","name":"_rewardCliffEndBlock","type":"uint256"},{"internalType":"uint256","name":"_rewardEndBlock","type":"uint256"}],"name":"setupVestingRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"updatePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"pledgeFundingAmount","type":"uint256"},{"internalType":"uint256","name":"rewardDebtRewards","type":"uint256"},{"internalType":"uint256","name":"tokenAllocDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]