pragma solidity ^0.6.12;
// SPDX-License-Identifier: MIT
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner public {
require(newOwner != address(0));
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
interface YfDAI {
function balanceOf(address) external returns (uint);
function transferFrom(address, address, uint) external returns (bool);
function transfer(address, uint) external returns (bool);
}
contract YfDAIlock is Ownable {
using SafeMath for uint;
address public constant tokenAddress = 0xf4CD3d3Fda8d7Fd6C5a500203e38640A70Bf9577;
uint public constant tokensLocked = 1050e18;
uint public constant unlockRate = 10000;
uint public constant lockDuration = 180 days;
uint public lastClaimedTime;
uint public deployTime;
constructor() public {
deployTime = now;
lastClaimedTime = now;
}
function claim() public onlyOwner {
uint pendingUnlocked = getPendingUnlocked();
uint contractBalance = YfDAI(tokenAddress).balanceOf(address(this));
uint amountToSend = pendingUnlocked;
if (contractBalance < pendingUnlocked) {
amountToSend = contractBalance;
}
require(YfDAI(tokenAddress).transfer(owner, amountToSend), "Could not transfer Tokens.");
lastClaimedTime = now;
}
function getPendingUnlocked() public view returns (uint) {
uint timeDiff = now.sub(lastClaimedTime);
uint pendingUnlocked = tokensLocked
.mul(unlockRate)
.mul(timeDiff)
.div(lockDuration)
.div(1e4);
return pendingUnlocked;
}
// function to allow admin to claim *other* ERC20 tokens sent to this contract (by mistake)
function transferAnyERC20Tokens(address _tokenAddr, address _to, uint _amount) public onlyOwner {
require(_tokenAddr != tokenAddress, "Cannot transfer out reward tokens");
YfDAI(_tokenAddr).transfer(_to, _amount);
}
}
{
"compilationTarget": {
"browser/lock.sol": "YfDAIlock"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deployTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPendingUnlocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastClaimedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferAnyERC20Tokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]