// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (addresspayable) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytesmemory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691returnmsg.data;
}
}
Contract Source Code
File 2 of 9: FixedSwap.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.7.6;import"./IERC20Detailed.sol";
import"@openzeppelin/contracts/token/ERC20/IERC20.sol";
import"@openzeppelin/contracts/utils/Pausable.sol";
import"@openzeppelin/contracts/math/SafeMath.sol";
import"./Whitelist.sol";
import"./libraries/TransferHelper.sol";
contractFixedSwapisPausable, Whitelist{
usingSafeMathforuint256;
uint256 increment =0;
mapping(uint256=> Purchase) public purchases; /* Purchasers mapping */address[] public buyers; /* Current Buyers Addresses */uint256[] public purchaseIds; /* All purchaseIds */mapping(address=>uint256[]) public myPurchases; /* Purchasers mapping */
IERC20 public erc20;
boolpublic isSaleFunded =false;
uintpublic decimals =0;
boolpublic unsoldTokensRedeemed =false;
uint256public tradeValue; /* Price in Wei */uint256public startDate; /* Start Date */uint256public endDate; /* End Date */uint256public individualMinimumAmount =0; /* Minimum Amount Per Address */uint256public individualMaximumAmount =0; /* Maximum Amount Per Address */uint256public minimumRaise =0; /* Minimum Amount of Tokens that have to be sold */uint256public tokensAllocated =0; /* Tokens Available for Allocation - Dynamic */uint256public tokensForSale =0; /* Tokens Available for Sale */boolpublic isTokenSwapAtomic; /* Make token release atomic or not */addresspayablepublic feeAddress; /* Default Address for Fee Percentage */uint256public feePercentage =1; /* Default Fee 1% */boolprivate locked;
structPurchase {
uint256 amount;
address purchaser;
uint256 ethAmount;
uint256 timestamp;
bool wasFinalized; /* Confirm the tokens were sent already */bool reverted; /* Confirm the tokens were sent already */
}
eventPurchaseEvent(uint256indexed purchaseId,
uint256 amount,
addressindexed purchaser,
uint256 ethAmount,
uint256 timestamp,
bool wasFinalized
);
eventFundEvent(addressindexed funder, uint256 amount, addressindexed contractAddress, uint256 timestamp);
eventRedeemTokenEvent(uint256indexed purchaseId,
uint256 amount,
addressindexed purchaser,
uint256 ethAmount,
bool wasFinalized,
bool reverted
);
constructor(address _tokenAddress,
addresspayable _feeAddress,
uint256 _tradeValue,
uint256 _tokensForSale,
uint256 _startDate,
uint256 _endDate,
uint256 _individualMinimumAmount,
uint256 _individualMaximumAmount,
bool _isTokenSwapAtomic,
uint256 _minimumRaise,
uint256 _feeAmount,
bool _hasWhitelisting
) Whitelist(_hasWhitelisting) {
/* Confirmations */require(block.timestamp< _endDate, "End Date should be further than current date");
require(block.timestamp< _startDate, "Start Date should be further than current date");
require(_startDate < _endDate, "End Date higher than Start Date");
require(_tokensForSale >0, "Tokens for Sale should be > 0");
require(_tokensForSale > _individualMinimumAmount, "Tokens for Sale should be > Individual Minimum Amount");
require(_individualMaximumAmount >= _individualMinimumAmount, "Individual Maximum Amount should be > Individual Minimum Amount");
require(_minimumRaise <= _tokensForSale, "Minimum Raise should be < Tokens For Sale");
require(_feeAmount >= feePercentage, "Fee Percentage has to be >= 1");
require(_feeAmount <=99, "Fee Percentage has to be < 100");
require(_feeAddress !=address(0), "Fee Address has to be not ZERO");
require(_tokenAddress !=address(0), "Token Address has to be not ZERO");
startDate = _startDate;
endDate = _endDate;
tokensForSale = _tokensForSale;
tradeValue = _tradeValue;
individualMinimumAmount = _individualMinimumAmount;
individualMaximumAmount = _individualMaximumAmount;
isTokenSwapAtomic = _isTokenSwapAtomic;
if (!_isTokenSwapAtomic) {
/* If raise is not atomic swap */
minimumRaise = _minimumRaise;
}
erc20 = IERC20(_tokenAddress);
decimals = IERC20Detailed(_tokenAddress).decimals();
feePercentage = _feeAmount;
feeAddress = _feeAddress;
}
/**
* Modifier to make a function callable only when the contract has Atomic Swaps not available.
*/modifierisNotAtomicSwap() {
require(!isTokenSwapAtomic, "Has to be non Atomic swap");
_;
}
/**
* Modifier to make a function callable only when the contract has Atomic Swaps not available.
*/modifierisSaleFinalized() {
require(hasFinalized(), "Has to be finalized");
_;
}
/**
* Modifier to make a function callable only when the swap time is open.
*/modifierisSaleOpen() {
require(isOpen(), "Has to be open");
_;
}
/**
* Modifier to make a function callable only when the contract has Atomic Swaps not available.
*/modifierisSalePreStarted() {
require(isPreStart(), "Has to be pre-started");
_;
}
/**
* Modifier to make a function callable only when the contract has Atomic Swaps not available.
*/modifierisFunded() {
require(isSaleFunded, "Has to be funded");
_;
}
/**
* Modifier for block reentrancy
*/modifierblockReentrancy{
require(!locked, "Reentrancy is blocked");
locked =true;
_;
locked =false;
}
/* Get Functions */functionisBuyer(uint256 purchase_id) publicviewreturns (bool) {
return (msg.sender== purchases[purchase_id].purchaser);
}
/* Get Functions */functiontotalRaiseCost() publicviewreturns (uint256) {
return (cost(tokensForSale));
}
functionavailableTokens() publicviewreturns (uint256) {
return erc20.balanceOf(address(this));
}
functiontokensLeft() publicviewreturns (uint256) {
return tokensForSale - tokensAllocated;
}
functionhasMinimumRaise() publicviewreturns (bool) {
return (minimumRaise !=0);
}
/* Verify if minimum raise was not achieved */functionminimumRaiseNotAchieved() publicviewreturns (bool) {
require(cost(tokensAllocated) < cost(minimumRaise), "TotalRaise is bigger than minimum raise amount");
returntrue;
}
/* Verify if minimum raise was achieved */functionminimumRaiseAchieved() publicviewreturns (bool) {
if (hasMinimumRaise()) {
require(cost(tokensAllocated) >= cost(minimumRaise), "TotalRaise is less than minimum raise amount");
}
returntrue;
}
functionhasFinalized() publicviewreturns (bool) {
returnblock.timestamp> endDate;
}
functionhasStarted() publicviewreturns (bool) {
returnblock.timestamp>= startDate;
}
functionisPreStart() publicviewreturns (bool) {
returnblock.timestamp< startDate;
}
functionisOpen() publicviewreturns (bool) {
return hasStarted() &&!hasFinalized();
}
functionhasMinimumAmount() publicviewreturns (bool) {
return (individualMinimumAmount !=0);
}
functioncost(uint256 _amount) publicviewreturns (uint256) {
return _amount.mul(tradeValue).div(10**decimals);
}
functiongetPurchase(uint256 _purchase_id)
externalviewreturns (uint256,
address,
uint256,
uint256,
bool,
bool)
{
Purchase memory purchase = purchases[_purchase_id];
return (purchase.amount, purchase.purchaser, purchase.ethAmount, purchase.timestamp, purchase.wasFinalized, purchase.reverted);
}
functiongetPurchaseIds() publicviewreturns (uint256[] memory) {
return purchaseIds;
}
functiongetBuyers() publicviewreturns (address[] memory) {
return buyers;
}
functiongetMyPurchases(address _address) publicviewreturns (uint256[] memory) {
return myPurchases[_address];
}
/* Fund - Pre Sale Start */functionfund(uint256 _amount) publicisSalePreStarted{
/* Confirm transferred tokens is no more than needed */require(availableTokens().add(_amount) <= tokensForSale, "Transferred tokens have to be equal or less than proposed");
/* Transfer Funds */
TransferHelper.safeTransferFrom(address(erc20), msg.sender, address(this), _amount);
/* If Amount is equal to needed - sale is ready */if (availableTokens() == tokensForSale) {
isSaleFunded =true;
}
emit FundEvent(msg.sender, _amount, address(this), block.timestamp);
}
/* Action Functions */functionswap(uint256 _amount) externalpayablewhenNotPausedisFundedisSaleOpenonlyWhitelistedblockReentrancy{
/* Confirm Amount is positive */require(_amount >0, "Amount has to be positive");
/* Confirm Amount is less than tokens available */require(_amount <= tokensLeft(), "Amount is less than tokens available");
/* Confirm the user has funds for the transfer, confirm the value is equal */require(msg.value== cost(_amount), "User swap amount has to equal to cost of token in ETH");
/* Confirm Amount is bigger than minimum Amount */require(_amount >= individualMinimumAmount, "Amount is bigger than minimum amount");
/* Confirm Amount is smaller than maximum Amount */require(_amount <= individualMaximumAmount, "Amount is smaller than maximum amount");
/* Verify all user purchases, loop thru them */uint256[] memory _purchases = getMyPurchases(msg.sender);
uint256 purchaserTotalAmountPurchased =0;
for (uint i =0; i < _purchases.length; i++) {
Purchase memory _purchase = purchases[_purchases[i]];
purchaserTotalAmountPurchased = purchaserTotalAmountPurchased.add(_purchase.amount);
}
require(purchaserTotalAmountPurchased.add(_amount) <= individualMaximumAmount, "Address has already passed the max amount of swap");
if (isTokenSwapAtomic) {
/* Confirm transfer */
TransferHelper.safeTransfer(address(erc20), msg.sender, _amount);
}
uint256 purchase_id = increment;
increment = increment.add(1);
/* Create new purchase */
Purchase memory purchase =
Purchase(
_amount,
msg.sender,
msg.value,
block.timestamp,
isTokenSwapAtomic, /* If Atomic Swap */false
);
purchases[purchase_id] = purchase;
purchaseIds.push(purchase_id);
myPurchases[msg.sender].push(purchase_id);
buyers.push(msg.sender);
tokensAllocated = tokensAllocated.add(_amount);
emit PurchaseEvent(purchase_id, _amount, msg.sender, msg.value, block.timestamp, isTokenSwapAtomic);
}
/* Redeem tokens when the sale was finalized */functionredeemTokens(uint256 purchase_id) externalisNotAtomicSwapisSaleFinalizedwhenNotPausedblockReentrancy{
/* Confirm it exists and was not finalized */require((purchases[purchase_id].amount !=0) &&!purchases[purchase_id].wasFinalized, "Purchase is either 0 or finalized");
require(isBuyer(purchase_id), "Address is not buyer");
purchases[purchase_id].wasFinalized =true;
TransferHelper.safeTransfer(address(erc20), msg.sender, purchases[purchase_id].amount);
emit RedeemTokenEvent(purchase_id, purchases[purchase_id].amount, msg.sender, 0, purchases[purchase_id].wasFinalized, false);
}
/* Retrieve Minimum Amount */functionredeemGivenMinimumGoalNotAchieved(uint256 purchase_id) externalisSaleFinalizedisNotAtomicSwapwhenNotPausedblockReentrancy{
require(hasMinimumRaise(), "Minimum raise has to exist");
require(minimumRaiseNotAchieved(), "Minimum raise has to be reached");
/* Confirm it exists and was not finalized */require((purchases[purchase_id].amount !=0) &&!purchases[purchase_id].wasFinalized, "Purchase is either 0 or finalized");
require(isBuyer(purchase_id), "Address is not buyer");
purchases[purchase_id].wasFinalized =true;
purchases[purchase_id].reverted =true;
msg.sender.transfer(purchases[purchase_id].ethAmount);
emit RedeemTokenEvent(
purchase_id,
0,
msg.sender,
purchases[purchase_id].ethAmount,
purchases[purchase_id].wasFinalized,
purchases[purchase_id].reverted
);
}
/* Admin Functions */functionwithdrawFunds() externalonlyOwnerwhenNotPausedisSaleFinalized{
require(minimumRaiseAchieved(), "Minimum raise has to be reached");
uint256 fee =address(this).balance.mul(feePercentage).div(100);
feeAddress.transfer(fee); /* Fee Address */uint256 funds =address(this).balance;
msg.sender.transfer(funds);
}
functionwithdrawUnsoldTokens() externalonlyOwnerisSaleFinalized{
require(!unsoldTokensRedeemed);
uint256 unsoldTokens;
if (hasMinimumRaise() && (cost(tokensAllocated) < cost(minimumRaise))) {
/* Minimum Raise not reached */
unsoldTokens = tokensForSale;
} else {
/* If minimum Raise Achieved Redeem All Tokens minus the ones */
unsoldTokens = tokensForSale.sub(tokensAllocated);
}
if (unsoldTokens >0) {
unsoldTokensRedeemed =true;
TransferHelper.safeTransfer(address(erc20), msg.sender, unsoldTokens);
}
}
functionremoveOtherERC20Tokens(address _tokenAddress, address _to) externalonlyOwnerisSaleFinalized{
require(_tokenAddress !=address(erc20), "Token Address has to be diff than the erc20 subject to sale"); // Confirm tokens addresses are different from main sale one
IERC20Detailed erc20Token = IERC20Detailed(_tokenAddress);
TransferHelper.safeTransfer(address(erc20Token), _to, erc20Token.balanceOf(address(this)));
}
functionpause() externalonlyOwner{
_pause();
}
/* Safe Pull function */functionsafePull() externalpayableonlyOwnerwhenPaused{
msg.sender.transfer(address(this).balance);
TransferHelper.safeTransfer(address(erc20), msg.sender, erc20.balanceOf(address(this)));
}
}
Contract Source Code
File 3 of 9: IERC20.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/interfaceIERC20{
/**
* @dev Returns the amount of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 amount) externalreturns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(address sender, address recipient, uint256 amount) externalreturns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;import"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor () internal{
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
emit OwnershipTransferred(_owner, address(0));
_owner =address(0);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
Contract Source Code
File 6 of 9: Pausable.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;import"./Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/abstractcontractPausableisContext{
/**
* @dev Emitted when the pause is triggered by `account`.
*/eventPaused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/eventUnpaused(address account);
boolprivate _paused;
/**
* @dev Initializes the contract in unpaused state.
*/constructor () internal{
_paused =false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/functionpaused() publicviewvirtualreturns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/modifierwhenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/modifierwhenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/function_pause() internalvirtualwhenNotPaused{
_paused =true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/function_unpause() internalvirtualwhenPaused{
_paused =false;
emit Unpaused(_msgSender());
}
}
Contract Source Code
File 7 of 9: SafeMath.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.0 <0.8.0;/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/librarySafeMath{
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/functiontryAdd(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/functiontrySub(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/functiontryMul(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the// benefit is lost if 'b' is also tested.// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522if (a ==0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/functiontryDiv(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
if (b ==0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/functiontryMod(uint256 a, uint256 b) internalpurereturns (bool, uint256) {
if (b ==0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/functionadd(uint256 a, uint256 b) internalpurereturns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/functionsub(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/functionmul(uint256 a, uint256 b) internalpurereturns (uint256) {
if (a ==0) return0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functiondiv(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b >0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functionmod(uint256 a, uint256 b) internalpurereturns (uint256) {
require(b >0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/functionsub(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functiondiv(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b >0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/functionmod(uint256 a, uint256 b, stringmemory errorMessage) internalpurereturns (uint256) {
require(b >0, errorMessage);
return a % b;
}
}
Contract Source Code
File 8 of 9: TransferHelper.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.7.6;// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/falselibraryTransferHelper{
functionsafeApprove(address token, address to, uint value) internal{
// bytes4(keccak256(bytes('approve(address,uint256)')));
(bool success, bytesmemory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
require(success && (data.length==0||abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
}
functionsafeTransfer(address token, address to, uint value) internal{
// bytes4(keccak256(bytes('transfer(address,uint256)')));
(bool success, bytesmemory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
require(success && (data.length==0||abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
}
functionsafeTransferFrom(address token, addressfrom, address to, uint value) internal{
// bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
(bool success, bytesmemory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
require(success && (data.length==0||abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
}
functionsafeTransferETH(address to, uint value) internal{
(bool success,) = to.call{value:value}(newbytes(0));
require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
}
}