pragmasolidity ^0.5.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.
*/contractContext{
// Empty internal constructor, to prevent people from mistakenly deploying// an instance of this contract, which should be used via inheritance.constructor () internal{ }
// solhint-disable-previous-line no-empty-blocksfunction_msgSender() internalviewreturns (addresspayable) {
returnmsg.sender;
}
function_msgData() internalviewreturns (bytesmemory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691returnmsg.data;
}
}
pragmasolidity >=0.5.0;pragmaexperimentalABIEncoderV2;interfaceIVeloV2Router{
structRoute {
addressfrom;
address to;
bool stable;
address factory;
}
functionweth() externalviewreturns (address);
/// @notice Add liquidity of two tokens to a Pool/// @param tokenA ./// @param tokenB ./// @param stable True if pool is stable, false if volatile/// @param amountADesired Amount of tokenA desired to deposit/// @param amountBDesired Amount of tokenB desired to deposit/// @param amountAMin Minimum amount of tokenA to deposit/// @param amountBMin Minimum amount of tokenB to deposit/// @param to Recipient of liquidity token/// @param deadline Deadline to receive liquidity/// @return amountA Amount of tokenA to actually deposit/// @return amountB Amount of tokenB to actually deposit/// @return liquidity Amount of liquidity token returned from depositfunctionaddLiquidity(address tokenA,
address tokenB,
bool stable,
uint256 amountADesired,
uint256 amountBDesired,
uint256 amountAMin,
uint256 amountBMin,
address to,
uint256 deadline
) externalreturns (uint256 amountA, uint256 amountB, uint256 liquidity);
/// @notice Swap one token for another/// @param amountIn Amount of token in/// @param amountOutMin Minimum amount of desired token received/// @param routes Array of trade routes used in the swap/// @param to Recipient of the tokens received/// @param deadline Deadline to receive tokens/// @return amounts Array of amounts returned per routefunctionswapExactTokensForTokens(uint256 amountIn,
uint256 amountOutMin,
Route[] calldata routes,
address to,
uint256 deadline
) externalreturns (uint256[] memory amounts);
}
pragmasolidity =0.5.16;// a library for performing various math operations// forked from: https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/libraries/Math.sollibraryMath{
functionmin(uint256 x, uint256 y) internalpurereturns (uint256 z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)functionsqrt(uint256 y) internalpurereturns (uint256 z) {
if (y >3) {
z = y;
uint256 x = y /2+1;
while (x < z) {
z = x;
x = (y / x + x) /2;
}
} elseif (y !=0) {
z =1;
}
}
}
Contract Source Code
File 15 of 19: Ownable.sol
pragmasolidity ^0.5.0;import"../GSN/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.
*
* 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.
*/contractOwnableisContext{
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() publicviewreturns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
require(isOwner(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Returns true if the caller is the current owner.
*/functionisOwner() publicviewreturns (bool) {
return _msgSender() == _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() publiconlyOwner{
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) publiconlyOwner{
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
*/function_transferOwnership(address newOwner) internal{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
Contract Source Code
File 16 of 19: PoolToken.sol
pragmasolidity =0.5.16;import"./TarotERC20.sol";
import"./interfaces/IERC20.sol";
import"./interfaces/IPoolToken.sol";
import"./libraries/SafeMath.sol";
contractPoolTokenisIPoolToken, TarotERC20{
uint256internalconstant initialExchangeRate =1e18;
addresspublic underlying;
addresspublic factory;
uint256public totalBalance;
uint256publicconstant MINIMUM_LIQUIDITY =1000;
eventMint(addressindexed sender,
addressindexed minter,
uint256 mintAmount,
uint256 mintTokens
);
eventRedeem(addressindexed sender,
addressindexed redeemer,
uint256 redeemAmount,
uint256 redeemTokens
);
eventSync(uint256 totalBalance);
/*** Initialize ***/// called once by the factoryfunction_setFactory() external{
require(factory ==address(0), "Tarot: FACTORY_ALREADY_SET");
factory =msg.sender;
}
/*** PoolToken ***/function_update() internal{
totalBalance = IERC20(underlying).balanceOf(address(this));
emit Sync(totalBalance);
}
functionexchangeRate() publicviewreturns (uint256) {
uint256 _totalSupply = totalSupply; // gas savingsuint256 _totalBalance = totalBalance; // gas savingsif (_totalSupply ==0|| _totalBalance ==0) return initialExchangeRate;
return _totalBalance.mul(1e18).div(_totalSupply);
}
// this low-level function should be called from another contractfunctionmint(address minter)
externalnonReentrantupdatereturns (uint256 mintTokens)
{
uint256 balance = IERC20(underlying).balanceOf(address(this));
uint256 mintAmount = balance.sub(totalBalance);
mintTokens = mintAmount.mul(1e18).div(exchangeRate());
if (totalSupply ==0) {
// permanently lock the first MINIMUM_LIQUIDITY tokens
mintTokens = mintTokens.sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY);
}
require(mintTokens >0, "Tarot: MINT_AMOUNT_ZERO");
_mint(minter, mintTokens);
emit Mint(msg.sender, minter, mintAmount, mintTokens);
}
// this low-level function should be called from another contractfunctionredeem(address redeemer)
externalnonReentrantupdatereturns (uint256 redeemAmount)
{
uint256 redeemTokens = balanceOf[address(this)];
redeemAmount = redeemTokens.mul(exchangeRate()).div(1e18);
require(redeemAmount >0, "Tarot: REDEEM_AMOUNT_ZERO");
require(redeemAmount <= totalBalance, "Tarot: INSUFFICIENT_CASH");
_burn(address(this), redeemTokens);
_safeTransfer(redeemer, redeemAmount);
emit Redeem(msg.sender, redeemer, redeemAmount, redeemTokens);
}
// force real balance to match totalBalancefunctionskim(address to) externalnonReentrant{
_safeTransfer(
to,
IERC20(underlying).balanceOf(address(this)).sub(totalBalance)
);
}
// force totalBalance to match real balancefunctionsync() externalnonReentrantupdate{}
/*** Utilities ***/// same safe transfer function used by UniSwapV2 (with fixed underlying)bytes4privateconstant SELECTOR =bytes4(keccak256(bytes("transfer(address,uint256)")));
function_safeTransfer(address to, uint256 amount) internal{
(bool success, bytesmemory data) = underlying.call(
abi.encodeWithSelector(SELECTOR, to, amount)
);
require(
success && (data.length==0||abi.decode(data, (bool))),
"Tarot: TRANSFER_FAILED"
);
}
// prevents a contract from calling itself, directly or indirectly.boolinternal _notEntered =true;
modifiernonReentrant() {
require(_notEntered, "Tarot: REENTERED");
_notEntered =false;
_;
_notEntered =true;
}
// update totalBalance with current balancemodifierupdate() {
_;
_update();
}
}
Contract Source Code
File 17 of 19: SafeMath.sol
pragmasolidity =0.5.16;// From https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/Math.sol// Subject to the MIT license./**
* @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, 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 addition of two unsigned integers, reverting with custom message on overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
* - Addition cannot overflow.
*/functionadd(uint256 a,
uint256 b,
stringmemory errorMessage
) internalpurereturns (uint256) {
uint256 c = a + b;
require(c >= a, errorMessage);
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on underflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot underflow.
*/functionsub(uint256 a, uint256 b) internalpurereturns (uint256) {
return sub(a, b, "SafeMath: subtraction underflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on underflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot underflow.
*/functionsub(uint256 a,
uint256 b,
stringmemory errorMessage
) internalpurereturns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
/**
* @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) {
// 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) {
return0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @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,
stringmemory errorMessage
) internalpurereturns (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) {
return0;
}
uint256 c = a * b;
require(c / a == b, errorMessage);
return c;
}
/**
* @dev Returns the integer division of two unsigned integers.
* Reverts 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) {
return div(a, b, "SafeMath: division by zero");
}
/**
* @dev Returns the integer division of two unsigned integers.
* Reverts with custom message 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,
stringmemory errorMessage
) internalpurereturns (uint256) {
// Solidity only automatically asserts when dividing by 0require(b >0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't holdreturn c;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts 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) {
return mod(a, b, "SafeMath: modulo by zero");
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* Reverts with custom message 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,
stringmemory errorMessage
) internalpurereturns (uint256) {
require(b !=0, errorMessage);
return a % b;
}
}