pragmasolidity ^0.6.6;libraryACOAssetHelper{
uint256internalconstant MAX_UINT =0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
/**
* @dev Internal function to get if the address is for Ethereum (0x0).
* @param _address Address to be checked.
* @return Whether the address is for Ethereum.
*/function_isEther(address _address) internalpurereturns(bool) {
return _address ==address(0);
}
/**
* @dev Internal function to approve ERC20 tokens.
* @param token Address of the token.
* @param spender Authorized address.
* @param amount Amount to authorize.
*/function_callApproveERC20(address token, address spender, uint256 amount) internal{
(bool success, bytesmemory returndata) = token.call(abi.encodeWithSelector(0x095ea7b3, spender, amount));
require(success && (returndata.length==0||abi.decode(returndata, (bool))), "approve");
}
/**
* @dev Internal function to transfer ERC20 tokens.
* @param token Address of the token.
* @param recipient Address of the transfer destination.
* @param amount Amount to transfer.
*/function_callTransferERC20(address token, address recipient, uint256 amount) internal{
(bool success, bytesmemory returndata) = token.call(abi.encodeWithSelector(0xa9059cbb, recipient, amount));
require(success && (returndata.length==0||abi.decode(returndata, (bool))), "transfer");
}
/**
* @dev Internal function to call transferFrom on ERC20 tokens.
* @param token Address of the token.
* @param sender Address of the sender.
* @param recipient Address of the transfer destination.
* @param amount Amount to transfer.
*/function_callTransferFromERC20(address token, address sender, address recipient, uint256 amount) internal{
(bool success, bytesmemory returndata) = token.call(abi.encodeWithSelector(0x23b872dd, sender, recipient, amount));
require(success && (returndata.length==0||abi.decode(returndata, (bool))), "transferFrom");
}
/**
* @dev Internal function to the asset symbol.
* @param asset Address of the asset.
* @return The asset symbol.
*/function_getAssetSymbol(address asset) internalviewreturns(stringmemory) {
if (_isEther(asset)) {
return"ETH";
} else {
(bool success, bytesmemory returndata) = asset.staticcall(abi.encodeWithSelector(0x95d89b41));
require(success, "symbol");
returnabi.decode(returndata, (string));
}
}
/**
* @dev Internal function to the asset decimals.
* @param asset Address of the asset.
* @return The asset decimals.
*/function_getAssetDecimals(address asset) internalviewreturns(uint8) {
if (_isEther(asset)) {
returnuint8(18);
} else {
(bool success, bytesmemory returndata) = asset.staticcall(abi.encodeWithSelector(0x313ce567));
require(success, "decimals");
returnabi.decode(returndata, (uint8));
}
}
/**
* @dev Internal function to the asset name.
* @param asset Address of the asset.
* @return The asset name.
*/function_getAssetName(address asset) internalviewreturns(stringmemory) {
if (_isEther(asset)) {
return"Ethereum";
} else {
(bool success, bytesmemory returndata) = asset.staticcall(abi.encodeWithSelector(0x06fdde03));
require(success, "name");
returnabi.decode(returndata, (string));
}
}
/**
* @dev Internal function to the asset balance of an account.
* @param asset Address of the asset.
* @param account Address of the account.
* @return The account balance.
*/function_getAssetBalanceOf(address asset, address account) internalviewreturns(uint256) {
if (_isEther(asset)) {
return account.balance;
} else {
(bool success, bytesmemory returndata) = asset.staticcall(abi.encodeWithSelector(0x70a08231, account));
require(success, "balanceOf");
returnabi.decode(returndata, (uint256));
}
}
/**
* @dev Internal function to the asset allowance between two addresses.
* @param asset Address of the asset.
* @param owner Address of the owner of the tokens.
* @param spender Address of the spender authorized.
* @return The owner allowance for the spender.
*/function_getAssetAllowance(address asset, address owner, address spender) internalviewreturns(uint256) {
if (_isEther(asset)) {
return0;
} else {
(bool success, bytesmemory returndata) = asset.staticcall(abi.encodeWithSelector(0xdd62ed3e, owner, spender));
require(success, "allowance");
returnabi.decode(returndata, (uint256));
}
}
/**
* @dev Internal function to transfer an asset.
* @param asset Address of the asset to be transferred.
* @param to Address of the destination.
* @param amount The amount to be transferred.
*/function_transferAsset(address asset, address to, uint256 amount) internal{
if (_isEther(asset)) {
(bool success,) = to.call{value:amount}(newbytes(0));
require(success, "send");
} else {
_callTransferERC20(asset, to, amount);
}
}
/**
* @dev Internal function to receive an asset.
* @param asset Address of the asset to be received.
* @param amount The amount to be received.
*/function_receiveAsset(address asset, uint256 amount) internal{
if (_isEther(asset)) {
require(msg.value== amount, "Invalid ETH amount");
} else {
require(msg.value==0, "No payable");
_callTransferFromERC20(asset, msg.sender, address(this), amount);
}
}
/**
* @dev Internal function to check asset allowance and set to Infinity if necessary.
* @param asset Address of the asset.
* @param owner Address of the owner of the tokens.
* @param spender Address of the spender authorized.
* @param amount Amount to check allowance.
*/function_setAssetInfinityApprove(address asset, address owner, address spender, uint256 amount) internal{
if (_getAssetAllowance(asset, owner, spender) < amount) {
_callApproveERC20(asset, spender, MAX_UINT);
}
}
}
Contract Source Code
File 2 of 6: ACORewards.sol
pragmasolidity ^0.6.6;import'./Ownable.sol';
import'./SafeMath.sol';
import'./ACOAssetHelper.sol';
import'./IACOToken.sol';
contractACORewardsisOwnable{
usingSafeMathforuint256;
eventDeposit(addressindexed user, uint256indexed pid, uint256 amount);
eventWithdraw(addressindexed user, uint256indexed pid, uint256 amount);
eventEmergencyWithdraw(addressindexed user, uint256indexed pid, uint256 amount);
eventRewardPaid(addressindexed user, uint256indexed pid, addressindexed aco, uint256 reward);
eventSetLPTokenAllocPoint(uint256indexed pid, addressindexed lpToken, uint256 allocPoint);
eventSetCurrentReward(addressindexed aco, uint256 rewardRate);
eventWithdrawStuckToken(addressindexed token, addressindexed destination, uint256 amount);
structCurrentRewardData {
address aco; // Address of the ACO to be distributed.uint256 rewardRate; // ACOs te be reward per second.
}
structPoolInfo {
address lpToken; // Address of LP token contract.uint256 allocPoint; // How many allocation points assigned to this LP token.
}
structACORewardData {
uint256 lastUpdateTime; // Last timestamp that ACO distribution was updated.uint256 accRewardPerShare; // Accumulated ACO per share, times 1e18.
}
structUserACORewardData {
uint256 pendingRewardStored; // Pending reward stored.uint256 accAcoRewardPerShareStored; // Last accumulated ACO per share, times 1e18, since last user interaction with the SC.
}
// Total allocation poitns. Must be the sum of all allocation points in all pools.uint256public totalAllocPoint;
// The current reward data. See CurrentRewardData struct.
CurrentRewardData public currentReward;
// Info of each pool.
PoolInfo[] public poolInfo;
// Array with all ACOs used to reward and that it is still not expired.address[] public acos;
// LP token index => ACO => ACO reward data. See ACORewardData struct.mapping(uint256=>mapping(address=> ACORewardData)) public acosRewardDataPerLP;
// LP token index => User => How many LP tokens the user has provided.mapping(uint256=>mapping(address=>uint256)) public balanceOf;
// LP token index => User => ACO => User reward data. See UserACORewardData struct.mapping(uint256=>mapping(address=>mapping(address=> UserACORewardData))) public usersAcoRewardData;
constructor() public{
super.init();
}
////////////////////// VIEW FUNCTIONS //////////////////////functionpoolLength() externalviewreturns(uint256) {
return poolInfo.length;
}
functionacosLength() externalviewreturns(uint256) {
return acos.length;
}
// External function to be used on the front-end to list the pending ACOs rewards for an account and a LP token. functionpendingReward(uint256 _pid, address account) externalviewreturns (address[] memory _acos, uint256[] memory _amounts) {
PoolInfo storage info = poolInfo[_pid];
uint256 share = balanceOf[_pid][account];
uint256 totalLPSupply = ACOAssetHelper._getAssetBalanceOf(info.lpToken, address(this));
uint256 qty =0;
for (uint256 i =0; i < acos.length; ++i) {
uint256 pending = _getPendingReward(
_pid,
info.allocPoint,
totalLPSupply,
account,
share,
acos[i]);
if (pending >0) {
++qty;
}
}
_acos =newaddress[](qty);
_amounts =newuint256[](qty);
if (qty >0) {
uint256 index =0;
for (uint256 i =0; i < acos.length; ++i) {
uint256 pending = _getPendingReward(
_pid,
info.allocPoint,
totalLPSupply,
account,
share,
acos[i]);
if (pending >0) {
_acos[index] = acos[i];
_amounts[index] = pending;
++index;
}
}
}
}
////////////////////// USERS FUNCTIONS //////////////////////functiondeposit(uint256 _pid, uint256 amount) external{
CurrentRewardData storage _currentReward = currentReward;
PoolInfo storage info = poolInfo[_pid];
require(info.allocPoint >0&& _currentReward.rewardRate >0, "LP token is forbidden");
require(amount >0, "Invalid amount");
_setCurrentAcoRewardAccPerShare(_pid, _currentReward);
_getUserAcoReward(_pid, true); // Claim available rewards.
ACOAssetHelper._callTransferFromERC20(info.lpToken, msg.sender, address(this), amount);
balanceOf[_pid][msg.sender] = amount.add(balanceOf[_pid][msg.sender]);
emit Deposit(msg.sender, _pid, amount);
}
functionwithdraw(uint256 _pid, uint256 amount) external{
uint256 totalUserBalance = balanceOf[_pid][msg.sender];
require(amount >0&& totalUserBalance >= amount, "Invalid amount");
_setCurrentAcoRewardAccPerShare(_pid, currentReward);
_getUserAcoReward(_pid, true); // Claim available rewards.
balanceOf[_pid][msg.sender] = totalUserBalance.sub(amount);
ACOAssetHelper._callTransferERC20(poolInfo[_pid].lpToken, msg.sender, amount);
emit Withdraw(msg.sender, _pid, amount);
}
functionclaimReward(uint256 _pid) public{
PoolInfo storage info = poolInfo[_pid];
require(info.lpToken !=address(0), "Invalid LP token");
_setCurrentAcoRewardAccPerShare(_pid, currentReward);
_getUserAcoReward(_pid, false);
}
functionclaimRewards(uint256[] calldata _pids) external{
for (uint256 i =0; i < _pids.length; ++i) {
claimReward(_pids[i]);
}
}
// Withdraw without caring about rewards. EMERGENCY ONLY!functionemergencyWithdraw(uint256 _pid) external{
uint256 totalUserBalance = balanceOf[_pid][msg.sender];
require(totalUserBalance >0, "No balance");
_setCurrentAcoRewardAccPerShare(_pid, currentReward);
balanceOf[_pid][msg.sender] =0;
ACOAssetHelper._callTransferERC20(poolInfo[_pid].lpToken, msg.sender, totalUserBalance);
emit EmergencyWithdraw(msg.sender, _pid, totalUserBalance);
}
////////////////////// INTERNAL FUNCTIONS ///////////////////////*
* Calculate the pending rewards and transfers them to the user.
* The math is basically, any point in time, the amount of ACOs entitled to a user but is pending to be distributed is:
*
* pending reward = user.share * (aco.accRewardPerShare - user.AccAcoRewardPerShareStored)
*
* Whenever a user deposit or withdraws for a LP token or even a reward claim:
* 1. The current ACOs accRewardPerShare and `lastUpdateTime get updated. `_setCurrentAcoRewardAccPerShare` function.
* 2. User receives the pending reward sent to his/her address.
* 3. userAccAcoRewardPerShareStored gets updated with the current ACO accRewardPerShare.
*/function_getUserAcoReward(uint256 _pid, bool ignoreIfNoBalance) internal{
uint256 share = balanceOf[_pid][msg.sender];
for (uint256 i = acos.length; i >0; --i) {
address aco = acos[i -1];
if (IACOToken(aco).expiryTime() <=block.timestamp) { // ACO is expired.
_removeAco(i -1);
} else {
uint256 acoAccRewardPerShare = acosRewardDataPerLP[_pid][aco].accRewardPerShare;
UserACORewardData storage userAcoRewardData = usersAcoRewardData[_pid][msg.sender][aco];
uint256 pending = _earned(share, acoAccRewardPerShare, userAcoRewardData.accAcoRewardPerShareStored);
pending = pending.add(userAcoRewardData.pendingRewardStored);
userAcoRewardData.pendingRewardStored = pending;
userAcoRewardData.accAcoRewardPerShareStored = acoAccRewardPerShare;
if (pending >0) {
// If for some reason the current ACO on the SC has not enough balance, the respective reward could be skipped to be paid later and this way avoids an error. (This is true on withdraw and deposit).if (ignoreIfNoBalance) {
uint256 acoBalance = ACOAssetHelper._getAssetBalanceOf(aco, address(this));
if (acoBalance < pending) {
continue;
}
}
userAcoRewardData.pendingRewardStored =0; // All ACO reward was paid.
ACOAssetHelper._callTransferERC20(aco, msg.sender, pending);
emit RewardPaid(msg.sender, _pid, aco, pending);
}
}
}
}
// Update the current ACO accRewardPerShare and lastUpdateTime for the active LP token.function_setCurrentAcoRewardAccPerShare(uint256 _pid, CurrentRewardData storage _currentReward) internal{
PoolInfo storage info = poolInfo[_pid];
if (info.allocPoint >0) {
uint256 totalLPSupply = ACOAssetHelper._getAssetBalanceOf(info.lpToken, address(this));
ACORewardData storage currentAcoData = acosRewardDataPerLP[_pid][_currentReward.aco];
currentAcoData.accRewardPerShare = _getAccRewardPerAco(totalLPSupply, info.allocPoint, _currentReward.aco, _currentReward.rewardRate, _currentReward.aco, currentAcoData);
currentAcoData.lastUpdateTime =block.timestamp;
}
}
/*
* Get the accumulated reward per share for an ACO.
* For the current ACO rewarding:
* previous accRewardPerShare + [rewardRate * (now - lastUpdateTime) * lpAllocPoint / totalAllocPoint] * 1e18 / totalSupply
* lpAllocPoint / totalAllocPoint is to get the weight for the respective LP token on the ACO reward.
* The value is multiplied by 1e18 for no losing precision. Hereafter it will be divided by 1e18.
*/function_getAccRewardPerAco(uint256 totalSupply,
uint256 allocPoint,
address currentAco,
uint256 currentAcoRewardRate,
address aco,
ACORewardData storage acoRewardData
) internalviewreturns (uint256) {
if (currentAco != aco || totalSupply ==0|| allocPoint ==0|| currentAcoRewardRate ==0) {
return acoRewardData.accRewardPerShare;
} else {
uint256 acoReward =block.timestamp.sub(acoRewardData.lastUpdateTime).mul(currentAcoRewardRate).mul(allocPoint).div(totalAllocPoint);
return acoReward.mul(1e18).div(totalSupply).add(acoRewardData.accRewardPerShare);
}
}
// user.share * (aco.accRewardPerShare - user.accAcoRewardPerShareStored) / 1e18 (the division per 1e18 is because all "per share" data is multiplied by 1e18)function_earned(uint256 accountShare,
uint256 acoAccRewardPerShare,
uint256 userAccAcoRewardPerShareStored
) internalpurereturns (uint256) {
return accountShare.mul(acoAccRewardPerShare.sub(userAccAcoRewardPerShareStored)).div(1e18);
}
/*
* To remove an expired ACO that expired condition already was checked.
* Useful to save gas on next txs.
*/function_removeAco(uint256 acoIndex) internal{
uint256 lastIndex = acos.length-1;
if (lastIndex != acoIndex) {
address last = acos[lastIndex];
acos[acoIndex] = last;
}
acos.pop();
}
// Used only on the pending reward external view function.function_getPendingReward(uint256 _pid,
uint256 allocPoint,
uint256 totalLPSupply,
address account,
uint256 accountShare,
address aco
) internalviewreturns(uint256 pending) {
pending =0;
if (IACOToken(aco).expiryTime() >block.timestamp) {
uint256 accRewardPerShare = _getAccRewardPerAco(
totalLPSupply,
allocPoint,
currentReward.aco,
currentReward.rewardRate,
aco,
acosRewardDataPerLP[_pid][aco]
);
UserACORewardData storage userAcoRewardData = usersAcoRewardData[_pid][account][aco];
pending = _earned(accountShare, accRewardPerShare, userAcoRewardData.accAcoRewardPerShareStored);
pending = pending.add(userAcoRewardData.pendingRewardStored);
}
}
////////////////////// PUBLIC FUNCTIONS //////////////////////// Update all accumulated per share value for the current ACO rewarding on all active LP tokens.functionsetAllLPTokensCurrentAcoRewardAccPerShare() internal{
CurrentRewardData storage _currentReward = currentReward;
for (uint256 i =0; i < poolInfo.length; ++i) {
_setCurrentAcoRewardAccPerShare(i, _currentReward);
}
}
// Remove expired ACOs from the array. To save gas on the next txs.functionsetValidAcos() public{
for (uint256 i = acos.length; i >0; --i) {
address aco = acos[i -1];
if (IACOToken(aco).expiryTime() <=block.timestamp) {
_removeAco(i -1);
}
}
}
////////////////////// ADMIN FUNCTIONS ///////////////////////*
* Function to the admin sets new LP tokens or change the allocation points.
* When an allocation point is set to zero the respective LP token is inactivated.
* If the LP token is inactived there is no reward and the respective deposit is also forbidden.
* However, withdrawals and previous rewards claims keep working.
*/functionsetLPTokens(address[] calldata lpTokens, uint256[] calldata allocPoints) externalonlyOwner{
require(lpTokens.length== allocPoints.length, "Invalid arguments");
setAllLPTokensCurrentAcoRewardAccPerShare();
setValidAcos();
address _currentAco = currentReward.aco;
for (uint256 i =0; i < lpTokens.length; ++i) {
require(allocPoints[i] <=1e18, "Invalid alloc point"); // To avoid overflow.bool isNew =true;
uint256 _pid;
for (uint256 j =0; j < poolInfo.length; ++j) {
PoolInfo storage info = poolInfo[j];
if (info.lpToken == lpTokens[i]) {
_pid = j;
totalAllocPoint = totalAllocPoint.sub(info.allocPoint).add(allocPoints[i]);
info.allocPoint = allocPoints[i];
isNew =false;
break;
}
}
if (isNew) { // It is new LP token.
_pid = poolInfo.length;
poolInfo.push(PoolInfo(lpTokens[i], allocPoints[i]));
totalAllocPoint = totalAllocPoint.add(allocPoints[i]);
}
// Sets the current ACO timestamp as "now" for the new LP token configuration.
acosRewardDataPerLP[_pid][_currentAco].lastUpdateTime =block.timestamp;
emit SetLPTokenAllocPoint(_pid, lpTokens[i], allocPoints[i]);
}
}
/*
* Function to the admin sets the ACO to the current reward.
* The rewardRate is ACO per second.
*/functionsetCurrentReward(address aco, uint256 rewardRate) externalonlyOwner{
require(rewardRate <=1e40, "The reward rate is too big"); // To avoid overflow.
setAllLPTokensCurrentAcoRewardAccPerShare();
setValidAcos();
bool isNew =true;
for (uint256 i =0; i < acos.length; ++i) {
if (acos[i] == aco) {
isNew =false;
break;
}
}
if (isNew) {
acos.push(aco);
}
CurrentRewardData storage _currentReward = currentReward;
_currentReward.aco = aco;
_currentReward.rewardRate = rewardRate;
/*
* Set the lastUpdateTime as now for all active LP tokens.
* This timestamp is used to calculate the accumulated per share value.
* So new current ACO timestamp is set for all LP tokens as "now".
*/for (uint256 i =0; i < poolInfo.length; ++i) {
if (poolInfo[i].allocPoint >0) {
acosRewardDataPerLP[i][aco].lastUpdateTime =block.timestamp;
}
}
emit SetCurrentReward(aco, rewardRate);
}
/*
* Function to the admin withdraws a stuck token if necessary.
* For example, an ACO rewarded and that is not being used anymore.
* Withdraw any LP token is FORBIDDEN.
*/functionwithdrawStuckToken(address token, uint256 amount, address destination) externalonlyOwner{
// To guarantee the deny for withdrawing a LP token.for (uint256 i =0; i < poolInfo.length; ++i) {
require(poolInfo[i].lpToken != token, "Forbidden!");
}
uint256 tokenBalance = ACOAssetHelper._getAssetBalanceOf(token, address(this));
if (amount > tokenBalance) {
amount = tokenBalance;
}
if (amount >0) {
ACOAssetHelper._callTransferERC20(token, destination, amount);
emit WithdrawStuckToken(token, destination, amount);
}
}
}
pragmasolidity ^0.6.6;// Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/**
* @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);
}
Contract Source Code
File 5 of 6: Ownable.sol
// SPDX-License-Identifier: MIT// Adapted from OpenZeppelinpragmasolidity ^0.6.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;
}
}
/**
* @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.
*/contractOwnableisContext{
addressprivate _owner;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/functioninit() internal{
require(_owner ==address(0), "Ownable: Contract initialized");
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(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @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 6: SafeMath.sol
pragmasolidity ^0.6.6;// Contract on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/**
* @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 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) {
return sub(a, b, "SafeMath: subtraction overflow");
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
* - Subtraction cannot overflow.
*/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 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) {
require(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;
}
}