Created
February 19, 2021 09:32
-
-
Save athlona64/0e5f6ad79b10d0974c4f74e87b7581a1 to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.4.19+commit.c4cbbb05.js&optimize=false&runs=200&gist=
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
pragma experimental ABIEncoderV2; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
function percent(uint numerator, uint denominator) internal pure returns(uint quotient) { | |
// caution, check safe-to-multiply here | |
uint _numerator = numerator * 10 ** (10); | |
// with rounding of last digit | |
uint _quotient = ((_numerator / denominator)) / 10; | |
return ( _quotient); | |
} | |
} | |
contract LockSmartContract { | |
function depositToken(address likeAddr, uint amount, uint256 expire) public returns (bool); | |
function requestWithdraw(address likeAddr) public returns (bool); | |
function withdrawToken(address likeAddr, uint amount) public returns (bool); | |
function getLock(address likeAddr, address _sender) public view returns (uint256); | |
function getWithdraw(address likeAddr, address _sender) public view returns (uint8); | |
function getAmount(address likeAddr, address _sender) public view returns (uint256); | |
function getDepositTime(address likeAddr, address _sender) public view returns (uint256); | |
function getActiveLock(address likeAddr) public view returns (uint256); | |
} | |
contract Loan { | |
function contractLoans(address _borrower) public view returns (address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint8); | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
//oracle address for feed total lock and reward this address is oracle | |
address public oracleAddress; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
modifier onlyOracleAddress() { | |
require(oracleAddress == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
function transferOracleAddress(address newOracle) onlyOwner public { | |
if (newOracle != address(0)) { | |
oracleAddress = newOracle; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract Airdrop is Ownable{ | |
using SafeMath for uint; | |
function Airdrop(address oracle) public { | |
oracleAddress = oracle; | |
} | |
enum statusAirdrop { | |
EXPIRED, | |
START | |
} | |
//round for claim | |
mapping (address => uint256) public Round; | |
//total token locked in smart contract | |
mapping (address => mapping (uint256 => uint256)) public TotalLock; | |
//total reward in this round | |
mapping (address => mapping (uint256 => uint256)) public TotalRewards; | |
//user claim | |
mapping (address => mapping (address => claim)) public Claim; | |
//check status round | |
mapping (address => mapping (uint256 => expire)) public CheckExpire; | |
mapping (address => uint256) public balanceToken; | |
mapping (address => mapping (uint256 => uint256)) public balanceOfRound; | |
address public loanaddr = 0x44cE5344C65f992Cd7DF1b5B24e80ac09d9FCe29; | |
address public lockaddr = 0x9D94910F2F5271d770b9021537ba07e0a3811F2c; | |
address public likeaddr = 0xB1B4615508528DE75012E38A0e1c07e0143c0c5D; | |
event GetRewards(address _addr, address _lock, uint256 round, address sender, uint256 reward); | |
event UpdateRewards(address _addr, address lock, uint256 rewards, uint256 round, uint256 expire); | |
event AdminWithdrawByRound(address _addr, uint256 _round, uint256 balance); | |
event AdminWithdraw(address _addr, uint256 balance); | |
struct claim { | |
uint256 lastTime; | |
uint256 round; | |
uint256 nextTime; | |
uint256 amount; | |
} | |
struct expire { | |
statusAirdrop status; | |
uint256 expire; | |
uint256 start; | |
} | |
function changeLoan(address addr) onlyOwner public { | |
loanaddr = addr; | |
} | |
function changeLock(address addr) onlyOwner public { | |
lockaddr = addr; | |
} | |
function changeLike(address addr) onlyOwner public { | |
likeaddr = addr; | |
} | |
//this function update round and reward, locked token by Oracle address | |
function updateRewards(address _addr, address lock, uint256 rewards, uint256 _expire) onlyOracleAddress public{ | |
if(rewards > ERC20_Interface(_addr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(_addr).transferFrom(msg.sender, address(this), rewards); | |
balanceToken[_addr] = balanceToken[_addr].add(rewards); | |
//update round in this token address | |
Round[_addr] = Round[_addr].add(1); | |
uint256 activeLock = LockSmartContract(lock).getActiveLock(_addr); | |
//set Total Lock in this round | |
TotalLock[_addr][Round[_addr]] = activeLock; | |
//set Total rewards in this round | |
TotalRewards[_addr][Round[_addr]] = rewards; | |
balanceOfRound[_addr][Round[_addr]] = rewards; | |
uint256 currentTime = now; | |
//set expire round in this token | |
expire memory setExpire = CheckExpire[_addr][Round[_addr]]; | |
setExpire.status = statusAirdrop.START; | |
setExpire.expire = currentTime.add(_expire); | |
setExpire.start = currentTime; | |
//save state | |
CheckExpire[_addr][Round[_addr]] = setExpire; | |
UpdateRewards(_addr, lock, rewards, Round[_addr], currentTime.add(_expire)); | |
} | |
function getAllBalance(address _borrower) internal view returns (uint256) { | |
uint256 sum; | |
uint256 balanceLocked = LockSmartContract(lockaddr).getAmount(likeaddr, _borrower); | |
(,,,,,,sum,,,,) = Loan(loanaddr).contractLoans(_borrower); | |
return sum.add(balanceLocked); | |
} | |
function getRewards(address _addr, address _lock) public returns (bool) { | |
claim memory userClaim = Claim[_addr][msg.sender]; | |
expire memory setExpire = CheckExpire[_addr][Round[_addr]]; | |
uint256 currentTime = now; | |
require(userClaim.round < Round[_addr]); | |
require(LockSmartContract(_lock).getWithdraw(_addr, msg.sender) == 0); | |
require(setExpire.start > LockSmartContract(_lock).getDepositTime(_addr, msg.sender)); | |
uint256 balanceLocked = getAllBalance(msg.sender); | |
//calculate ratio | |
uint256 ratio = balanceLocked.percent(TotalLock[_addr][Round[_addr]]); | |
//calculate rewards | |
uint256 reward = ratio.mul(TotalRewards[_addr][Round[_addr]]).div(1000000000); | |
balanceToken[_addr] = balanceToken[_addr].sub(reward); | |
balanceOfRound[_addr][Round[_addr]] = balanceOfRound[_addr][Round[_addr]].sub(reward); | |
ERC20_Interface(_addr).transfer(msg.sender, reward); | |
//update state | |
userClaim.lastTime = currentTime; | |
userClaim.round = Round[_addr]; | |
userClaim.nextTime = setExpire.expire.add(1); | |
userClaim.amount = reward; | |
Claim[_addr][msg.sender] = userClaim; | |
GetRewards(_addr, _lock, Round[_addr], msg.sender, reward); | |
return true; | |
} | |
function checkRewards(address _addr, address _lock, address _checker) public view returns (uint256){ | |
expire memory setExpire = CheckExpire[_addr][Round[_addr]]; | |
// return (setExpire.start, LockSmartContract(_lock).getDepositTime(_addr, _checker)); | |
uint256 balanceLocked = getAllBalance(_checker); | |
//calculate ratio | |
uint256 ratio = balanceLocked.percent(TotalLock[_addr][Round[_addr]]); | |
//calculate rewards | |
uint256 reward = ratio.mul(TotalRewards[_addr][Round[_addr]]).div(1000000000); | |
//check time lock user and system | |
if(setExpire.start > LockSmartContract(_lock).getDepositTime(_addr, _checker)){ | |
return reward; | |
}else{ | |
return 0; | |
} | |
} | |
//admin | |
function adminWithdrawByRound(address _addr, uint256 _round) onlyOwner public returns (bool) { | |
uint256 balance = balanceOfRound[_addr][_round]; | |
balanceOfRound[_addr][_round] = balanceOfRound[_addr][_round].sub(balance); | |
require(balanceOfRound[_addr][_round] == 0); | |
ERC20_Interface(_addr).transfer(msg.sender, balance); | |
AdminWithdrawByRound(_addr, _round, balance); | |
} | |
function adminWithdraw(address _addr) onlyOwner public returns (bool) { | |
uint256 balance = balanceToken[_addr]; | |
balanceToken[_addr] = balanceToken[_addr].sub(balance); | |
require(balanceToken[_addr] == 0); | |
ERC20_Interface(_addr).transfer(msg.sender, balance); | |
AdminWithdraw(_addr, balance); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
contract Ballot { | |
struct Voter { | |
uint weight; | |
bool voted; | |
uint8 vote; | |
address delegate; | |
} | |
struct Proposal { | |
uint voteCount; | |
} | |
address chairperson; | |
mapping(address => Voter) voters; | |
Proposal[] proposals; | |
/// Create a new ballot with $(_numProposals) different proposals. | |
constructor(uint8 _numProposals) public { | |
chairperson = msg.sender; | |
voters[chairperson].weight = 1; | |
proposals.length = _numProposals; | |
} | |
/// Give $(toVoter) the right to vote on this ballot. | |
/// May only be called by $(chairperson). | |
function giveRightToVote(address toVoter) public { | |
if (msg.sender != chairperson || voters[toVoter].voted) return; | |
voters[toVoter].weight = 1; | |
} | |
/// Delegate your vote to the voter $(to). | |
function delegate(address to) public { | |
Voter storage sender = voters[msg.sender]; // assigns reference | |
if (sender.voted) return; | |
while (voters[to].delegate != address(0) && voters[to].delegate != msg.sender) | |
to = voters[to].delegate; | |
if (to == msg.sender) return; | |
sender.voted = true; | |
sender.delegate = to; | |
Voter storage delegateTo = voters[to]; | |
if (delegateTo.voted) | |
proposals[delegateTo.vote].voteCount += sender.weight; | |
else | |
delegateTo.weight += sender.weight; | |
} | |
/// Give a single vote to proposal $(toProposal). | |
function vote(uint8 toProposal) public { | |
Voter storage sender = voters[msg.sender]; | |
if (sender.voted || toProposal >= proposals.length) return; | |
sender.voted = true; | |
sender.vote = toProposal; | |
proposals[toProposal].voteCount += sender.weight; | |
} | |
function winningProposal() public view returns (uint8 _winningProposal) { | |
uint256 winningVoteCount = 0; | |
for (uint8 prop = 0; prop < proposals.length; prop++) | |
if (proposals[prop].voteCount > winningVoteCount) { | |
winningVoteCount = proposals[prop].voteCount; | |
_winningProposal = prop; | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
import "remix_tests.sol"; // this import is automatically injected by Remix. | |
import "./ballot.sol"; | |
contract test3 { | |
Ballot ballotToTest; | |
function beforeAll () public { | |
ballotToTest = new Ballot(2); | |
} | |
function checkWinningProposal () public { | |
ballotToTest.vote(1); | |
Assert.equal(ballotToTest.winningProposal(), uint(1), "1 should be the winning proposal"); | |
} | |
function checkWinninProposalWithReturnValue () public view returns (bool) { | |
return ballotToTest.winningProposal() == 1; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
/** | |
* @title Hashed Timelock Contracts (HTLCs) on Ethereum ERC20 tokens. | |
* | |
* This contract provides a way to create and keep HTLCs for ERC20 tokens. | |
* | |
* See HashedTimelock.sol for a contract that provides the same functions | |
* for the native ETH token. | |
* | |
* Protocol: | |
* | |
* 1) newContract(receiver, hashlock, timelock, tokenContract, amount) - a | |
* sender calls this to create a new HTLC on a given token (tokenContract) | |
* for a given amount. A 32 byte contract id is returned | |
* 2) withdraw(contractId, preimage) - once the receiver knows the preimage of | |
* the hashlock hash they can claim the tokens with this function | |
* 3) refund() - after timelock has expired and if the receiver did not | |
* withdraw the tokens the sender / creator of the HTLC can get their tokens | |
* back with this function. | |
*/ | |
contract ERC20 { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract batchTransaction { | |
using SafeMath for uint; | |
event TRANSACTION(address sender, address receiver, uint amount, address token, bytes32 message); | |
function batch(address[] _address, uint[] amount, address _token, bytes32[] _message) public returns(bool){ | |
uint totalSent = 0; | |
for(uint v=0;v<amount.length;v++){ | |
totalSent = totalSent.add(amount[v]); | |
} | |
require(ERC20(_token).allowance(msg.sender, address(this)) >= totalSent); | |
for(uint i=0;i<_address.length;i++){ | |
ERC20(_token).transferFrom(msg.sender, _address[i], amount[i]); | |
TRANSACTION(msg.sender, _address[i], amount[i], _token, _message[i]); | |
} | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
pragma experimental ABIEncoderV2; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
/** | |
* @title Hashed Timelock Contracts (HTLCs) on Ethereum ERC20 tokens. | |
* | |
* This contract provides a way to create and keep HTLCs for ERC20 tokens. | |
* | |
* See HashedTimelock.sol for a contract that provides the same functions | |
* for the native ETH token. | |
* | |
* Protocol: | |
* | |
* 1) newContract(receiver, hashlock, timelock, tokenContract, amount) - a | |
* sender calls this to create a new HTLC on a given token (tokenContract) | |
* for a given amount. A 32 byte contract id is returned | |
* 2) withdraw(contractId, preimage) - once the receiver knows the preimage of | |
* the hashlock hash they can claim the tokens with this function | |
* 3) refund() - after timelock has expired and if the receiver did not | |
* withdraw the tokens the sender / creator of the HTLC can get their tokens | |
* back with this function. | |
*/ | |
contract ERC20 { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract batchTransaction { | |
using SafeMath for uint; | |
event TRANSACTION(address sender, address receiver, uint amount, address token, string message); | |
function batch(address[] _address, uint[] amount, address _token, string[] memory _message) public returns(bool){ | |
uint totalSent = 0; | |
for(uint v=0;v<amount.length;v++){ | |
totalSent = totalSent.add(amount[v]); | |
} | |
require(ERC20(_token).allowance(msg.sender, address(this)) >= totalSent); | |
for(uint i=0;i<_address.length;i++){ | |
ERC20(_token).transferFrom(msg.sender, _address[i], amount[i]); | |
TRANSACTION(msg.sender, _address[i], amount[i], _token, _message[i]); | |
} | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
/** | |
* @title Hashed Timelock Contracts (HTLCs) on Ethereum ERC20 tokens. | |
* | |
* This contract provides a way to create and keep HTLCs for ERC20 tokens. | |
* | |
* See HashedTimelock.sol for a contract that provides the same functions | |
* for the native ETH token. | |
* | |
* Protocol: | |
* | |
* 1) newContract(receiver, hashlock, timelock, tokenContract, amount) - a | |
* sender calls this to create a new HTLC on a given token (tokenContract) | |
* for a given amount. A 32 byte contract id is returned | |
* 2) withdraw(contractId, preimage) - once the receiver knows the preimage of | |
* the hashlock hash they can claim the tokens with this function | |
* 3) refund() - after timelock has expired and if the receiver did not | |
* withdraw the tokens the sender / creator of the HTLC can get their tokens | |
* back with this function. | |
*/ | |
contract ERC20 { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
function addCredit(address _from, address _to, uint _value) public returns (bool success); | |
function disCredit(address _from, address _to, uint _value) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
transferOwner(newOwner); | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
} | |
contract batchTransaction is Ownable{ | |
using SafeMath for uint; | |
event TRANSACTION(address sender, address receiver, uint amount, address token, uint symbol, bytes32 message); | |
function batchCredit(address[] _address, uint[] amount, uint[] symbol, address _token, bytes32[] hcs) onlyOwner public returns(bool) { | |
for(uint i=0;i<_address.length;i++){ | |
if(symbol[i] == 1){ | |
ERC20(_token).addCredit(msg.sender, _address[i], amount[i]); | |
TRANSACTION(msg.sender, _address[i], amount[i], _token, symbol[i], hcs[i]); | |
}else{ | |
ERC20(_token).disCredit(_address[i], msg.sender, amount[i]); | |
TRANSACTION(_address[i], msg.sender, amount[i], _token, symbol[i], hcs[i]); | |
} | |
} | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Your current Solidity version is//0.4.19+commit.c4cbbb05.Emscripten.clangpragma solidity ^0.4.4;contract Token { /// @return total amount of tokens function totalSupply() constant returns (uint256 supply) {} /// @param _owner The address from which the balance will be retrieved /// @return The balance function balanceOf(address _owner) constant returns (uint256 balance) {} /// @notice send `_value` token to `_to` from `msg.sender` /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not function transfer(address _to, uint256 _value) returns (bool success) {} /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` /// @param _from The address of the sender /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {} /// @notice `msg.sender` approves `_addr` to spend `_value` tokens /// @param _spender The address of the account able to transfer the tokens /// @param _value The amount of wei to be approved for transfer /// @return Whether the approval was successful or not function approve(address _spender, uint256 _value) returns (bool success) {} /// @param _owner The address of the account owning tokens /// @param _spender The address of the account able to transfer the tokens /// @return Amount of remaining tokens allowed to spent function allowance(address _owner, address _spender) constant returns (uint256 remaining) {} event Transfer(address indexed _from, address indexed _to, uint256 _value); event Approval(address indexed _owner, address indexed _spender, uint256 _value);}contract StandardToken is Token { function transfer(address _to, uint256 _value) returns (bool success) { //Default assumes totalSupply can't be over max (2^256 - 1). //If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap. //Replace the if with this one instead. //if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) { if (balances[msg.sender] >= _value && _value > 0) { balances[msg.sender] -= _value; balances[_to] += _value; Transfer(msg.sender, _to, _value); return true; } else { return false; } } function transferFrom(address _from, address _to, uint256 _value) returns (bool success) { //same as above. Replace this line with the following if you want to protect against wrapping uints. //if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) { if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) { balances[_to] += _value; balances[_from] -= _value; allowed[_from][msg.sender] -= _value; Transfer(_from, _to, _value); return true; } else { return false; } } function balanceOf(address _owner) constant returns (uint256 balance) { return balances[_owner]; } function approve(address _spender, uint256 _value) returns (bool success) { allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); return true; } function allowance(address _owner, address _spender) constant returns (uint256 remaining) { return allowed[_owner][_spender]; } mapping (address => uint256) balances; mapping (address => mapping (address => uint256)) allowed; uint256 public totalSupply;}//name this contract whatever you'd likecontract ERC20Token is StandardToken { function () { //if ether is sent to this address, send it back. throw; } /* Public variables of the token */ /* NOTE: The following variables are OPTIONAL vanities. One does not have to include them. They allow one to customise the token contract & in no way influences the core functionality. Some wallets/interfaces might not even bother to look at this information. */ string public name; //fancy name: eg Simon Bucks uint8 public decimals; //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether. string public symbol; //An identifier: eg SBX string public version = 'H1.0'; //human 0.1 standard. Just an arbitrary versioning scheme.//// CHANGE THESE VALUES FOR YOUR TOKEN////make sure this function name matches the contract name above. So if you're token is called TutorialToken, make sure the //contract name above is also TutorialToken instead of ERC20Token function ERC20Token( ) { balances[msg.sender] = 100000; // Give the creator all initial tokens (100000 for example) totalSupply = 100000; // Update total supply (100000 for example) name = 'OathCoin'; // Set the name for display purposes decimals = 0; // Amount of decimals for display purposes symbol = 'OATH'; // Set the symbol for display purposes } /* Approves and then calls the receiving contract */ function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) { allowed[msg.sender][_spender] = _value; Approval(msg.sender, _spender, _value); //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this. //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData) //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead. if(!_spender.call(bytes4(bytes32(sha3('receiveApproval(address,uint256,address,bytes)'))), msg.sender, _value, this, _extraData)) { throw; } return true; }} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
contract GeoTraking { | |
struct LocationStamp { | |
uint256 lat; | |
uint256 lng; | |
uint256 dateTime; | |
} | |
mapping(address => LocationStamp[]) public userLocations; | |
function track(uint256 lat, uint256 lng) public { | |
LocationStamp memory currentLoc; | |
currentLoc.lat = lat; | |
currentLoc.lng = lng; | |
currentLoc.dateTime = block.timestamp; | |
userLocations[msg.sender].push(currentLoc); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
/** | |
* @title Hashed Timelock Contracts (HTLCs) on Ethereum ERC20 tokens. | |
* | |
* This contract provides a way to create and keep HTLCs for ERC20 tokens. | |
* | |
* See HashedTimelock.sol for a contract that provides the same functions | |
* for the native ETH token. | |
* | |
* Protocol: | |
* | |
* 1) newContract(receiver, hashlock, timelock, tokenContract, amount) - a | |
* sender calls this to create a new HTLC on a given token (tokenContract) | |
* for a given amount. A 32 byte contract id is returned | |
* 2) withdraw(contractId, preimage) - once the receiver knows the preimage of | |
* the hashlock hash they can claim the tokens with this function | |
* 3) refund() - after timelock has expired and if the receiver did not | |
* withdraw the tokens the sender / creator of the HTLC can get their tokens | |
* back with this function. | |
*/ | |
contract ERC20 { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract HashedTimelockERC20 { | |
event HTLCERC20New( | |
bytes32 indexed contractId, | |
address indexed sender, | |
address indexed receiver, | |
address tokenContract, | |
uint256 amount, | |
bytes32 hashlock, | |
uint256 timelock | |
); | |
event HTLCERC20Withdraw(bytes32 indexed contractId); | |
event HTLCERC20Refund(bytes32 indexed contractId); | |
struct LockContract { | |
address sender; | |
address receiver; | |
address tokenContract; | |
uint256 amount; | |
bytes32 hashlock; | |
// locked UNTIL this time. Unit depends on consensus algorithm. | |
// PoA, PoA and IBFT all use seconds. But Quorum Raft uses nano-seconds | |
uint256 timelock; | |
bool withdrawn; | |
bool refunded; | |
string preimage; | |
} | |
modifier tokensTransferable(address _token, address _sender, uint256 _amount) { | |
require(_amount > 0); | |
require( | |
ERC20(_token).allowance(_sender, address(this)) >= _amount | |
); | |
_; | |
} | |
modifier futureTimelock(uint256 _time) { | |
// only requirement is the timelock time is after the last blocktime (now). | |
// probably want something a bit further in the future then this. | |
// but this is still a useful sanity check: | |
require(_time > now); | |
_; | |
} | |
modifier contractExists(bytes32 _contractId) { | |
require(haveContract(_contractId)); | |
_; | |
} | |
modifier hashlockMatches(bytes32 _contractId, string _x) { | |
require( | |
contracts[_contractId].hashlock == sha256(_x) | |
); | |
_; | |
} | |
modifier withdrawable(bytes32 _contractId) { | |
require(contracts[_contractId].receiver == msg.sender); | |
require(contracts[_contractId].withdrawn == false); | |
// if we want to disallow claim to be made after the timeout, uncomment the following line | |
// require(contracts[_contractId].timelock > now, "withdrawable: timelock time must be in the future"); | |
_; | |
} | |
modifier refundable(bytes32 _contractId) { | |
require(contracts[_contractId].sender == msg.sender); | |
require(contracts[_contractId].refunded == false); | |
require(contracts[_contractId].withdrawn == false); | |
require(contracts[_contractId].timelock <= now); | |
_; | |
} | |
mapping (bytes32 => LockContract) contracts; | |
/** | |
* @dev Sender / Payer sets up a new hash time lock contract depositing the | |
* funds and providing the reciever and terms. | |
* | |
* NOTE: _receiver must first call approve() on the token contract. | |
* See allowance check in tokensTransferable modifier. | |
* @param _receiver Receiver of the tokens. | |
* @param _hashlock A sha-2 sha256 hash hashlock. | |
* @param _timelock UNIX epoch seconds time that the lock expires at. | |
* Refunds can be made after this time. | |
* @param _tokenContract ERC20 Token contract address. | |
* @param _amount Amount of the token to lock up. | |
* @return contractId Id of the new HTLC. This is needed for subsequent | |
* calls. | |
*/ | |
function newContract( | |
address _receiver, | |
bytes32 _hashlock, | |
uint256 _timelock, | |
address _tokenContract, | |
uint256 _amount | |
) | |
external | |
tokensTransferable(_tokenContract, msg.sender, _amount) | |
futureTimelock(_timelock) | |
returns (bytes32 contractId) | |
{ | |
contractId = sha256( | |
msg.sender, | |
_receiver, | |
_tokenContract, | |
_amount, | |
_hashlock, | |
_timelock | |
); | |
// Reject if a contract already exists with the same parameters. The | |
// sender must change one of these parameters (ideally providing a | |
// different _hashlock). | |
if (haveContract(contractId)) | |
revert(); | |
// This contract becomes the temporary owner of the tokens | |
if (!ERC20(_tokenContract).transferFrom(msg.sender, address(this), _amount)) | |
revert(); | |
contracts[contractId] = LockContract( | |
msg.sender, | |
_receiver, | |
_tokenContract, | |
_amount, | |
_hashlock, | |
_timelock, | |
false, | |
false, | |
"0x0" | |
); | |
HTLCERC20New( | |
contractId, | |
msg.sender, | |
_receiver, | |
_tokenContract, | |
_amount, | |
_hashlock, | |
_timelock | |
); | |
} | |
/** | |
* @dev Called by the receiver once they know the preimage of the hashlock. | |
* This will transfer ownership of the locked tokens to their address. | |
* | |
* @param _contractId Id of the HTLC. | |
* @param _preimage sha256(_preimage) should equal the contract hashlock. | |
* @return bool true on success | |
*/ | |
function withdraw(bytes32 _contractId, string _preimage) | |
external | |
contractExists(_contractId) | |
hashlockMatches(_contractId, _preimage) | |
withdrawable(_contractId) | |
returns (bool) | |
{ | |
LockContract storage c = contracts[_contractId]; | |
c.preimage = _preimage; | |
c.withdrawn = true; | |
ERC20(c.tokenContract).transfer(c.receiver, c.amount); | |
HTLCERC20Withdraw(_contractId); | |
return true; | |
} | |
/** | |
* @dev Called by the sender if there was no withdraw AND the time lock has | |
* expired. This will restore ownership of the tokens to the sender. | |
* | |
* @param _contractId Id of HTLC to refund from. | |
* @return bool true on success | |
*/ | |
function refund(bytes32 _contractId) | |
external | |
contractExists(_contractId) | |
refundable(_contractId) | |
returns (bool) | |
{ | |
LockContract storage c = contracts[_contractId]; | |
c.refunded = true; | |
ERC20(c.tokenContract).transfer(c.sender, c.amount); | |
HTLCERC20Refund(_contractId); | |
return true; | |
} | |
/** | |
* @dev Get contract details. | |
* @param _contractId HTLC contract id | |
* @return All parameters in struct LockContract for _contractId HTLC | |
*/ | |
function getContract(bytes32 _contractId) | |
public | |
view | |
returns ( | |
address sender, | |
address receiver, | |
address tokenContract, | |
uint256 amount, | |
bytes32 hashlock, | |
uint256 timelock, | |
bool withdrawn, | |
bool refunded, | |
string preimage | |
) | |
{ | |
if (haveContract(_contractId) == false) | |
return (address(0), address(0), address(0), 0, 0, 0, false, false, ""); | |
LockContract storage c = contracts[_contractId]; | |
return ( | |
c.sender, | |
c.receiver, | |
c.tokenContract, | |
c.amount, | |
c.hashlock, | |
c.timelock, | |
c.withdrawn, | |
c.refunded, | |
c.preimage | |
); | |
} | |
/** | |
* @dev Is there a contract with id _contractId. | |
* @param _contractId Id into contracts mapping. | |
*/ | |
function haveContract(bytes32 _contractId) | |
internal | |
view | |
returns (bool exists) | |
{ | |
exists = (contracts[_contractId].sender != address(0)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract KickbackResturant is Ownable { | |
struct onwerToken { | |
address token; | |
address shop; | |
uint256 amount; | |
} | |
mapping(address => uint) public totalBalance; | |
mapping (address => mapping(address => onwerToken)) public tokens; | |
//tokens[trc20][shopaddr] | |
event KickbackMsg(address trc20,address _sender, address _to, uint _value,uint _return_like, string _msg); | |
event DepositMsg(address trc20,address _sender, uint _value, string _msg ); | |
event WithdrawToken(address trc20,address _sender, uint _value,string _msg); | |
//for call outside | |
function kickback(address trc20,address _to, uint _value, string _msg) public returns (bool){ | |
//check balance for sender | |
if(_value > TRC20_Interface(trc20).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
//transfer | |
TRC20_Interface(trc20).transferFrom(msg.sender, _to, _value); | |
uint return_like = _value/30; | |
//check amount | |
require(tokens[trc20][_to].amount>=return_like); | |
//return_like to sneder | |
TRC20_Interface(trc20).transfer(msg.sender, return_like); | |
//set totalBalance all like in smart contract | |
totalBalance[trc20] -= return_like; | |
onwerToken memory tokenData = tokens[trc20][_to]; | |
tokenData.amount -= return_like; | |
tokens[trc20][_to] = tokenData; | |
//anounce to outside | |
KickbackMsg(trc20,msg.sender, _to, _value,return_like,_msg); | |
} | |
// function transferMessage(address trc20, address _to, uint _value, string message) public returns (bool) { | |
// if(_value > TRC20_Interface(trc20).allowance(msg.sender, address(this))) { | |
// revert(); | |
// } | |
// TRC20_Interface(trc20).transferFrom(msg.sender, _to, _value); | |
// TransferMessage(trc20, _to, _value, message); | |
// return true; | |
// } | |
function depositToken(address trc20, uint amount, address shopaddr, string _msg) public { | |
//check amount of deposit not > TRC20_Interface.approve | |
if(amount > TRC20_Interface(trc20).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
//deposit likepoint to smart contract | |
TRC20_Interface(trc20).transferFrom(msg.sender, address(this), amount); | |
//set totalBalance all like in smart contract | |
totalBalance[trc20] += amount; | |
//set balance for shopaddr | |
onwerToken memory tokenData = tokens[trc20][shopaddr]; | |
tokenData.token = trc20; | |
tokenData.amount += amount; | |
tokenData.shop = shopaddr; | |
tokens[trc20][shopaddr] = tokenData; | |
//anounce event | |
DepositMsg(trc20,shopaddr,amount,_msg); | |
} | |
function withdrawToken(address trc20, uint amount,string _msg) onlyOwner public { | |
onwerToken memory tokenData = tokens[trc20][msg.sender]; | |
//require(now > tokenData.expire); | |
require(amount <= tokenData.amount); | |
tokenData.amount -= amount; | |
tokens[trc20][msg.sender] = tokenData; | |
//balanceToken[trc20]= balanceToken[trc20].sub(amount); | |
totalBalance[trc20] -= amount; | |
TRC20_Interface(trc20).transfer(msg.sender, amount); | |
WithdrawToken(trc20, msg.sender, amount,_msg); | |
} | |
} | |
contract TRC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
contract HelloWorld { | |
string public name = "Prapat"; | |
uint256 age = 28; | |
function updateName(string memory _name) public { | |
name = _name; | |
} | |
function addAge() public { | |
age += 1; | |
} | |
function readAge() public view returns (uint256) { | |
return age; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
contract Bank { | |
mapping(address => uint256) private balances; | |
address public owner; | |
address[] accounts; | |
constructor() public { | |
owner = msg.sender; | |
} | |
function deposit() public payable returns (uint256) { | |
if(0 == balances[msg.sender]){ | |
accounts.push(msg.sender); | |
} | |
balances[msg.sender] += msg.value; | |
return balances[msg.sender]; | |
} | |
function withdraw(uint256 _amount) public returns (uint256) { | |
require(balances[msg.sender] >= _amount, 'not enought.'); | |
balances[msg.sender] -= _amount; | |
msg.sender.transfer(_amount); | |
return balances[msg.sender]; | |
} | |
function balanceOf(address user) view public returns (uint256) { | |
return balances[user]; | |
} | |
function systemDeposit() public payable { | |
require(owner == msg.sender, "you're not admin"); | |
} | |
function systemWithdraw(uint256 amount) public { | |
require(owner == msg.sender, "you're not authorized"); | |
msg.sender.transfer(amount); | |
} | |
function balanceContract() view public returns(uint256) { | |
return address(this).balance; | |
} | |
receive() external payable { | |
deposit(); | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.5.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
require(b <= a, "SafeMath: subtraction overflow"); | |
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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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-solidity/pull/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
// Solidity only automatically asserts when dividing by 0 | |
require(b > 0, "SafeMath: division by zero"); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (uint256) { | |
require(b != 0, "SafeMath: modulo by zero"); | |
return a % b; | |
} | |
} | |
/** | |
* @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; | |
/** | |
* @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) public onlyOwner { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
} | |
} | |
} | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) public view returns (uint); | |
function transfer(address to, uint value) public; | |
event Transfer(address indexed from, address indexed to, uint value); | |
} | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint _value) public { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
emit Transfer(msg.sender, _to, _value); | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) public view returns (uint balance) { | |
return balances[_owner]; | |
} | |
} | |
/** | |
* @title ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) public view returns (uint); | |
function transferFrom(address from, address to, uint value) public; | |
function approve(address spender, uint value) public; | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implemantation of the basic standart token. | |
* @dev https://github.com/ethereum/EIPs/issues/20 | |
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
/** | |
* @dev Transfer tokens from one address to another | |
* @param _from address The address which you want to send tokens from | |
* @param _to address The address which you want to transfer to | |
* @param _value uint the amout of tokens to be transfered | |
*/ | |
function transferFrom(address _from, address _to, uint _value) public { | |
uint256 _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already revert() if this condition is not met | |
// if (_value > _allowance) revert(); | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
emit Transfer(_from, _to, _value); | |
} | |
/** | |
* @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender. | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint _value) public { | |
// To change the approve amount you first have to reduce the addresses` | |
// allowance to zero by calling `approve(_spender, 0)` if it is not | |
// already 0 to mitigate the race condition described here: | |
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) revert("approve revert"); | |
allowed[msg.sender][_spender] = _value; | |
emit Approval(msg.sender, _spender, _value); | |
} | |
/** | |
* @dev Function to check the amount of tokens than an owner allowed to a spender. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A uint specifing the amount of tokens still avaible for the spender. | |
*/ | |
function allowance(address _owner, address _spender) public view returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 | |
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol | |
*/ | |
contract MintableToken is StandardToken, Ownable { | |
event Mint(address indexed to, uint value); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
uint public totalSupply = 0; | |
modifier canMint() { | |
if(mintingFinished) revert(); | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will recieve the minted tokens. | |
* @param _amount The amount of tokens to mint. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mint(address _to, uint _amount) public onlyOwner canMint returns (bool) { | |
totalSupply = totalSupply.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
emit Mint(_to, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() public onlyOwner returns (bool) { | |
mintingFinished = true; | |
emit MintFinished(); | |
return true; | |
} | |
} | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev modifier to allow actions only when the contract IS paused | |
*/ | |
modifier whenNotPaused() { | |
if (paused) revert("it's paused"); | |
_; | |
} | |
/** | |
* @dev modifier to allow actions only when the contract IS NOT paused | |
*/ | |
modifier whenPaused { | |
if (!paused) revert("it's not paused"); | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() public onlyOwner whenNotPaused returns (bool) { | |
paused = true; | |
emit Pause(); | |
return true; | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() public onlyOwner whenPaused returns (bool) { | |
paused = false; | |
emit Unpause(); | |
return true; | |
} | |
} | |
/** | |
* Pausable token | |
* | |
* Simple ERC20 Token example, with pausable token creation | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer(address _to, uint _value) public whenNotPaused { | |
super.transfer(_to, _value); | |
} | |
function transferFrom(address _from, address _to, uint _value) public whenNotPaused { | |
super.transferFrom(_from, _to, _value); | |
} | |
} | |
/** | |
* @title ERC20 Token | |
*/ | |
contract ERC20Token is PausableToken, MintableToken { | |
using SafeMath for uint256; | |
string public name; | |
string public symbol; | |
uint public decimals; | |
constructor(string memory _name, string memory _symbol, uint _decimals) public { | |
name = _name; | |
symbol = _symbol; | |
decimals = _decimals; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.6.0; | |
pragma experimental ABIEncoderV2; | |
contract SimpleVoting { | |
mapping (string => uint256) votesReceived; | |
string[] public candidateList; | |
mapping(address => bool) public checkVote; | |
constructor(string[] memory candidateNames) public{ | |
candidateList = candidateNames; | |
} | |
function voteForCandidate(string memory candidate) public { | |
require(checkVote[msg.sender] != true, "voted"); | |
checkVote[msg.sender] = true; | |
votesReceived[candidate] += 1; | |
} | |
function totalVotesFor(string memory candidate) public view returns (uint256) { | |
return votesReceived[candidate]; | |
} | |
function candidateCount() public view returns (uint256) { | |
return candidateList.length; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
pragma experimental ABIEncoderV2; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
function interateRate(uint numerator, uint denominator) internal pure returns(uint quotient) { | |
return numerator*denominator; | |
} | |
function mulDiv (uint x, uint y, uint z) public pure returns (uint) | |
{ | |
return mul (x, y) / z; | |
} | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Collateral_Interface { | |
function getTransfer(address likeAddr, address _sender) public view returns (bool); | |
function getLock(address likeAddr, address _sender) public view returns (uint256); | |
function getAmountAll(address likeAddr, address _sender) public view returns (uint256); | |
function getWithdraw(address likeAddr, address _sender) public view returns (bool); | |
function getAmount(address likeAddr, address _sender) public view returns (uint256); | |
function getDepositTime(address likeAddr, address _sender) public view returns (uint256); | |
function getActiveLock(address likeAddr) public view returns (uint256); | |
function transferWithdrawFund(address likeAddr, address borrower, uint amount) public returns (bool); | |
function transferDepositFund(address likeAddr, address borrower, uint amount, uint canTransfer) public returns (bool); | |
function liquidateCollateral(address likeAddr, address borrower, uint256 collateral, uint256 liquidate, address liquidator, uint256 dept) public returns (bool); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract Loan is Ownable { | |
event RePay(address borrower, address _like, address _lock, uint256 amount, uint256 dept, uint256 round); | |
event changeInterestor(address interestor); | |
event changeInterestRate(uint256 rate); | |
event InitLoan(address borrower, address _like, address _lock, uint256 amount, uint256 round); | |
event LiquidateCollateral(address likeAddr, address borrower, uint256 collateral, address liquidator, uint256 dept); | |
event changeEndDate(uint256 endDate); | |
function Loan(address lock) public { | |
InterestorKeep = msg.sender; | |
_lock = lock; | |
} | |
using SafeMath for uint; | |
uint256 public interest = 50000000000000000; | |
uint256 public roundInterest = 0; | |
uint256 public limitLoan = 50; | |
uint256 public endDate = 365 days; | |
address public InterestorKeep; | |
address public _lock; | |
struct interestRound { | |
uint256 interest; | |
uint256 round; | |
uint256 timestamp; | |
} | |
struct Loans { | |
address borrower; | |
uint256 startTime; | |
uint256 interest; | |
uint256 endTime; | |
uint256 dept; | |
uint256 amountInterest; | |
uint256 principal; | |
uint256 collateral; | |
uint256 liquidateCollateral; | |
uint256 repayPrincipal; | |
uint256 repayInterest; | |
statusLoan isActive; | |
} | |
struct History { | |
uint256 amount; | |
uint256 time; | |
uint256 interest; | |
uint256 active; | |
uint256 end; | |
} | |
enum statusLoan { | |
INACTIVE, | |
ACTIVE | |
} | |
enum statusLockTransfer { | |
ACTIVE, | |
INACTIVE | |
} | |
enum statusWithdraw { | |
INACTIVE, | |
ACTIVE | |
} | |
address[] public user; | |
address[] public userReserve; | |
mapping (address => Loans) public contractLoans; | |
mapping (uint256 => interestRound) public interestHistory; | |
mapping (address => uint256) public userRound; | |
uint256 public balance; | |
uint256 public totalIncome; | |
mapping (address => mapping(uint256 => mapping(uint256 => History))) public payHistory; | |
//total lenngh | |
mapping (address => mapping(uint256 => uint256)) public lenHistory; | |
function changeLock(address _new) public onlyOwner returns (bool) { | |
_lock = _new; | |
} | |
function setInterestor(address inter) public onlyOwner returns (bool) { | |
InterestorKeep = inter; | |
changeInterestor(inter); | |
return true; | |
} | |
function setEndDate(uint256 _date) public onlyOwner returns (bool) { | |
endDate = _date; | |
changeEndDate(_date); | |
return true; | |
} | |
function maximumBorrow(address _like) public view returns (uint256) { | |
uint256 collateral = Collateral_Interface(_lock).getLock(_like, msg.sender); | |
uint256 maxLoan = collateral.interateRate(limitLoan*10**16).div(1000000000000000000); | |
return maxLoan; | |
} | |
//เปลี่ยนอัตราดอกเบี้ย | |
function changeInterest(uint256 _interest) public onlyOwner returns (bool){ | |
roundInterest = roundInterest.add(1); | |
interestRound memory inter = interestHistory[roundInterest]; | |
inter.interest = inter.interest.add(_interest); | |
inter.round = roundInterest; | |
inter.timestamp = now; | |
interestHistory[roundInterest] = inter; | |
interest = _interest; | |
changeInterestRate(interest); | |
return true; | |
} | |
function approvalContract(address _like, address spender, uint256 value) public onlyOwner returns (bool) { | |
ERC20_Interface(_like).approve(spender, value); | |
return true; | |
} | |
function removeApproval(address _like, address spender) public onlyOwner returns (bool) { | |
ERC20_Interface(_like).approve(spender, 0); | |
return true; | |
} | |
function initLoan(address _like, uint256 borrowAmount) public returns (bool){ | |
bool isTransfer = Collateral_Interface(_lock).getTransfer(_like, msg.sender); | |
uint256 collateral = Collateral_Interface(_lock).getLock(_like, msg.sender); | |
bool isWithdraw = Collateral_Interface(_lock).getWithdraw(_like, msg.sender); | |
require(isWithdraw == false); | |
require(!isTransfer); | |
require(collateral > 0); | |
uint256 maxLoan = collateral.interateRate(limitLoan*10**16).div(1000000000000000000); | |
require(maxLoan >= borrowAmount); | |
require(Collateral_Interface(_lock).transferWithdrawFund(_like, msg.sender, borrowAmount)); | |
Loans memory bookInit = contractLoans[msg.sender]; | |
//check ว่ามีสัญญาอยู่ไหม | |
require(bookInit.isActive == statusLoan.INACTIVE); | |
bookInit.borrower = msg.sender; | |
bookInit.startTime = now; | |
bookInit.liquidateCollateral = collateral - borrowAmount; | |
bookInit.endTime = now + endDate; | |
bookInit.interest = interest; | |
bookInit.principal = borrowAmount; | |
bookInit.collateral = collateral; | |
bookInit.isActive = statusLoan.ACTIVE; | |
contractLoans[msg.sender] = bookInit; | |
userRound[msg.sender] = userRound[msg.sender].add(1); | |
//add user loans | |
user.push(msg.sender); | |
InitLoan(msg.sender, _like, _lock, borrowAmount, userRound[msg.sender]); | |
return true; | |
} | |
function getTotalUser() public view returns (uint256) { | |
return user.length; | |
} | |
function removeUser() internal returns (bool) { | |
for(uint256 i=0;i<user.length;i++){ | |
userReserve.push(user[i]); | |
} | |
for(uint256 v=0;v<userReserve.length;v++){ | |
if(user[v] != msg.sender){ | |
user[v] = userReserve[v]; | |
} | |
} | |
user.length--; | |
delete userReserve; | |
return true; | |
} | |
function getCurrentDept(address _borrower) public view returns (Loans, uint256) { | |
Loans memory borrower = contractLoans[_borrower]; | |
uint256 period = now.sub(borrower.startTime); | |
//31556952 is second 1 years | |
uint256 ratio = borrower.interest.div(31556952); | |
uint256 percent = ratio.mul(period); | |
uint256 dept = percent.mulDiv(borrower.principal, 1000000000000000000); | |
return (borrower, dept); | |
} | |
function rePay(address _like, uint256 amount) public returns (bool) { | |
Loans memory borrower = contractLoans[msg.sender]; | |
uint256 period = now.sub(borrower.startTime); | |
//31556952 is second 1 years | |
uint256 ratio = borrower.interest.div(31556952); | |
uint256 percent = ratio.mul(period); | |
uint256 dept = percent.mulDiv(borrower.principal, 1000000000000000000); | |
uint256 principal = amount - dept; | |
//เงินต้นที่คงเหลือที่ใช้ในการคำนวนดอกเบี้ยในการชำระครั้งต่อไป | |
uint256 paidPrincipal = 0; | |
//ส่วนที่ต้องโอนคืนกรณีชำระเกินมา** | |
uint256 fundRevese = 0; | |
//ยอดที่ชำระส่วนเงินต้น | |
uint256 sumPaid = 0; | |
//ตรวจสอบว่าเงินต้นที่ต้องคืนน้อยกว่ายอดชำระไหม | |
if(borrower.principal <= principal){ | |
ERC20_Interface(_like).transferFrom(msg.sender, address(InterestorKeep), dept); | |
Collateral_Interface(_lock).transferDepositFund(_like, msg.sender, borrower.principal, 1); | |
paidPrincipal = 0; | |
balance = balance.add(borrower.principal); | |
totalIncome = totalIncome.add(dept); | |
sumPaid = borrower.principal; | |
//คืนส่วนเกิน | |
fundRevese = principal.sub(borrower.principal); | |
//ปรับสถานะเป็นไม่มีหนี้ | |
borrower.isActive = statusLoan.INACTIVE; | |
// removeUser(); | |
}else{ | |
ERC20_Interface(_like).transferFrom(msg.sender, address(InterestorKeep), dept); | |
balance = balance.add(principal); | |
totalIncome = totalIncome.add(dept); | |
Collateral_Interface(_lock).transferDepositFund(_like, msg.sender, principal, 0); | |
paidPrincipal = borrower.principal.sub(principal); | |
sumPaid = principal; | |
} | |
borrower.repayPrincipal = borrower.repayPrincipal.add(sumPaid); | |
borrower.repayInterest = borrower.repayInterest.add(dept); | |
borrower.startTime = now; | |
borrower.principal = paidPrincipal; | |
contractLoans[msg.sender] = borrower; | |
//History | |
History memory history = payHistory[msg.sender][userRound[msg.sender]][lenHistory[msg.sender][userRound[msg.sender]]]; | |
history.amount = paidPrincipal; | |
history.time = borrower.startTime; | |
history.interest = dept; | |
payHistory[msg.sender][userRound[msg.sender]][lenHistory[msg.sender][userRound[msg.sender]]] = history; | |
lenHistory[msg.sender][userRound[msg.sender]] = lenHistory[msg.sender][userRound[msg.sender]].add(1); | |
RePay(msg.sender, _like, _lock, sumPaid, dept, userRound[msg.sender]); | |
return true; | |
} | |
function rePayAll(address _like) public returns (bool) { | |
Loans memory borrower = contractLoans[msg.sender]; | |
uint256 period = now.sub(borrower.startTime); | |
uint256 ratio = borrower.interest.div(31556952); | |
uint256 percent = ratio.mul(period); | |
uint256 dept = percent.mulDiv(borrower.principal, 1000000000000000000); | |
//เงินต้นที่คงเหลือที่ใช้ในการคำนวนดอกเบี้ยในการชำระครั้งต่อไป | |
uint256 paidPrincipal = 0; | |
//ส่วนที่ต้องโอนคืนกรณีชำระเกินมา** | |
//ยอดที่ชำระส่วนเงินต้น | |
uint256 sumPaid = 0; | |
//โอนดอกเบี้ยไปให้แอดเดรสนี้เก็บ | |
ERC20_Interface(_like).transferFrom(msg.sender, address(InterestorKeep), dept); | |
//ปลดหนี้พร้อมสั่งสถานะล็อคให้ถอนได้ | |
Collateral_Interface(_lock).transferDepositFund(_like, msg.sender, borrower.principal, 1); | |
paidPrincipal = 0; | |
balance = balance.add(borrower.principal); | |
totalIncome = totalIncome.add(dept); | |
sumPaid = borrower.principal; | |
//ปรับสถานะเป็นไม่มีหนี้ | |
borrower.isActive = statusLoan.INACTIVE; | |
// removeUser(); | |
borrower.repayPrincipal = borrower.repayPrincipal.add(sumPaid); | |
borrower.repayInterest = borrower.repayInterest.add(dept); | |
borrower.startTime = now; | |
borrower.principal = paidPrincipal; | |
contractLoans[msg.sender] = borrower; | |
//History | |
History memory history = payHistory[msg.sender][userRound[msg.sender]][lenHistory[msg.sender][userRound[msg.sender]]]; | |
history.amount = paidPrincipal; | |
history.time = borrower.startTime; | |
history.interest = dept; | |
history.end = borrower.startTime; | |
history.active = 1; | |
payHistory[msg.sender][userRound[msg.sender]][lenHistory[msg.sender][userRound[msg.sender]]] = history; | |
RePay(msg.sender, _like, _lock, sumPaid, dept, userRound[msg.sender]); | |
return true; | |
} | |
function checkLiquidate(address _borrower) public view returns (bool) { | |
Loans memory borrower = contractLoans[_borrower]; | |
if(borrower.isActive == statusLoan.ACTIVE && now > borrower.endTime){ | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
function liquidateLoan(address _like, address _borrower) public returns (bool) { | |
Loans memory borrower = contractLoans[_borrower]; | |
require(borrower.isActive == statusLoan.ACTIVE); | |
require(borrower.endTime < now); | |
uint256 dept = borrower.principal; | |
Collateral_Interface(_lock).liquidateCollateral(address(_like), address(_borrower), borrower.collateral, borrower.liquidateCollateral, address(InterestorKeep), borrower.principal); | |
borrower.isActive = statusLoan.INACTIVE; | |
borrower.principal = 0; | |
contractLoans[_borrower] = borrower; | |
History memory history = payHistory[msg.sender][userRound[msg.sender]][lenHistory[msg.sender][userRound[msg.sender]]]; | |
history.amount = 0; | |
history.interest = borrower.liquidateCollateral; | |
history.end = borrower.startTime; | |
history.active = 2; | |
payHistory[msg.sender][userRound[msg.sender]][lenHistory[msg.sender][userRound[msg.sender]]] = history; | |
LiquidateCollateral(_like, _borrower, borrower.liquidateCollateral, address(InterestorKeep), dept); | |
return true; | |
} | |
//contract lock & lending | |
// function calculateInterest() public pure returns (uint256) { | |
// // 1000000000000000000000*50000000000000000/1000000000000000000 | |
// uint256 principal = 1000*10**18; | |
// uint256 ratio = principal.interateRate(5*10**16).div(1000000000000000000); | |
// //5% | |
// ratio = 50000000000000000; | |
// //1000*(1+8/100)**10 | |
// // uint256 interest = priciple.mul(((1*10**18)+ratio)**3); | |
// // uint256 interest = 1000*10**18*(1+8*10**18/100)**3; | |
// // principal = principal.add(ratio.mulDiv(principal, 10^18)); | |
// ratio = ratio/31556952; | |
// ratio = ratio.mul(31556952); | |
// principal = principal.add(ratio.mulDiv(principal, 1000000000000000000)); | |
// return principal; | |
// } | |
function getAPY() public view returns (uint256) { | |
uint256 ratio = interest.div(31556952); | |
uint256 percent = ratio.mul(1 years); | |
return percent; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.11; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) constant returns (uint); | |
function transfer(address to, uint value); | |
event Transfer(address indexed from, address indexed to, uint value); | |
} | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
/** | |
* @dev Fix for the ERC20 short address attack. | |
*/ | |
modifier onlyPayloadSize(uint size) { | |
if(msg.data.length < size + 4) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(msg.sender, _to, _value); | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) constant returns (uint balance) { | |
return balances[_owner]; | |
} | |
} | |
/** | |
* @title ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) constant returns (uint); | |
function transferFrom(address from, address to, uint value); | |
function approve(address spender, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implemantation of the basic standart token. | |
* @dev https://github.com/ethereum/EIPs/issues/20 | |
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
/** | |
* @dev Transfer tokens from one address to another | |
* @param _from address The address which you want to send tokens from | |
* @param _to address The address which you want to transfer to | |
* @param _value uint the amout of tokens to be transfered | |
*/ | |
function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) { | |
var _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met | |
// if (_value > _allowance) throw; | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
Transfer(_from, _to, _value); | |
} | |
/** | |
* @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender. | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint _value) { | |
// To change the approve amount you first have to reduce the addresses` | |
// allowance to zero by calling `approve(_spender, 0)` if it is not | |
// already 0 to mitigate the race condition described here: | |
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
} | |
/** | |
* @dev Function to check the amount of tokens than an owner allowed to a spender. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A uint specifing the amount of tokens still avaible for the spender. | |
*/ | |
function allowance(address _owner, address _spender) constant returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/** | |
* @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; | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
function Ownable() { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
if (msg.sender != owner) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @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 { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
} | |
} | |
} | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 | |
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol | |
*/ | |
contract MintableToken is StandardToken, Ownable { | |
event Mint(address indexed to, uint value); | |
event MintMore(address indexed to, uint value); | |
event BurnToken(address indexed to, uint value); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
uint public totalSupply = 0; | |
modifier canMint() { | |
if(mintingFinished) throw; | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will recieve the minted tokens. | |
* @param _amount The amount of tokens to mint. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) { | |
totalSupply = totalSupply.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
Mint(_to, _amount); | |
return true; | |
} | |
function addMint(uint _amount) onlyOwner returns (bool){ | |
totalSupply = totalSupply.add(_amount); | |
balances[msg.sender] = balances[msg.sender].add(_amount); | |
MintMore(msg.sender, _amount); | |
return true; | |
} | |
function burnToken(uint _amount) returns (bool) { | |
totalSupply = totalSupply.sub(_amount); | |
balances[msg.sender] = balances[msg.sender].sub(_amount); | |
require(balances[msg.sender] >= 0); | |
BurnToken(msg.sender, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() onlyOwner returns (bool) { | |
mintingFinished = true; | |
MintFinished(); | |
return true; | |
} | |
} | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev modifier to allow actions only when the contract IS paused | |
*/ | |
modifier whenNotPaused() { | |
if (paused) throw; | |
_; | |
} | |
/** | |
* @dev modifier to allow actions only when the contract IS NOT paused | |
*/ | |
modifier whenPaused { | |
if (!paused) throw; | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused returns (bool) { | |
paused = true; | |
Pause(); | |
return true; | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused returns (bool) { | |
paused = false; | |
Unpause(); | |
return true; | |
} | |
} | |
/** | |
* Pausable token | |
* | |
* Simple ERC20 Token example, with pausable token creation | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer(address _to, uint _value) whenNotPaused { | |
super.transfer(_to, _value); | |
} | |
function transferFrom(address _from, address _to, uint _value) whenNotPaused { | |
super.transferFrom(_from, _to, _value); | |
} | |
} | |
/** | |
* @title TokenTimelock | |
* @dev TokenTimelock is a token holder contract that will allow a | |
* beneficiary to extract the tokens after a time has passed | |
*/ | |
contract TokenTimelock { | |
// ERC20 basic token contract being held | |
ERC20Basic token; | |
// beneficiary of tokens after they are released | |
address beneficiary; | |
// timestamp where token release is enabled | |
uint releaseTime; | |
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) { | |
require(_releaseTime > now); | |
token = _token; | |
beneficiary = _beneficiary; | |
releaseTime = _releaseTime; | |
} | |
/** | |
* @dev beneficiary claims tokens held by time lock | |
*/ | |
function claim() { | |
require(msg.sender == beneficiary); | |
require(now >= releaseTime); | |
uint amount = token.balanceOf(this); | |
require(amount > 0); | |
token.transfer(beneficiary, amount); | |
} | |
} | |
/** | |
* @title OMGToken | |
* @dev Omise Go Token contract | |
*/ | |
contract PHATCYTOEY is PausableToken, MintableToken { | |
using SafeMath for uint256; | |
string public name = "PHATCY-TOEY"; | |
string public symbol = "PTT"; | |
uint public decimals = 18; | |
/** | |
* @dev mint timelocked tokens | |
*/ | |
function mintTimelocked(address _to, uint256 _amount, uint256 _releaseTime) | |
onlyOwner canMint returns (TokenTimelock) { | |
TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime); | |
mint(timelock, _amount); | |
return timelock; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.6.0; | |
contract GetNumber { | |
address public owner; | |
constructor() public { | |
owner = msg.sender; | |
} | |
uint public number = 0; | |
event InputNumber(address caller, uint _number); | |
function inputNumber(uint _number) public returns (bool){ | |
require(owner == msg.sender); | |
number = _number; | |
emit InputNumber(msg.sender, _number); | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.11; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) constant returns (uint); | |
function transfer(address to, uint value); | |
event Transfer(address indexed from, address indexed to, uint value, uint balances, uint balanceSub, uint status); | |
} | |
/** | |
* @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; | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
function Ownable() { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
if (msg.sender != owner) { | |
throw; | |
} | |
_; | |
} | |
} | |
contract Adminable is Ownable { | |
address[] public admins; | |
address[] adminsPre; | |
uint256 public adminsLength = 0; | |
event adminStatus(address addr, uint256 length); | |
function Adminable() { | |
admins.push(owner); | |
adminsLength = admins.length; | |
} | |
function allAdmins() public view returns (address[]) { | |
return admins; | |
} | |
function addAdmin(address addr) onlyOwner{ | |
if(adminsLength > 0){ | |
uint count = 0; | |
for(uint i = 0; i < adminsLength; i++){ | |
if(admins[i] == addr){ | |
count++; | |
} | |
} | |
if(count == 0){ | |
admins.push(addr); | |
adminsLength = admins.length; | |
adminStatus(addr, adminsLength); | |
} | |
}else{ | |
admins.push(addr); | |
adminsLength = admins.length; | |
adminStatus(addr, adminsLength); | |
} | |
} | |
function removeAdmin(address addr) onlyOwner{ | |
if(adminsLength > 0){ | |
delete adminsPre; | |
for(uint i = 0; i < adminsLength; i++){ | |
if(admins[i] != addr){ | |
adminsPre.push(admins[i]); | |
} | |
} | |
if(admins.length != adminsPre.length){ | |
delete admins; | |
admins = adminsPre; | |
adminsLength = admins.length; | |
adminStatus(addr, adminsLength); | |
}else{ | |
throw; | |
} | |
}else{ | |
throw; | |
} | |
} | |
modifier onlyAdmin() { | |
if(adminsLength > 0){ | |
uint count = 0; | |
for(uint i = 0; i < adminsLength; i++){ | |
if(admins[i] == msg.sender){ | |
count++; | |
} | |
} | |
if(count == 0){ | |
throw; | |
} | |
_; | |
}else{ | |
throw; | |
} | |
} | |
/** | |
* @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 { | |
if (newOwner != address(0)) { | |
addAdmin(newOwner); | |
removeAdmin(owner); | |
owner = newOwner; | |
} | |
} | |
} | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic, Adminable { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
mapping(address => uint) balanceSub; | |
/** | |
* @dev Fix for the ERC20 short address attack. | |
*/ | |
modifier onlyPayloadSize(uint size) { | |
if(msg.data.length < size + 4) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint _value) onlyAdmin onlyPayloadSize(2 * 32) { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(msg.sender, _to, _value, balances[_to], balanceSub[_to], 1); | |
} | |
function addCredit(address _from, address _to, uint _value) onlyAdmin onlyPayloadSize(2 * 32) { | |
if(balanceSub[_to] > 0){ | |
if(balanceSub[_to] > _value){ | |
balanceSub[_to] = balanceSub[_to].sub(_value); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 1); | |
}else{ | |
uint creditAdd = _value.sub(balanceSub[_to]); | |
balanceSub[_to] = balanceSub[_to].sub(balanceSub[_to]); | |
balances[_from] = balances[_from].sub(creditAdd); | |
balances[_to] = balances[_to].add(creditAdd); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 1); | |
} | |
}else{ | |
balances[_from] = balances[_from].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 1); | |
} | |
} | |
function disCredit(address _from, address _to, uint _value) onlyAdmin onlyPayloadSize(2 * 32) { | |
if(balances[_from] > _value){ | |
balances[_from] = balances[_from].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 0); | |
}else{ | |
if(balances[_from] == 0){ | |
balanceSub[_from] = balanceSub[_from].add(_value); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 0); | |
}else{ | |
uint creditDis = _value.sub(balances[_from]); | |
balances[_to] = balances[_to].add(balances[_from]); | |
balances[_from] = balances[_from].sub(balances[_from]); | |
balanceSub[_from] = balanceSub[_from].add(creditDis); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 0); | |
} | |
} | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) constant returns (uint balance) { | |
return balances[_owner]; | |
} | |
function totalBalanceOf(address _owner) constant returns (uint[] totalBalance) { | |
uint[] total; | |
total.push(balances[_owner]); | |
total.push(balanceSub[_owner]); | |
return total; | |
} | |
} | |
/** | |
* @title ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) constant returns (uint); | |
function transferFrom(address from, address to, uint value); | |
function approve(address spender, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implemantation of the basic standart token. | |
* @dev https://github.com/ethereum/EIPs/issues/20 | |
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
/** | |
* @dev Transfer tokens from one address to another | |
* @param _from address The address which you want to send tokens from | |
* @param _to address The address which you want to transfer to | |
* @param _value uint the amout of tokens to be transfered | |
*/ | |
function transferFrom(address _from, address _to, uint _value) onlyAdmin onlyPayloadSize(3 * 32) { | |
var _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met | |
// if (_value > _allowance) throw; | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
Transfer(_from, _to, _value, balances[_to], balanceSub[_to], 1); | |
} | |
/** | |
* @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender. | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint _value) onlyAdmin { | |
// To change the approve amount you first have to reduce the addresses` | |
// allowance to zero by calling `approve(_spender, 0)` if it is not | |
// already 0 to mitigate the race condition described here: | |
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
} | |
/** | |
* @dev Function to check the amount of tokens than an owner allowed to a spender. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A uint specifing the amount of tokens still avaible for the spender. | |
*/ | |
function allowance(address _owner, address _spender) constant returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 | |
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol | |
*/ | |
contract MintableToken is StandardToken { | |
event Mint(address indexed to, uint value); | |
event MintMore(address indexed to, uint value); | |
event BurnToken(address indexed to, uint value); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
uint public totalSupply = 0; | |
modifier canMint() { | |
if(mintingFinished) throw; | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will recieve the minted tokens. | |
* @param _amount The amount of tokens to mint. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) { | |
totalSupply = totalSupply.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
Mint(_to, _amount); | |
return true; | |
} | |
function addMint(uint _amount) onlyOwner returns (bool){ | |
totalSupply = totalSupply.add(_amount); | |
balances[msg.sender] = balances[msg.sender].add(_amount); | |
MintMore(msg.sender, _amount); | |
return true; | |
} | |
function burnToken(uint _amount) onlyOwner returns (bool) { | |
totalSupply = totalSupply.sub(_amount); | |
balances[msg.sender] = balances[msg.sender].sub(_amount); | |
require(balances[msg.sender] >= 0); | |
BurnToken(msg.sender, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() onlyOwner returns (bool) { | |
mintingFinished = true; | |
MintFinished(); | |
return true; | |
} | |
} | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev modifier to allow actions only when the contract IS paused | |
*/ | |
modifier whenNotPaused() { | |
if (paused) throw; | |
_; | |
} | |
/** | |
* @dev modifier to allow actions only when the contract IS NOT paused | |
*/ | |
modifier whenPaused { | |
if (!paused) throw; | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused returns (bool) { | |
paused = true; | |
Pause(); | |
return true; | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused returns (bool) { | |
paused = false; | |
Unpause(); | |
return true; | |
} | |
} | |
/** | |
* Pausable token | |
* | |
* Simple ERC20 Token example, with pausable token creation | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer(address _to, uint _value) whenNotPaused { | |
super.transfer(_to, _value); | |
} | |
function transferFrom(address _from, address _to, uint _value) whenNotPaused { | |
super.transferFrom(_from, _to, _value); | |
} | |
} | |
/** | |
* @title TokenTimelock | |
* @dev TokenTimelock is a token holder contract that will allow a | |
* beneficiary to extract the tokens after a time has passed | |
*/ | |
contract TokenTimelock { | |
// ERC20 basic token contract being held | |
ERC20Basic token; | |
// beneficiary of tokens after they are released | |
address beneficiary; | |
// timestamp where token release is enabled | |
uint releaseTime; | |
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) { | |
require(_releaseTime > now); | |
token = _token; | |
beneficiary = _beneficiary; | |
releaseTime = _releaseTime; | |
} | |
/** | |
* @dev beneficiary claims tokens held by time lock | |
*/ | |
function claim(){ | |
require(msg.sender == beneficiary); | |
require(now >= releaseTime); | |
uint amount = token.balanceOf(this); | |
require(amount > 0); | |
token.transfer(beneficiary, amount); | |
} | |
} | |
/** | |
* @title OMGToken | |
* @dev Omise Go Token contract | |
*/ | |
contract likeCredit is PausableToken, MintableToken { | |
using SafeMath for uint256; | |
string public name = "Like Credit"; | |
string public symbol = "LCDT"; | |
uint public decimals = 18; | |
/** | |
* @dev mint timelocked tokens | |
*/ | |
function mintTimelocked(address _to, uint256 _amount, uint256 _releaseTime) | |
onlyOwner canMint returns (TokenTimelock) { | |
TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime); | |
mint(timelock, _amount); | |
return timelock; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.11; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) constant returns (uint); | |
function transfer(address to, uint value); | |
event Transfer(address indexed from, address indexed to, uint value); | |
} | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
/** | |
* @dev Fix for the ERC20 short address attack. | |
*/ | |
modifier onlyPayloadSize(uint size) { | |
if(msg.data.length < size + 4) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(msg.sender, _to, _value); | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) constant returns (uint balance) { | |
return balances[_owner]; | |
} | |
} | |
/** | |
* @title ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) constant returns (uint); | |
function transferFrom(address from, address to, uint value); | |
function approve(address spender, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implemantation of the basic standart token. | |
* @dev https://github.com/ethereum/EIPs/issues/20 | |
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
/** | |
* @dev Transfer tokens from one address to another | |
* @param _from address The address which you want to send tokens from | |
* @param _to address The address which you want to transfer to | |
* @param _value uint the amout of tokens to be transfered | |
*/ | |
function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) { | |
var _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met | |
// if (_value > _allowance) throw; | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
Transfer(_from, _to, _value); | |
} | |
/** | |
* @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender. | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint _value) { | |
// To change the approve amount you first have to reduce the addresses` | |
// allowance to zero by calling `approve(_spender, 0)` if it is not | |
// already 0 to mitigate the race condition described here: | |
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
} | |
/** | |
* @dev Function to check the amount of tokens than an owner allowed to a spender. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A uint specifing the amount of tokens still avaible for the spender. | |
*/ | |
function allowance(address _owner, address _spender) constant returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/** | |
* @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; | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
function Ownable() { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
if (msg.sender != owner) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @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 { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
} | |
} | |
} | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 | |
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol | |
*/ | |
contract MintableToken is StandardToken, Ownable { | |
event Mint(address indexed to, uint value); | |
event MintMore(address indexed to, uint value); | |
event BurnToken(address indexed to, uint value); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
uint public totalSupply = 0; | |
modifier canMint() { | |
if(mintingFinished) throw; | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will recieve the minted tokens. | |
* @param _amount The amount of tokens to mint. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) { | |
totalSupply = totalSupply.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
Mint(_to, _amount); | |
return true; | |
} | |
function addMint(uint _amount) onlyOwner returns (bool){ | |
totalSupply = totalSupply.add(_amount); | |
balances[msg.sender] = balances[msg.sender].add(_amount); | |
MintMore(msg.sender, _amount); | |
return true; | |
} | |
function burnToken(uint _amount) returns (bool) { | |
totalSupply = totalSupply.sub(_amount); | |
balances[msg.sender] = balances[msg.sender].sub(_amount); | |
require(balances[msg.sender] >= 0); | |
BurnToken(msg.sender, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() onlyOwner returns (bool) { | |
mintingFinished = true; | |
MintFinished(); | |
return true; | |
} | |
} | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev modifier to allow actions only when the contract IS paused | |
*/ | |
modifier whenNotPaused() { | |
if (paused) throw; | |
_; | |
} | |
/** | |
* @dev modifier to allow actions only when the contract IS NOT paused | |
*/ | |
modifier whenPaused { | |
if (!paused) throw; | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused returns (bool) { | |
paused = true; | |
Pause(); | |
return true; | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused returns (bool) { | |
paused = false; | |
Unpause(); | |
return true; | |
} | |
} | |
/** | |
* Pausable token | |
* | |
* Simple ERC20 Token example, with pausable token creation | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer(address _to, uint _value) whenNotPaused { | |
super.transfer(_to, _value); | |
} | |
function transferFrom(address _from, address _to, uint _value) whenNotPaused { | |
super.transferFrom(_from, _to, _value); | |
} | |
} | |
/** | |
* @title TokenTimelock | |
* @dev TokenTimelock is a token holder contract that will allow a | |
* beneficiary to extract the tokens after a time has passed | |
*/ | |
contract TokenTimelock { | |
// ERC20 basic token contract being held | |
ERC20Basic token; | |
// beneficiary of tokens after they are released | |
address beneficiary; | |
// timestamp where token release is enabled | |
uint releaseTime; | |
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) { | |
require(_releaseTime > now); | |
token = _token; | |
beneficiary = _beneficiary; | |
releaseTime = _releaseTime; | |
} | |
/** | |
* @dev beneficiary claims tokens held by time lock | |
*/ | |
function claim() { | |
require(msg.sender == beneficiary); | |
require(now >= releaseTime); | |
uint amount = token.balanceOf(this); | |
require(amount > 0); | |
token.transfer(beneficiary, amount); | |
} | |
} | |
/** | |
* @title OMGToken | |
* @dev Omise Go Token contract | |
*/ | |
contract LIKEPOINT is PausableToken, MintableToken { | |
using SafeMath for uint256; | |
string public name = "LikepointTESTContract"; | |
string public symbol = "LIKET"; | |
uint public decimals = 18; | |
/** | |
* @dev mint timelocked tokens | |
*/ | |
function mintTimelocked(address _to, uint256 _amount, uint256 _releaseTime) | |
onlyOwner canMint returns (TokenTimelock) { | |
TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime); | |
mint(timelock, _amount); | |
return timelock; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract LockERC20 is Ownable{ | |
struct lockToken { | |
address token; | |
uint256 expire; | |
uint256 block; | |
uint256 amount; | |
} | |
using SafeMath for uint; | |
// mapping (address => mapping (address => uint256)) public tokens; | |
mapping (address => mapping(address => lockToken)) public tokens; | |
mapping (address => uint256) public balanceToken; | |
event DepositToken(address contractAddress, address sender, uint256 amount, uint256 expire); | |
event WithdrawToken(address contractAddress, address sender, uint256 amount); | |
event AdminWithdrawToken(address contractAddress, address sender, uint256 amount, string message); | |
function depositToken(address likeAddr, uint amount, uint256 expire) public { | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
tokenData.token = likeAddr; | |
tokenData.expire = now+expire; | |
tokenData.block = block.number; | |
tokenData.amount += amount; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
DepositToken(likeAddr, msg.sender, amount, expire); | |
} | |
function withdrawToken(address likeAddr, uint amount) public { | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(now > tokenData.expire); | |
require(amount <= tokenData.amount); | |
tokenData.amount -= amount; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr]= balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
WithdrawToken(likeAddr, msg.sender, amount); | |
} | |
function getLock(address likeAddr, address _sender) public view returns (uint256){ | |
return tokens[likeAddr][_sender].amount; | |
} | |
function adminWithdrawToken(address likeAddr, uint amount, string message) onlyOwner public { | |
require(amount <= balanceToken[likeAddr]); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
AdminWithdrawToken(likeAddr, msg.sender, amount, message); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract LockERC20 is Ownable{ | |
enum statusWithdraw { | |
INACTIVE, | |
ACTIVE | |
} | |
struct lockToken { | |
address token; | |
uint256 expire; | |
uint256 block; | |
uint256 start; | |
uint256 amount; | |
statusWithdraw isWithdraw; | |
} | |
using SafeMath for uint; | |
// mapping (address => mapping (address => uint256)) public tokens; | |
mapping (address => mapping(address => lockToken)) public tokens; | |
mapping (address => uint256) public balanceToken; | |
uint256 public isExpire = 1 days; | |
event DepositToken(address contractAddress, address sender, uint256 amount, uint256 expire); | |
event WithdrawToken(address contractAddress, address sender, uint256 amount); | |
event AdminWithdrawToken(address contractAddress, address sender, uint256 amount, string message); | |
event RequestWithdraw(address contractAddress, address sender); | |
function setExpire(uint256 expire) onlyOwner public{ | |
isExpire = expire; | |
} | |
function depositToken(address likeAddr, uint amount, uint256 expire) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
tokenData.token = likeAddr; | |
tokenData.expire = now.add(expire); | |
tokenData.block = block.number; | |
tokenData.start = now; | |
tokenData.amount = tokenData.amount.add(amount); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
DepositToken(likeAddr, msg.sender, amount, expire); | |
return true; | |
} | |
function requestWithdraw(address likeAddr) public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(tokenData.isWithdraw == statusWithdraw.INACTIVE); | |
require(tokenData.amount > 0); | |
tokenData.isWithdraw = statusWithdraw.ACTIVE; | |
tokenData.expire = now.add(isExpire); | |
tokens[likeAddr][msg.sender] = tokenData; | |
RequestWithdraw(likeAddr, msg.sender); | |
return true; | |
} | |
function withdrawToken(address likeAddr, uint amount) public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(now > tokenData.expire); | |
require(amount <= tokenData.amount); | |
require(tokenData.isWithdraw == statusWithdraw.ACTIVE); | |
tokenData.amount = tokenData.amount.sub(amount); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr]= balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
WithdrawToken(likeAddr, msg.sender, amount); | |
return true; | |
} | |
function getLock(address likeAddr, address _sender) public view returns (uint256){ | |
return tokens[likeAddr][_sender].amount; | |
} | |
function getWithdraw(address likeAddr, address _sender) public view returns (statusWithdraw) { | |
return tokens[likeAddr][_sender].isWithdraw; | |
} | |
function getAmount(address likeAddr, address _sender) public view returns (uint256) { | |
return tokens[likeAddr][_sender].amount; | |
} | |
function getDepositTime(address likeAddr, address _sender) public view returns (uint256) { | |
return tokens[likeAddr][_sender].start; | |
} | |
function adminWithdrawToken(address likeAddr, uint amount, string message) onlyOwner public { | |
require(amount <= balanceToken[likeAddr]); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
AdminWithdrawToken(likeAddr, msg.sender, amount, message); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
pragma experimental ABIEncoderV2; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
function percent(uint numerator, uint denominator) internal pure returns(uint quotient) { | |
// caution, check safe-to-multiply here | |
uint _numerator = numerator * 10 ** (10); | |
// with rounding of last digit | |
uint _quotient = ((_numerator / denominator)) / 10; | |
return ( _quotient); | |
} | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract LenderOwner is Ownable { | |
address[] public ownerLender; | |
address[] public reserveLender; | |
event transferLenderOwner(address newLenderOwner); | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyLenderOwner() { | |
for(uint256 i=0;i<ownerLender.length;i++){ | |
if(msg.sender == ownerLender[i]){ | |
_; | |
} | |
} | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function updateLenderContract(address newOwner, uint256 number) onlyOwner public { | |
if (newOwner != address(0)) { | |
ownerLender[number] = newOwner; | |
transferLenderOwner(newOwner); | |
} | |
} | |
function addLenderContract(address lenderAddress) onlyOwner public { | |
if(lenderAddress != (address(0))){ | |
ownerLender.push(lenderAddress); | |
} | |
} | |
function removeLenderContract(address _address) onlyOwner public returns (address[]) { | |
for(uint256 i=0;i<ownerLender.length;i++){ | |
reserveLender.push(ownerLender[i]); | |
} | |
for(uint256 v=0;v<reserveLender.length;v++){ | |
if(ownerLender[v] != _address){ | |
ownerLender[v] = reserveLender[v]; | |
} | |
} | |
ownerLender.length--; | |
delete reserveLender; | |
return reserveLender; | |
} | |
function checkAdmin(address checker) onlyLenderOwner public returns (bool){ | |
return true; | |
} | |
function totalLenderContract() public view returns (uint256) { | |
return ownerLender.length; | |
} | |
function listLenderContract() public view returns (address[]) { | |
return ownerLender; | |
} | |
} | |
contract LockERC20 is LenderOwner { | |
enum statusWithdraw { | |
INACTIVE, | |
ACTIVE | |
} | |
enum statusLockTransfer { | |
ACTIVE, | |
INACTIVE | |
} | |
struct lockToken { | |
address token; | |
uint256 expire; | |
uint256 block; | |
uint256 start; | |
uint256 amount; | |
uint256 amountUnlock; | |
statusLockTransfer isTransfer; | |
statusWithdraw isWithdraw; | |
} | |
struct timeLock { | |
address token; | |
uint256 expire; | |
uint256 block; | |
uint256 start; | |
uint256 amount; | |
statusWithdraw isWithdraw; | |
uint256 round; | |
} | |
using SafeMath for uint; | |
// mapping (address => mapping (address => uint256)) public tokens; | |
mapping (address => mapping(address => lockToken)) public tokens; | |
mapping (address => mapping(address => timeLock)) public timelockhold; | |
mapping (address => uint256) public balanceToken; | |
mapping (address => uint256) public activeLock; | |
uint256 public isExpire = 1 days; | |
event DepositToken(address contractAddress, address sender, uint256 amount, uint256 expire); | |
event WithdrawTokenTimeLock(address contractAddress, address sender, uint256 amount); | |
event WithdrawToken(address contractAddress, address sender, uint256 amount, uint256 amountexists); | |
event AdminWithdrawToken(address contractAddress, address sender, uint256 amount, string message); | |
event RequestWithdraw(address contractAddress, address sender); | |
function setExpire(uint256 expire) onlyOwner public{ | |
isExpire = expire; | |
} | |
function depositTimeLock(address likeAddr, address holder, uint amount, uint256 lockto) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
timeLock memory holderLock = timelockhold[likeAddr][holder]; | |
holderLock.token = likeAddr; | |
holderLock.expire = now.add(lockto); | |
holderLock.block = block.number; | |
holderLock.start = now; | |
holderLock.amount = holderLock.amount.add(amount); | |
holderLock.isWithdraw = statusWithdraw.INACTIVE; | |
timelockhold[likeAddr][holder] = holderLock; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].add(amount); | |
DepositToken(likeAddr, msg.sender, amount, lockto); | |
return true; | |
} | |
function withdrawTimeLock(address likeAddr, uint amount) public returns (bool){ | |
timeLock memory holderLock = timelockhold[likeAddr][msg.sender]; | |
require(now > holderLock.expire); | |
require(amount <= holderLock.amount); | |
holderLock.amount = holderLock.amount.sub(amount); | |
timelockhold[likeAddr][msg.sender] = holderLock; | |
balanceToken[likeAddr]= balanceToken[likeAddr].sub(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
WithdrawTokenTimeLock(likeAddr, msg.sender, amount); | |
return true; | |
} | |
function depositToken(address likeAddr, uint amount, uint256 expire) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
//เช็คว่าปลดล็อคไว้หรือไม่ | |
if(tokenData.isWithdraw == statusWithdraw.ACTIVE) { | |
activeLock[likeAddr] = activeLock[likeAddr].add(tokenData.amount); | |
} | |
tokenData.token = likeAddr; | |
tokenData.expire = now.add(expire); | |
tokenData.block = block.number; | |
tokenData.start = now; | |
tokenData.amount = tokenData.amount.add(amount); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].add(amount); | |
DepositToken(likeAddr, msg.sender, amount, expire); | |
return true; | |
} | |
function depositTokenByAdmin(address likeAddr, address recev, uint amount, uint256 expire) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
lockToken memory tokenData = tokens[likeAddr][recev]; | |
//เช็คว่าปลดล็อคไว้หรือ | |
if(tokenData.isWithdraw == statusWithdraw.ACTIVE) { | |
activeLock[likeAddr] = activeLock[likeAddr].add(tokenData.amount); | |
} | |
tokenData.token = likeAddr; | |
tokenData.expire = now.add(expire); | |
tokenData.block = block.number; | |
tokenData.start = now; | |
tokenData.amount = tokenData.amount.add(amount); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][recev] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].add(amount); | |
DepositToken(likeAddr, recev, amount, expire); | |
return true; | |
} | |
function requestWithdraw(address likeAddr, uint256 amount) public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(tokenData.isWithdraw == statusWithdraw.INACTIVE); | |
require(tokenData.isTransfer == statusLockTransfer.ACTIVE); | |
require(tokenData.amount >= amount); | |
tokenData.isWithdraw = statusWithdraw.ACTIVE; | |
tokenData.expire = now.add(isExpire); | |
tokenData.amountUnlock = amount; | |
tokens[likeAddr][msg.sender] = tokenData; | |
activeLock[likeAddr] = activeLock[likeAddr].sub(tokenData.amount); | |
RequestWithdraw(likeAddr, msg.sender); | |
return true; | |
} | |
function withdrawToken(address likeAddr) public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(now > tokenData.expire); | |
require(tokenData.amountUnlock <= tokenData.amount); | |
require(tokenData.isWithdraw == statusWithdraw.ACTIVE); | |
require(tokenData.isTransfer == statusLockTransfer.ACTIVE); | |
if(tokenData.amountUnlock < tokenData.amount){ | |
uint256 updateAmount = tokenData.amount.sub(tokenData.amountUnlock); | |
activeLock[likeAddr] = activeLock[likeAddr].add(updateAmount); | |
} | |
tokenData.amount = tokenData.amount.sub(tokenData.amountUnlock); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr]= balanceToken[likeAddr].sub(tokenData.amountUnlock); | |
ERC20_Interface(likeAddr).transfer(msg.sender, tokenData.amountUnlock); | |
WithdrawToken(likeAddr, msg.sender, tokenData.amountUnlock, updateAmount); | |
return true; | |
} | |
function getTransfer(address likeAddr, address _sender) public view returns (statusLockTransfer) { | |
return tokens[likeAddr][_sender].isTransfer; | |
} | |
function getLock(address likeAddr, address _sender) public view returns (uint256){ | |
return tokens[likeAddr][_sender].amount; | |
} | |
function getAmountAll(address likeAddr, address _sender) public view returns (uint256){ | |
return tokens[likeAddr][_sender].amount+timelockhold[likeAddr][_sender].amount; | |
} | |
function getWithdraw(address likeAddr, address _sender) public view returns (statusWithdraw) { | |
return tokens[likeAddr][_sender].isWithdraw; | |
} | |
function getAmount(address likeAddr, address _sender) public view returns (uint256) { | |
return tokens[likeAddr][_sender].amount; | |
} | |
function getDepositTime(address likeAddr, address _sender) public view returns (uint256) { | |
return tokens[likeAddr][_sender].start; | |
} | |
function adminWithdrawToken(address likeAddr, uint amount, string message) onlyOwner public { | |
require(amount <= balanceToken[likeAddr]); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
AdminWithdrawToken(likeAddr, msg.sender, amount, message); | |
} | |
function getActiveLock(address likeAddr) public view returns (uint256) { | |
return activeLock[likeAddr]; | |
} | |
} | |
contract Lending is LockERC20 { | |
event TransferWithdrawFund(address contractAddress, address sender, uint256 amount); | |
event TransferDepositFund(address contractAddress, address sender, uint256 amount); | |
event LiquidateCollateral(address likeAddr, address borrower, uint256 fullcollateral, uint256 collateral, address liquidator, uint256 dept); | |
mapping (address => uint256) public balanceLending; | |
function adminClearBlacklist(address likeAddr, address borrower) onlyOwner public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][borrower]; | |
tokenData.isTransfer = statusLockTransfer.ACTIVE; | |
tokens[likeAddr][borrower] = tokenData; | |
return true; | |
} | |
function transferWithdrawFund(address likeAddr, address borrower, uint amount) onlyLenderOwner public returns (bool) { | |
//decrease balance of borrower | |
lockToken memory tokenData = tokens[likeAddr][borrower]; | |
tokenData.amount = tokenData.amount.sub(amount); | |
tokenData.isTransfer = statusLockTransfer.INACTIVE; | |
tokens[likeAddr][borrower] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(amount); | |
balanceLending[likeAddr] = balanceLending[likeAddr].add(amount); | |
ERC20_Interface(likeAddr).transfer(borrower, amount); | |
TransferWithdrawFund(likeAddr, borrower, amount); | |
return true; | |
} | |
function transferDepositFund(address likeAddr, address borrower, uint amount, uint canTransfer) onlyLenderOwner public returns (bool) { | |
//increase balance of borrower | |
lockToken memory tokenData = tokens[likeAddr][borrower]; | |
tokenData.amount = tokenData.amount.add(amount); | |
if(canTransfer == 1){ | |
tokenData.isTransfer = statusLockTransfer.ACTIVE; | |
} | |
tokens[likeAddr][borrower] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
balanceLending[likeAddr] = balanceLending[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transferFrom(borrower, address(this), amount); | |
TransferWithdrawFund(likeAddr, borrower, amount); | |
return true; | |
} | |
function liquidateCollateral(address likeAddr, address borrower, uint256 collateral, uint256 liquidate, address liquidator, uint256 dept) onlyLenderOwner public returns (bool) { | |
lockToken memory tokenData = tokens[likeAddr][borrower]; | |
if(tokenData.amount < collateral) { | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(dept); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(collateral); | |
activeLock[likeAddr] = activeLock[likeAddr].sub(collateral); | |
tokenData.amount = 0; | |
balanceLending[likeAddr] = balanceLending[likeAddr].sub(dept); | |
ERC20_Interface(address(likeAddr)).transfer(address(liquidator), liquidate); | |
}else{ | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(dept); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(collateral); | |
tokenData.amount = tokenData.amount.sub(collateral); | |
activeLock[likeAddr] = activeLock[likeAddr].sub(collateral); | |
balanceLending[likeAddr] = balanceLending[likeAddr].sub(dept); | |
ERC20_Interface(likeAddr).transfer(liquidator, liquidate); | |
} | |
tokenData.isTransfer = statusLockTransfer.ACTIVE; | |
tokens[likeAddr][borrower] = tokenData; | |
LiquidateCollateral(likeAddr, borrower, collateral ,liquidate, liquidator, dept); | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract LockERC20 is Ownable{ | |
enum statusWithdraw { | |
INACTIVE, | |
ACTIVE | |
} | |
struct lockToken { | |
address token; | |
uint256 expire; | |
uint256 block; | |
uint256 start; | |
uint256 amount; | |
statusWithdraw isWithdraw; | |
} | |
struct timeLock { | |
address token; | |
uint256 expire; | |
uint256 block; | |
uint256 start; | |
uint256 amount; | |
statusWithdraw isWithdraw; | |
uint256 round; | |
} | |
using SafeMath for uint; | |
// mapping (address => mapping (address => uint256)) public tokens; | |
mapping (address => mapping(address => lockToken)) public tokens; | |
mapping (address => mapping(address => timeLock)) public timelockhold; | |
mapping (address => uint256) public balanceToken; | |
mapping (address => uint256) public activeLock; | |
uint256 public isExpire = 1 days; | |
event DepositToken(address contractAddress, address sender, uint256 amount, uint256 expire); | |
event WithdrawToken(address contractAddress, address sender, uint256 amount); | |
event AdminWithdrawToken(address contractAddress, address sender, uint256 amount, string message); | |
event RequestWithdraw(address contractAddress, address sender); | |
function setExpire(uint256 expire) onlyOwner public{ | |
isExpire = expire; | |
} | |
function depositTimeLock(address likeAddr, address holder, uint amount, uint256 lockto) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
timeLock memory holderLock = timelockhold[likeAddr][holder]; | |
holderLock.token = likeAddr; | |
holderLock.expire = now.add(lockto); | |
holderLock.block = block.number; | |
holderLock.start = now; | |
holderLock.amount = holderLock.amount.add(amount); | |
holderLock.isWithdraw = statusWithdraw.INACTIVE; | |
timelockhold[likeAddr][holder] = holderLock; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].add(amount); | |
DepositToken(likeAddr, msg.sender, amount, lockto); | |
return true; | |
} | |
function withdrawTimeLock(address likeAddr, uint amount) public returns (bool){ | |
timeLock memory holderLock = timelockhold[likeAddr][msg.sender]; | |
require(now > holderLock.expire); | |
require(amount <= holderLock.amount); | |
holderLock.amount = holderLock.amount.sub(amount); | |
timelockhold[likeAddr][msg.sender] = holderLock; | |
balanceToken[likeAddr]= balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
WithdrawToken(likeAddr, msg.sender, amount); | |
return true; | |
} | |
function depositToken(address likeAddr, uint amount, uint256 expire) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
tokenData.token = likeAddr; | |
tokenData.expire = now.add(expire); | |
tokenData.block = block.number; | |
tokenData.start = now; | |
tokenData.amount = tokenData.amount.add(amount); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].add(amount); | |
DepositToken(likeAddr, msg.sender, amount, expire); | |
return true; | |
} | |
function requestWithdraw(address likeAddr) public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(tokenData.isWithdraw == statusWithdraw.INACTIVE); | |
require(tokenData.amount > 0); | |
tokenData.isWithdraw = statusWithdraw.ACTIVE; | |
tokenData.expire = now.add(isExpire); | |
tokens[likeAddr][msg.sender] = tokenData; | |
activeLock[likeAddr] = activeLock[likeAddr].sub(tokenData.amount); | |
RequestWithdraw(likeAddr, msg.sender); | |
return true; | |
} | |
function withdrawToken(address likeAddr, uint amount) public returns (bool){ | |
lockToken memory tokenData = tokens[likeAddr][msg.sender]; | |
require(now > tokenData.expire); | |
require(amount <= tokenData.amount); | |
require(tokenData.isWithdraw == statusWithdraw.ACTIVE); | |
if(amount < tokenData.amount){ | |
uint256 updateAmount = tokenData.amount.sub(amount); | |
activeLock[likeAddr] = activeLock[likeAddr].add(updateAmount); | |
} | |
tokenData.amount = tokenData.amount.sub(amount); | |
tokenData.isWithdraw = statusWithdraw.INACTIVE; | |
tokens[likeAddr][msg.sender] = tokenData; | |
balanceToken[likeAddr]= balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
WithdrawToken(likeAddr, msg.sender, amount); | |
return true; | |
} | |
function getLock(address likeAddr, address _sender) public view returns (uint256){ | |
return tokens[likeAddr][_sender].amount; | |
} | |
function getWithdraw(address likeAddr, address _sender) public view returns (statusWithdraw) { | |
return tokens[likeAddr][_sender].isWithdraw; | |
} | |
function getAmount(address likeAddr, address _sender) public view returns (uint256) { | |
return tokens[likeAddr][_sender].amount; | |
} | |
function getDepositTime(address likeAddr, address _sender) public view returns (uint256) { | |
return tokens[likeAddr][_sender].start; | |
} | |
function adminWithdrawToken(address likeAddr, uint amount, string message) onlyOwner public { | |
require(amount <= balanceToken[likeAddr]); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
AdminWithdrawToken(likeAddr, msg.sender, amount, message); | |
} | |
function getActiveLock(address likeAddr) public view returns (uint256) { | |
return activeLock[likeAddr]; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*Submitted for verification at Etherscan.io on 2020-08-26 | |
*/ | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.5.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call.value(amount)(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call.value(weiValue)(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @title SafeERC20 | |
* @dev Wrappers around ERC20 operations that throw on failure (when the token | |
* contract returns false). Tokens that return no value (and instead revert or | |
* throw on failure) are also supported, non-reverting calls are assumed to be | |
* successful. | |
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, | |
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc. | |
*/ | |
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)); | |
} | |
/** | |
* @dev Deprecated. This function has issues similar to the ones found in | |
* {IERC20-approve}, and its usage is discouraged. | |
* | |
* Whenever possible, use {safeIncreaseAllowance} and | |
* {safeDecreaseAllowance} instead. | |
*/ | |
function safeApprove(IERC20 token, address spender, uint256 value) internal { | |
// safeApprove should only be called when setting an initial allowance, | |
// or when resetting it to zero. To increase and decrease it, use | |
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance' | |
// solhint-disable-next-line max-line-length | |
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)); | |
} | |
/** | |
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement | |
* on the return value: the return value is optional (but if data is returned, it must not be false). | |
* @param token The token targeted by the call. | |
* @param data The call data (encoded using abi.encode or one of its variants). | |
*/ | |
function _callOptionalReturn(IERC20 token, bytes memory data) private { | |
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since | |
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that | |
// the target address contains contract code and also asserts for success in the low-level call. | |
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/utils/EnumerableSet.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Library for managing | |
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive | |
* types. | |
* | |
* Sets have the following properties: | |
* | |
* - Elements are added, removed, and checked for existence in constant time | |
* (O(1)). | |
* - Elements are enumerated in O(n). No guarantees are made on the ordering. | |
* | |
* ``` | |
* contract Example { | |
* // Add the library methods | |
* using EnumerableSet for EnumerableSet.AddressSet; | |
* | |
* // Declare a set state variable | |
* EnumerableSet.AddressSet private mySet; | |
* } | |
* ``` | |
* | |
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` | |
* (`UintSet`) are supported. | |
*/ | |
library EnumerableSet { | |
// To implement this library for multiple types with as little code | |
// repetition as possible, we write it in terms of a generic Set type with | |
// bytes32 values. | |
// The Set implementation uses private functions, and user-facing | |
// implementations (such as AddressSet) are just wrappers around the | |
// underlying Set. | |
// This means that we can only create new EnumerableSets for types that fit | |
// in bytes32. | |
struct Set { | |
// Storage of set values | |
bytes32[] _values; | |
// Position of the value in the `values` array, plus 1 because index 0 | |
// means a value is not in the set. | |
mapping (bytes32 => uint256) _indexes; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function _add(Set storage set, bytes32 value) private returns (bool) { | |
if (!_contains(set, value)) { | |
set._values.push(value); | |
// The value is stored at length-1, but we add 1 to all indexes | |
// and use 0 as a sentinel value | |
set._indexes[value] = set._values.length; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function _remove(Set storage set, bytes32 value) private returns (bool) { | |
// We read and store the value's index to prevent multiple reads from the same storage slot | |
uint256 valueIndex = set._indexes[value]; | |
if (valueIndex != 0) { // Equivalent to contains(set, value) | |
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in | |
// the array, and then remove the last element (sometimes called as 'swap and pop'). | |
// This modifies the order of the array, as noted in {at}. | |
uint256 toDeleteIndex = valueIndex - 1; | |
uint256 lastIndex = set._values.length - 1; | |
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs | |
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. | |
bytes32 lastvalue = set._values[lastIndex]; | |
// Move the last value to the index where the value to delete is | |
set._values[toDeleteIndex] = lastvalue; | |
// Update the index for the moved value | |
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based | |
// Delete the slot where the moved value was stored | |
set._values.pop(); | |
// Delete the index for the deleted slot | |
delete set._indexes[value]; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function _contains(Set storage set, bytes32 value) private view returns (bool) { | |
return set._indexes[value] != 0; | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function _length(Set storage set) private view returns (uint256) { | |
return set._values.length; | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function _at(Set storage set, uint256 index) private view returns (bytes32) { | |
require(set._values.length > index, "EnumerableSet: index out of bounds"); | |
return set._values[index]; | |
} | |
// AddressSet | |
struct AddressSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(AddressSet storage set, address value) internal returns (bool) { | |
return _add(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(AddressSet storage set, address value) internal returns (bool) { | |
return _remove(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(AddressSet storage set, address value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns the number of values in the set. O(1). | |
*/ | |
function length(AddressSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(AddressSet storage set, uint256 index) internal view returns (address) { | |
return address(uint256(_at(set._inner, index))); | |
} | |
// UintSet | |
struct UintSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(UintSet storage set, uint256 value) internal returns (bool) { | |
return _add(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(UintSet storage set, uint256 value) internal returns (bool) { | |
return _remove(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(UintSet storage set, uint256 value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function length(UintSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(UintSet storage set, uint256 index) internal view returns (uint256) { | |
return uint256(_at(set._inner, index)); | |
} | |
} | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
pragma solidity ^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. | |
*/ | |
contract Context { | |
function _msgSender() internal view returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
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. | |
*/ | |
function renounceOwnership() public onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal { } | |
} | |
// File: contracts/SushiToken.sol | |
pragma solidity ^0.5.0; | |
// SushiToken with Governance. | |
contract WhaleToken is ERC20("WhaleToken", "WHALE"), Ownable { | |
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef). | |
function mint(address _to, uint256 _amount) public onlyOwner { | |
_mint(_to, _amount); | |
_moveDelegates(address(0), _delegates[_to], _amount); | |
} | |
// Copied and modified from YAM code: | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol | |
// Which is copied and modified from COMPOUND: | |
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol | |
/// @notice A record of each accounts delegate | |
mapping (address => address) internal _delegates; | |
/// @notice A checkpoint for marking number of votes from a given block | |
struct Checkpoint { | |
uint32 fromBlock; | |
uint256 votes; | |
} | |
/// @notice A record of votes checkpoints for each account, by index | |
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; | |
/// @notice The number of checkpoints for each account | |
mapping (address => uint32) public numCheckpoints; | |
/// @notice The EIP-712 typehash for the contract's domain | |
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); | |
/// @notice The EIP-712 typehash for the delegation struct used by the contract | |
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | |
/// @notice A record of states for signing / validating signatures | |
mapping (address => uint) public nonces; | |
/// @notice An event thats emitted when an account changes its delegate | |
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); | |
/// @notice An event thats emitted when a delegate account's vote balance changes | |
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegator The address to get delegatee for | |
*/ | |
function delegates(address delegator) | |
external | |
view | |
returns (address) | |
{ | |
return _delegates[delegator]; | |
} | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegatee The address to delegate votes to | |
*/ | |
function delegate(address delegatee) external { | |
return _delegate(msg.sender, delegatee); | |
} | |
/** | |
* @notice Delegates votes from signatory to `delegatee` | |
* @param delegatee The address to delegate votes to | |
* @param nonce The contract state required to match the signature | |
* @param expiry The time at which to expire the signature | |
* @param v The recovery byte of the signature | |
* @param r Half of the ECDSA signature pair | |
* @param s Half of the ECDSA signature pair | |
*/ | |
function delegateBySig( | |
address delegatee, | |
uint nonce, | |
uint expiry, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
external | |
{ | |
bytes32 domainSeparator = keccak256( | |
abi.encode( | |
DOMAIN_TYPEHASH, | |
keccak256(bytes(name())), | |
1, | |
address(this) | |
) | |
); | |
bytes32 structHash = keccak256( | |
abi.encode( | |
DELEGATION_TYPEHASH, | |
delegatee, | |
nonce, | |
expiry | |
) | |
); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
domainSeparator, | |
structHash | |
) | |
); | |
address signatory = ecrecover(digest, v, r, s); | |
require(signatory != address(0), "SUSHI::delegateBySig: invalid signature"); | |
require(nonce == nonces[signatory]++, "SUSHI::delegateBySig: invalid nonce"); | |
require(now <= expiry, "SUSHI::delegateBySig: signature expired"); | |
return _delegate(signatory, delegatee); | |
} | |
/** | |
* @notice Gets the current votes balance for `account` | |
* @param account The address to get votes balance | |
* @return The number of current votes for `account` | |
*/ | |
function getCurrentVotes(address account) | |
external | |
view | |
returns (uint256) | |
{ | |
uint32 nCheckpoints = numCheckpoints[account]; | |
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; | |
} | |
/** | |
* @notice Determine the prior number of votes for an account as of a block number | |
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | |
* @param account The address of the account to check | |
* @param blockNumber The block number to get the vote balance at | |
* @return The number of votes the account had as of the given block | |
*/ | |
function getPriorVotes(address account, uint blockNumber) | |
external | |
view | |
returns (uint256) | |
{ | |
require(blockNumber < block.number, "SUSHI::getPriorVotes: not yet determined"); | |
uint32 nCheckpoints = numCheckpoints[account]; | |
if (nCheckpoints == 0) { | |
return 0; | |
} | |
// First check most recent balance | |
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { | |
return checkpoints[account][nCheckpoints - 1].votes; | |
} | |
// Next check implicit zero balance | |
if (checkpoints[account][0].fromBlock > blockNumber) { | |
return 0; | |
} | |
uint32 lower = 0; | |
uint32 upper = nCheckpoints - 1; | |
while (upper > lower) { | |
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow | |
Checkpoint memory cp = checkpoints[account][center]; | |
if (cp.fromBlock == blockNumber) { | |
return cp.votes; | |
} else if (cp.fromBlock < blockNumber) { | |
lower = center; | |
} else { | |
upper = center - 1; | |
} | |
} | |
return checkpoints[account][lower].votes; | |
} | |
function _delegate(address delegator, address delegatee) | |
internal | |
{ | |
address currentDelegate = _delegates[delegator]; | |
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying SUSHIs (not scaled); | |
_delegates[delegator] = delegatee; | |
emit DelegateChanged(delegator, currentDelegate, delegatee); | |
_moveDelegates(currentDelegate, delegatee, delegatorBalance); | |
} | |
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { | |
if (srcRep != dstRep && amount > 0) { | |
if (srcRep != address(0)) { | |
// decrease old representative | |
uint32 srcRepNum = numCheckpoints[srcRep]; | |
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; | |
uint256 srcRepNew = srcRepOld.sub(amount); | |
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); | |
} | |
if (dstRep != address(0)) { | |
// increase new representative | |
uint32 dstRepNum = numCheckpoints[dstRep]; | |
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; | |
uint256 dstRepNew = dstRepOld.add(amount); | |
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); | |
} | |
} | |
} | |
function _writeCheckpoint( | |
address delegatee, | |
uint32 nCheckpoints, | |
uint256 oldVotes, | |
uint256 newVotes | |
) | |
internal | |
{ | |
uint32 blockNumber = safe32(block.number, "SUSHI::_writeCheckpoint: block number exceeds 32 bits"); | |
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { | |
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; | |
} else { | |
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); | |
numCheckpoints[delegatee] = nCheckpoints + 1; | |
} | |
emit DelegateVotesChanged(delegatee, oldVotes, newVotes); | |
} | |
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { | |
require(n < 2**32, errorMessage); | |
return uint32(n); | |
} | |
} | |
// File: contracts/MasterChef.sol | |
pragma solidity ^0.5.0; | |
interface IMigratorChef { | |
// Perform LP token migration from legacy UniswapV2 to SushiSwap. | |
// Take the current LP token address and return the new LP token address. | |
// Migrator should have full access to the caller's LP token. | |
// Return the new LP token address. | |
// | |
// XXX Migrator must have allowance access to UniswapV2 LP tokens. | |
// SushiSwap must mint EXACTLY the same amount of SushiSwap LP tokens or | |
// else something bad will happen. Traditional UniswapV2 does not | |
// do that so be careful! | |
function migrate(IERC20 token) external returns (IERC20); | |
} | |
// MasterChef is the master of Sushi. He can make Sushi and he is a fair guy. | |
// | |
// Note that it's ownable and the owner wields tremendous power. The ownership | |
// will be transferred to a governance smart contract once SUSHI is sufficiently | |
// distributed and the community can show to govern itself. | |
// | |
// Have fun reading it. Hopefully it's bug-free. God bless. | |
contract MasterChef is Ownable { | |
using SafeMath for uint256; | |
using SafeERC20 for IERC20; | |
// Info of each user. | |
struct UserInfo { | |
uint256 amount; // How many LP tokens the user has provided. | |
uint256 rewardDebt; // Reward debt. See explanation below. | |
// | |
// We do some fancy math here. Basically, any point in time, the amount of SUSHIs | |
// entitled to a user but is pending to be distributed is: | |
// | |
// pending reward = (user.amount * pool.accSushiPerShare) - user.rewardDebt | |
// | |
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: | |
// 1. The pool's `accSushiPerShare` (and `lastRewardBlock`) gets updated. | |
// 2. User receives the pending reward sent to his/her address. | |
// 3. User's `amount` gets updated. | |
// 4. User's `rewardDebt` gets updated. | |
} | |
// Info of each pool. | |
struct PoolInfo { | |
IERC20 lpToken; // Address of LP token contract. | |
uint256 allocPoint; // How many allocation points assigned to this pool. SUSHIs to distribute per block. | |
uint256 lastRewardBlock; // Last block number that SUSHIs distribution occurs. | |
uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below. | |
} | |
// The SUSHI TOKEN! | |
WhaleToken public whale; | |
// Dev address. | |
address public devaddr; | |
// Block number when bonus SUSHI period ends. | |
uint256 public bonusEndBlock; | |
// SUSHI tokens created per block. | |
uint256 public sushiPerBlock; | |
// Bonus muliplier for early sushi makers. | |
uint256 public constant BONUS_MULTIPLIER = 10; | |
// The migrator contract. It has a lot of power. Can only be set through governance (owner). | |
IMigratorChef public migrator; | |
// Info of each pool. | |
PoolInfo[] public poolInfo; | |
// Info of each user that stakes LP tokens. | |
mapping (uint256 => mapping (address => UserInfo)) public userInfo; | |
// Total allocation poitns. Must be the sum of all allocation points in all pools. | |
uint256 public totalAllocPoint = 0; | |
// The block number when SUSHI mining starts. | |
uint256 public startBlock; | |
event Deposit(address indexed user, uint256 indexed pid, uint256 amount); | |
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); | |
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); | |
constructor( | |
WhaleToken _sushi, | |
address _devaddr, | |
uint256 _sushiPerBlock, | |
uint256 _startBlock, | |
uint256 _bonusEndBlock | |
) public { | |
whale = _sushi; | |
devaddr = _devaddr; | |
sushiPerBlock = _sushiPerBlock; | |
bonusEndBlock = _bonusEndBlock; | |
startBlock = _startBlock; | |
} | |
function poolLength() external view returns (uint256) { | |
return poolInfo.length; | |
} | |
// Add a new lp to the pool. Can only be called by the owner. | |
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. | |
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner { | |
if (_withUpdate) { | |
massUpdatePools(); | |
} | |
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock; | |
totalAllocPoint = totalAllocPoint.add(_allocPoint); | |
poolInfo.push(PoolInfo({ | |
lpToken: _lpToken, | |
allocPoint: _allocPoint, | |
lastRewardBlock: lastRewardBlock, | |
accSushiPerShare: 0 | |
})); | |
} | |
// Update the given pool's SUSHI allocation point. Can only be called by the owner. | |
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { | |
if (_withUpdate) { | |
massUpdatePools(); | |
} | |
totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint); | |
poolInfo[_pid].allocPoint = _allocPoint; | |
} | |
// Set the migrator contract. Can only be called by the owner. | |
function setMigrator(IMigratorChef _migrator) public onlyOwner { | |
migrator = _migrator; | |
} | |
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. | |
function migrate(uint256 _pid) public { | |
require(address(migrator) != address(0), "migrate: no migrator"); | |
PoolInfo storage pool = poolInfo[_pid]; | |
IERC20 lpToken = pool.lpToken; | |
uint256 bal = lpToken.balanceOf(address(this)); | |
lpToken.safeApprove(address(migrator), bal); | |
IERC20 newLpToken = migrator.migrate(lpToken); | |
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); | |
pool.lpToken = newLpToken; | |
} | |
// Return reward multiplier over the given _from to _to block. | |
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { | |
if (_to <= bonusEndBlock) { | |
return _to.sub(_from).mul(BONUS_MULTIPLIER); | |
} else if (_from >= bonusEndBlock) { | |
return _to.sub(_from); | |
} else { | |
return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add( | |
_to.sub(bonusEndBlock) | |
); | |
} | |
} | |
// View function to see pending SUSHIs on frontend. | |
function pendingSushi(uint256 _pid, address _user) external view returns (uint256) { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][_user]; | |
uint256 accSushiPerShare = pool.accSushiPerShare; | |
uint256 lpSupply = pool.lpToken.balanceOf(address(this)); | |
if (block.number > pool.lastRewardBlock && lpSupply != 0) { | |
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); | |
uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint); | |
accSushiPerShare = accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply)); | |
} | |
return user.amount.mul(accSushiPerShare).div(1e12).sub(user.rewardDebt); | |
} | |
// Update reward vairables for all pools. Be careful of gas spending! | |
function massUpdatePools() public { | |
uint256 length = poolInfo.length; | |
for (uint256 pid = 0; pid < length; ++pid) { | |
updatePool(pid); | |
} | |
} | |
// Update reward variables of the given pool to be up-to-date. | |
function updatePool(uint256 _pid) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
if (block.number <= pool.lastRewardBlock) { | |
return; | |
} | |
uint256 lpSupply = pool.lpToken.balanceOf(address(this)); | |
if (lpSupply == 0) { | |
pool.lastRewardBlock = block.number; | |
return; | |
} | |
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); | |
uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint); | |
whale.mint(devaddr, sushiReward.div(10)); | |
whale.mint(address(this), sushiReward); | |
pool.accSushiPerShare = pool.accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply)); | |
pool.lastRewardBlock = block.number; | |
} | |
// Deposit LP tokens to MasterChef for SUSHI allocation. | |
function deposit(uint256 _pid, uint256 _amount) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
updatePool(_pid); | |
if (user.amount > 0) { | |
uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt); | |
safeSushiTransfer(msg.sender, pending); | |
} | |
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); | |
user.amount = user.amount.add(_amount); | |
user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12); | |
emit Deposit(msg.sender, _pid, _amount); | |
} | |
// Withdraw LP tokens from MasterChef. | |
function withdraw(uint256 _pid, uint256 _amount) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
require(user.amount >= _amount, "withdraw: not good"); | |
updatePool(_pid); | |
uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt); | |
safeSushiTransfer(msg.sender, pending); | |
user.amount = user.amount.sub(_amount); | |
user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12); | |
pool.lpToken.safeTransfer(address(msg.sender), _amount); | |
emit Withdraw(msg.sender, _pid, _amount); | |
} | |
// Withdraw without caring about rewards. EMERGENCY ONLY. | |
function emergencyWithdraw(uint256 _pid) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
pool.lpToken.safeTransfer(address(msg.sender), user.amount); | |
emit EmergencyWithdraw(msg.sender, _pid, user.amount); | |
user.amount = 0; | |
user.rewardDebt = 0; | |
} | |
// Safe sushi transfer function, just in case if rounding error causes pool to not have enough SUSHIs. | |
function safeSushiTransfer(address _to, uint256 _amount) internal { | |
uint256 sushiBal = whale.balanceOf(address(this)); | |
if (_amount > sushiBal) { | |
whale.transfer(_to, sushiBal); | |
} else { | |
whale.transfer(_to, _amount); | |
} | |
} | |
// Update dev address by the previous dev. | |
function dev(address _devaddr) public { | |
require(msg.sender == devaddr, "dev: wut?"); | |
devaddr = _devaddr; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this line is added to create a gist. Empty file is not allowed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// this line is added to create a gist. Empty file is not allowed. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.26; | |
contract HashLock { | |
bytes32 public hashLock = 0x9f923544d86886be7465067ebb1d1287d6ea9adb6bf73b985964f6021b08f838; | |
function () payable public{} | |
function claim(string _WhatIsTheMagicKey) public { | |
require(sha256(abi.encodePacked(_WhatIsTheMagicKey)) == hashLock); | |
selfdestruct(msg.sender); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*Submitted for verification at Etherscan.io on 2020-08-26 | |
*/ | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
pragma solidity ^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. | |
*/ | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.6.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: contracts/SushiToken.sol | |
pragma solidity 0.6.12; | |
// SushiToken with Governance. | |
contract SushiToken is ERC20("SushiToken", "SUSHI"), Ownable { | |
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef). | |
function mint(address _to, uint256 _amount) public onlyOwner { | |
_mint(_to, _amount); | |
_moveDelegates(address(0), _delegates[_to], _amount); | |
} | |
// Copied and modified from YAM code: | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol | |
// Which is copied and modified from COMPOUND: | |
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol | |
/// @notice A record of each accounts delegate | |
mapping (address => address) internal _delegates; | |
/// @notice A checkpoint for marking number of votes from a given block | |
struct Checkpoint { | |
uint32 fromBlock; | |
uint256 votes; | |
} | |
/// @notice A record of votes checkpoints for each account, by index | |
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; | |
/// @notice The number of checkpoints for each account | |
mapping (address => uint32) public numCheckpoints; | |
/// @notice The EIP-712 typehash for the contract's domain | |
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); | |
/// @notice The EIP-712 typehash for the delegation struct used by the contract | |
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | |
/// @notice A record of states for signing / validating signatures | |
mapping (address => uint) public nonces; | |
/// @notice An event thats emitted when an account changes its delegate | |
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); | |
/// @notice An event thats emitted when a delegate account's vote balance changes | |
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegator The address to get delegatee for | |
*/ | |
function delegates(address delegator) | |
external | |
view | |
returns (address) | |
{ | |
return _delegates[delegator]; | |
} | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegatee The address to delegate votes to | |
*/ | |
function delegate(address delegatee) external { | |
return _delegate(msg.sender, delegatee); | |
} | |
/** | |
* @notice Delegates votes from signatory to `delegatee` | |
* @param delegatee The address to delegate votes to | |
* @param nonce The contract state required to match the signature | |
* @param expiry The time at which to expire the signature | |
* @param v The recovery byte of the signature | |
* @param r Half of the ECDSA signature pair | |
* @param s Half of the ECDSA signature pair | |
*/ | |
function delegateBySig( | |
address delegatee, | |
uint nonce, | |
uint expiry, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
external | |
{ | |
bytes32 domainSeparator = keccak256( | |
abi.encode( | |
DOMAIN_TYPEHASH, | |
keccak256(bytes(name())), | |
getChainId(), | |
address(this) | |
) | |
); | |
bytes32 structHash = keccak256( | |
abi.encode( | |
DELEGATION_TYPEHASH, | |
delegatee, | |
nonce, | |
expiry | |
) | |
); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
domainSeparator, | |
structHash | |
) | |
); | |
address signatory = ecrecover(digest, v, r, s); | |
require(signatory != address(0), "SUSHI::delegateBySig: invalid signature"); | |
require(nonce == nonces[signatory]++, "SUSHI::delegateBySig: invalid nonce"); | |
require(now <= expiry, "SUSHI::delegateBySig: signature expired"); | |
return _delegate(signatory, delegatee); | |
} | |
/** | |
* @notice Gets the current votes balance for `account` | |
* @param account The address to get votes balance | |
* @return The number of current votes for `account` | |
*/ | |
function getCurrentVotes(address account) | |
external | |
view | |
returns (uint256) | |
{ | |
uint32 nCheckpoints = numCheckpoints[account]; | |
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; | |
} | |
/** | |
* @notice Determine the prior number of votes for an account as of a block number | |
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | |
* @param account The address of the account to check | |
* @param blockNumber The block number to get the vote balance at | |
* @return The number of votes the account had as of the given block | |
*/ | |
function getPriorVotes(address account, uint blockNumber) | |
external | |
view | |
returns (uint256) | |
{ | |
require(blockNumber < block.number, "SUSHI::getPriorVotes: not yet determined"); | |
uint32 nCheckpoints = numCheckpoints[account]; | |
if (nCheckpoints == 0) { | |
return 0; | |
} | |
// First check most recent balance | |
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { | |
return checkpoints[account][nCheckpoints - 1].votes; | |
} | |
// Next check implicit zero balance | |
if (checkpoints[account][0].fromBlock > blockNumber) { | |
return 0; | |
} | |
uint32 lower = 0; | |
uint32 upper = nCheckpoints - 1; | |
while (upper > lower) { | |
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow | |
Checkpoint memory cp = checkpoints[account][center]; | |
if (cp.fromBlock == blockNumber) { | |
return cp.votes; | |
} else if (cp.fromBlock < blockNumber) { | |
lower = center; | |
} else { | |
upper = center - 1; | |
} | |
} | |
return checkpoints[account][lower].votes; | |
} | |
function _delegate(address delegator, address delegatee) | |
internal | |
{ | |
address currentDelegate = _delegates[delegator]; | |
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying SUSHIs (not scaled); | |
_delegates[delegator] = delegatee; | |
emit DelegateChanged(delegator, currentDelegate, delegatee); | |
_moveDelegates(currentDelegate, delegatee, delegatorBalance); | |
} | |
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { | |
if (srcRep != dstRep && amount > 0) { | |
if (srcRep != address(0)) { | |
// decrease old representative | |
uint32 srcRepNum = numCheckpoints[srcRep]; | |
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; | |
uint256 srcRepNew = srcRepOld.sub(amount); | |
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); | |
} | |
if (dstRep != address(0)) { | |
// increase new representative | |
uint32 dstRepNum = numCheckpoints[dstRep]; | |
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; | |
uint256 dstRepNew = dstRepOld.add(amount); | |
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); | |
} | |
} | |
} | |
function _writeCheckpoint( | |
address delegatee, | |
uint32 nCheckpoints, | |
uint256 oldVotes, | |
uint256 newVotes | |
) | |
internal | |
{ | |
uint32 blockNumber = safe32(block.number, "SUSHI::_writeCheckpoint: block number exceeds 32 bits"); | |
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { | |
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; | |
} else { | |
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); | |
numCheckpoints[delegatee] = nCheckpoints + 1; | |
} | |
emit DelegateVotesChanged(delegatee, oldVotes, newVotes); | |
} | |
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { | |
require(n < 2**32, errorMessage); | |
return uint32(n); | |
} | |
function getChainId() internal pure returns (uint) { | |
uint256 chainId; | |
assembly { chainId := chainid() } | |
return chainId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*Submitted for verification at Etherscan.io on 2020-08-26 | |
*/ | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.6.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @title SafeERC20 | |
* @dev Wrappers around ERC20 operations that throw on failure (when the token | |
* contract returns false). Tokens that return no value (and instead revert or | |
* throw on failure) are also supported, non-reverting calls are assumed to be | |
* successful. | |
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, | |
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc. | |
*/ | |
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)); | |
} | |
/** | |
* @dev Deprecated. This function has issues similar to the ones found in | |
* {IERC20-approve}, and its usage is discouraged. | |
* | |
* Whenever possible, use {safeIncreaseAllowance} and | |
* {safeDecreaseAllowance} instead. | |
*/ | |
function safeApprove(IERC20 token, address spender, uint256 value) internal { | |
// safeApprove should only be called when setting an initial allowance, | |
// or when resetting it to zero. To increase and decrease it, use | |
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance' | |
// solhint-disable-next-line max-line-length | |
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)); | |
} | |
/** | |
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement | |
* on the return value: the return value is optional (but if data is returned, it must not be false). | |
* @param token The token targeted by the call. | |
* @param data The call data (encoded using abi.encode or one of its variants). | |
*/ | |
function _callOptionalReturn(IERC20 token, bytes memory data) private { | |
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since | |
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that | |
// the target address contains contract code and also asserts for success in the low-level call. | |
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); | |
if (returndata.length > 0) { // Return data is optional | |
// solhint-disable-next-line max-line-length | |
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/utils/EnumerableSet.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Library for managing | |
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive | |
* types. | |
* | |
* Sets have the following properties: | |
* | |
* - Elements are added, removed, and checked for existence in constant time | |
* (O(1)). | |
* - Elements are enumerated in O(n). No guarantees are made on the ordering. | |
* | |
* ``` | |
* contract Example { | |
* // Add the library methods | |
* using EnumerableSet for EnumerableSet.AddressSet; | |
* | |
* // Declare a set state variable | |
* EnumerableSet.AddressSet private mySet; | |
* } | |
* ``` | |
* | |
* As of v3.0.0, only sets of type `address` (`AddressSet`) and `uint256` | |
* (`UintSet`) are supported. | |
*/ | |
library EnumerableSet { | |
// To implement this library for multiple types with as little code | |
// repetition as possible, we write it in terms of a generic Set type with | |
// bytes32 values. | |
// The Set implementation uses private functions, and user-facing | |
// implementations (such as AddressSet) are just wrappers around the | |
// underlying Set. | |
// This means that we can only create new EnumerableSets for types that fit | |
// in bytes32. | |
struct Set { | |
// Storage of set values | |
bytes32[] _values; | |
// Position of the value in the `values` array, plus 1 because index 0 | |
// means a value is not in the set. | |
mapping (bytes32 => uint256) _indexes; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function _add(Set storage set, bytes32 value) private returns (bool) { | |
if (!_contains(set, value)) { | |
set._values.push(value); | |
// The value is stored at length-1, but we add 1 to all indexes | |
// and use 0 as a sentinel value | |
set._indexes[value] = set._values.length; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function _remove(Set storage set, bytes32 value) private returns (bool) { | |
// We read and store the value's index to prevent multiple reads from the same storage slot | |
uint256 valueIndex = set._indexes[value]; | |
if (valueIndex != 0) { // Equivalent to contains(set, value) | |
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in | |
// the array, and then remove the last element (sometimes called as 'swap and pop'). | |
// This modifies the order of the array, as noted in {at}. | |
uint256 toDeleteIndex = valueIndex - 1; | |
uint256 lastIndex = set._values.length - 1; | |
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs | |
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. | |
bytes32 lastvalue = set._values[lastIndex]; | |
// Move the last value to the index where the value to delete is | |
set._values[toDeleteIndex] = lastvalue; | |
// Update the index for the moved value | |
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based | |
// Delete the slot where the moved value was stored | |
set._values.pop(); | |
// Delete the index for the deleted slot | |
delete set._indexes[value]; | |
return true; | |
} else { | |
return false; | |
} | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function _contains(Set storage set, bytes32 value) private view returns (bool) { | |
return set._indexes[value] != 0; | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function _length(Set storage set) private view returns (uint256) { | |
return set._values.length; | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function _at(Set storage set, uint256 index) private view returns (bytes32) { | |
require(set._values.length > index, "EnumerableSet: index out of bounds"); | |
return set._values[index]; | |
} | |
// AddressSet | |
struct AddressSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(AddressSet storage set, address value) internal returns (bool) { | |
return _add(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(AddressSet storage set, address value) internal returns (bool) { | |
return _remove(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(AddressSet storage set, address value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(uint256(value))); | |
} | |
/** | |
* @dev Returns the number of values in the set. O(1). | |
*/ | |
function length(AddressSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(AddressSet storage set, uint256 index) internal view returns (address) { | |
return address(uint256(_at(set._inner, index))); | |
} | |
// UintSet | |
struct UintSet { | |
Set _inner; | |
} | |
/** | |
* @dev Add a value to a set. O(1). | |
* | |
* Returns true if the value was added to the set, that is if it was not | |
* already present. | |
*/ | |
function add(UintSet storage set, uint256 value) internal returns (bool) { | |
return _add(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Removes a value from a set. O(1). | |
* | |
* Returns true if the value was removed from the set, that is if it was | |
* present. | |
*/ | |
function remove(UintSet storage set, uint256 value) internal returns (bool) { | |
return _remove(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns true if the value is in the set. O(1). | |
*/ | |
function contains(UintSet storage set, uint256 value) internal view returns (bool) { | |
return _contains(set._inner, bytes32(value)); | |
} | |
/** | |
* @dev Returns the number of values on the set. O(1). | |
*/ | |
function length(UintSet storage set) internal view returns (uint256) { | |
return _length(set._inner); | |
} | |
/** | |
* @dev Returns the value stored at position `index` in the set. O(1). | |
* | |
* Note that there are no guarantees on the ordering of values inside the | |
* array, and it may change when more values are added or removed. | |
* | |
* Requirements: | |
* | |
* - `index` must be strictly less than {length}. | |
*/ | |
function at(UintSet storage set, uint256 index) internal view returns (uint256) { | |
return uint256(_at(set._inner, index)); | |
} | |
} | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
pragma solidity ^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. | |
*/ | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
// File: contracts/SushiToken.sol | |
pragma solidity 0.6.12; | |
// SushiToken with Governance. | |
contract SushiToken is ERC20("SushiToken", "SUSHI"), Ownable { | |
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef). | |
function mint(address _to, uint256 _amount) public onlyOwner { | |
_mint(_to, _amount); | |
_moveDelegates(address(0), _delegates[_to], _amount); | |
} | |
// Copied and modified from YAM code: | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol | |
// Which is copied and modified from COMPOUND: | |
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol | |
/// @notice A record of each accounts delegate | |
mapping (address => address) internal _delegates; | |
/// @notice A checkpoint for marking number of votes from a given block | |
struct Checkpoint { | |
uint32 fromBlock; | |
uint256 votes; | |
} | |
/// @notice A record of votes checkpoints for each account, by index | |
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; | |
/// @notice The number of checkpoints for each account | |
mapping (address => uint32) public numCheckpoints; | |
/// @notice The EIP-712 typehash for the contract's domain | |
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); | |
/// @notice The EIP-712 typehash for the delegation struct used by the contract | |
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | |
/// @notice A record of states for signing / validating signatures | |
mapping (address => uint) public nonces; | |
/// @notice An event thats emitted when an account changes its delegate | |
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); | |
/// @notice An event thats emitted when a delegate account's vote balance changes | |
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegator The address to get delegatee for | |
*/ | |
function delegates(address delegator) | |
external | |
view | |
returns (address) | |
{ | |
return _delegates[delegator]; | |
} | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegatee The address to delegate votes to | |
*/ | |
function delegate(address delegatee) external { | |
return _delegate(msg.sender, delegatee); | |
} | |
/** | |
* @notice Delegates votes from signatory to `delegatee` | |
* @param delegatee The address to delegate votes to | |
* @param nonce The contract state required to match the signature | |
* @param expiry The time at which to expire the signature | |
* @param v The recovery byte of the signature | |
* @param r Half of the ECDSA signature pair | |
* @param s Half of the ECDSA signature pair | |
*/ | |
function delegateBySig( | |
address delegatee, | |
uint nonce, | |
uint expiry, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
external | |
{ | |
bytes32 domainSeparator = keccak256( | |
abi.encode( | |
DOMAIN_TYPEHASH, | |
keccak256(bytes(name())), | |
getChainId(), | |
address(this) | |
) | |
); | |
bytes32 structHash = keccak256( | |
abi.encode( | |
DELEGATION_TYPEHASH, | |
delegatee, | |
nonce, | |
expiry | |
) | |
); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
domainSeparator, | |
structHash | |
) | |
); | |
address signatory = ecrecover(digest, v, r, s); | |
require(signatory != address(0), "SUSHI::delegateBySig: invalid signature"); | |
require(nonce == nonces[signatory]++, "SUSHI::delegateBySig: invalid nonce"); | |
require(now <= expiry, "SUSHI::delegateBySig: signature expired"); | |
return _delegate(signatory, delegatee); | |
} | |
/** | |
* @notice Gets the current votes balance for `account` | |
* @param account The address to get votes balance | |
* @return The number of current votes for `account` | |
*/ | |
function getCurrentVotes(address account) | |
external | |
view | |
returns (uint256) | |
{ | |
uint32 nCheckpoints = numCheckpoints[account]; | |
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; | |
} | |
/** | |
* @notice Determine the prior number of votes for an account as of a block number | |
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | |
* @param account The address of the account to check | |
* @param blockNumber The block number to get the vote balance at | |
* @return The number of votes the account had as of the given block | |
*/ | |
function getPriorVotes(address account, uint blockNumber) | |
external | |
view | |
returns (uint256) | |
{ | |
require(blockNumber < block.number, "SUSHI::getPriorVotes: not yet determined"); | |
uint32 nCheckpoints = numCheckpoints[account]; | |
if (nCheckpoints == 0) { | |
return 0; | |
} | |
// First check most recent balance | |
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { | |
return checkpoints[account][nCheckpoints - 1].votes; | |
} | |
// Next check implicit zero balance | |
if (checkpoints[account][0].fromBlock > blockNumber) { | |
return 0; | |
} | |
uint32 lower = 0; | |
uint32 upper = nCheckpoints - 1; | |
while (upper > lower) { | |
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow | |
Checkpoint memory cp = checkpoints[account][center]; | |
if (cp.fromBlock == blockNumber) { | |
return cp.votes; | |
} else if (cp.fromBlock < blockNumber) { | |
lower = center; | |
} else { | |
upper = center - 1; | |
} | |
} | |
return checkpoints[account][lower].votes; | |
} | |
function _delegate(address delegator, address delegatee) | |
internal | |
{ | |
address currentDelegate = _delegates[delegator]; | |
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying SUSHIs (not scaled); | |
_delegates[delegator] = delegatee; | |
emit DelegateChanged(delegator, currentDelegate, delegatee); | |
_moveDelegates(currentDelegate, delegatee, delegatorBalance); | |
} | |
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { | |
if (srcRep != dstRep && amount > 0) { | |
if (srcRep != address(0)) { | |
// decrease old representative | |
uint32 srcRepNum = numCheckpoints[srcRep]; | |
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; | |
uint256 srcRepNew = srcRepOld.sub(amount); | |
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); | |
} | |
if (dstRep != address(0)) { | |
// increase new representative | |
uint32 dstRepNum = numCheckpoints[dstRep]; | |
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; | |
uint256 dstRepNew = dstRepOld.add(amount); | |
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); | |
} | |
} | |
} | |
function _writeCheckpoint( | |
address delegatee, | |
uint32 nCheckpoints, | |
uint256 oldVotes, | |
uint256 newVotes | |
) | |
internal | |
{ | |
uint32 blockNumber = safe32(block.number, "SUSHI::_writeCheckpoint: block number exceeds 32 bits"); | |
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { | |
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; | |
} else { | |
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); | |
numCheckpoints[delegatee] = nCheckpoints + 1; | |
} | |
emit DelegateVotesChanged(delegatee, oldVotes, newVotes); | |
} | |
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { | |
require(n < 2**32, errorMessage); | |
return uint32(n); | |
} | |
function getChainId() internal pure returns (uint) { | |
uint256 chainId; | |
assembly { chainId := chainid() } | |
return chainId; | |
} | |
} | |
// File: contracts/MasterChef.sol | |
pragma solidity 0.6.12; | |
interface IMigratorChef { | |
// Perform LP token migration from legacy UniswapV2 to SushiSwap. | |
// Take the current LP token address and return the new LP token address. | |
// Migrator should have full access to the caller's LP token. | |
// Return the new LP token address. | |
// | |
// XXX Migrator must have allowance access to UniswapV2 LP tokens. | |
// SushiSwap must mint EXACTLY the same amount of SushiSwap LP tokens or | |
// else something bad will happen. Traditional UniswapV2 does not | |
// do that so be careful! | |
function migrate(IERC20 token) external returns (IERC20); | |
} | |
// MasterChef is the master of Sushi. He can make Sushi and he is a fair guy. | |
// | |
// Note that it's ownable and the owner wields tremendous power. The ownership | |
// will be transferred to a governance smart contract once SUSHI is sufficiently | |
// distributed and the community can show to govern itself. | |
// | |
// Have fun reading it. Hopefully it's bug-free. God bless. | |
contract MasterChef is Ownable { | |
using SafeMath for uint256; | |
using SafeERC20 for IERC20; | |
// Info of each user. | |
struct UserInfo { | |
uint256 amount; // How many LP tokens the user has provided. | |
uint256 rewardDebt; // Reward debt. See explanation below. | |
// | |
// We do some fancy math here. Basically, any point in time, the amount of SUSHIs | |
// entitled to a user but is pending to be distributed is: | |
// | |
// pending reward = (user.amount * pool.accSushiPerShare) - user.rewardDebt | |
// | |
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: | |
// 1. The pool's `accSushiPerShare` (and `lastRewardBlock`) gets updated. | |
// 2. User receives the pending reward sent to his/her address. | |
// 3. User's `amount` gets updated. | |
// 4. User's `rewardDebt` gets updated. | |
} | |
// Info of each pool. | |
struct PoolInfo { | |
IERC20 lpToken; // Address of LP token contract. | |
uint256 allocPoint; // How many allocation points assigned to this pool. SUSHIs to distribute per block. | |
uint256 lastRewardBlock; // Last block number that SUSHIs distribution occurs. | |
uint256 accSushiPerShare; // Accumulated SUSHIs per share, times 1e12. See below. | |
} | |
// The SUSHI TOKEN! | |
SushiToken public sushi; | |
// Dev address. | |
address public devaddr; | |
// Block number when bonus SUSHI period ends. | |
uint256 public bonusEndBlock; | |
// SUSHI tokens created per block. | |
uint256 public sushiPerBlock; | |
// Bonus muliplier for early sushi makers. | |
uint256 public constant BONUS_MULTIPLIER = 10; | |
// The migrator contract. It has a lot of power. Can only be set through governance (owner). | |
IMigratorChef public migrator; | |
// Info of each pool. | |
PoolInfo[] public poolInfo; | |
// Info of each user that stakes LP tokens. | |
mapping (uint256 => mapping (address => UserInfo)) public userInfo; | |
// Total allocation poitns. Must be the sum of all allocation points in all pools. | |
uint256 public totalAllocPoint = 0; | |
// The block number when SUSHI mining starts. | |
uint256 public startBlock; | |
event Deposit(address indexed user, uint256 indexed pid, uint256 amount); | |
event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); | |
event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount); | |
constructor( | |
SushiToken _sushi, | |
address _devaddr, | |
uint256 _sushiPerBlock, | |
uint256 _startBlock, | |
uint256 _bonusEndBlock | |
) public { | |
sushi = _sushi; | |
devaddr = _devaddr; | |
sushiPerBlock = _sushiPerBlock; | |
bonusEndBlock = _bonusEndBlock; | |
startBlock = _startBlock; | |
} | |
function poolLength() external view returns (uint256) { | |
return poolInfo.length; | |
} | |
// Add a new lp to the pool. Can only be called by the owner. | |
// XXX DO NOT add the same LP token more than once. Rewards will be messed up if you do. | |
function add(uint256 _allocPoint, IERC20 _lpToken, bool _withUpdate) public onlyOwner { | |
if (_withUpdate) { | |
massUpdatePools(); | |
} | |
uint256 lastRewardBlock = block.number > startBlock ? block.number : startBlock; | |
totalAllocPoint = totalAllocPoint.add(_allocPoint); | |
poolInfo.push(PoolInfo({ | |
lpToken: _lpToken, | |
allocPoint: _allocPoint, | |
lastRewardBlock: lastRewardBlock, | |
accSushiPerShare: 0 | |
})); | |
} | |
// Update the given pool's SUSHI allocation point. Can only be called by the owner. | |
function set(uint256 _pid, uint256 _allocPoint, bool _withUpdate) public onlyOwner { | |
if (_withUpdate) { | |
massUpdatePools(); | |
} | |
totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint); | |
poolInfo[_pid].allocPoint = _allocPoint; | |
} | |
// Set the migrator contract. Can only be called by the owner. | |
function setMigrator(IMigratorChef _migrator) public onlyOwner { | |
migrator = _migrator; | |
} | |
// Migrate lp token to another lp contract. Can be called by anyone. We trust that migrator contract is good. | |
function migrate(uint256 _pid) public { | |
require(address(migrator) != address(0), "migrate: no migrator"); | |
PoolInfo storage pool = poolInfo[_pid]; | |
IERC20 lpToken = pool.lpToken; | |
uint256 bal = lpToken.balanceOf(address(this)); | |
lpToken.safeApprove(address(migrator), bal); | |
IERC20 newLpToken = migrator.migrate(lpToken); | |
require(bal == newLpToken.balanceOf(address(this)), "migrate: bad"); | |
pool.lpToken = newLpToken; | |
} | |
// Return reward multiplier over the given _from to _to block. | |
function getMultiplier(uint256 _from, uint256 _to) public view returns (uint256) { | |
if (_to <= bonusEndBlock) { | |
return _to.sub(_from).mul(BONUS_MULTIPLIER); | |
} else if (_from >= bonusEndBlock) { | |
return _to.sub(_from); | |
} else { | |
return bonusEndBlock.sub(_from).mul(BONUS_MULTIPLIER).add( | |
_to.sub(bonusEndBlock) | |
); | |
} | |
} | |
// View function to see pending SUSHIs on frontend. | |
function pendingSushi(uint256 _pid, address _user) external view returns (uint256) { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][_user]; | |
uint256 accSushiPerShare = pool.accSushiPerShare; | |
uint256 lpSupply = pool.lpToken.balanceOf(address(this)); | |
if (block.number > pool.lastRewardBlock && lpSupply != 0) { | |
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); | |
uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint); | |
accSushiPerShare = accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply)); | |
} | |
return user.amount.mul(accSushiPerShare).div(1e12).sub(user.rewardDebt); | |
} | |
// Update reward vairables for all pools. Be careful of gas spending! | |
function massUpdatePools() public { | |
uint256 length = poolInfo.length; | |
for (uint256 pid = 0; pid < length; ++pid) { | |
updatePool(pid); | |
} | |
} | |
// Update reward variables of the given pool to be up-to-date. | |
function updatePool(uint256 _pid) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
if (block.number <= pool.lastRewardBlock) { | |
return; | |
} | |
uint256 lpSupply = pool.lpToken.balanceOf(address(this)); | |
if (lpSupply == 0) { | |
pool.lastRewardBlock = block.number; | |
return; | |
} | |
uint256 multiplier = getMultiplier(pool.lastRewardBlock, block.number); | |
uint256 sushiReward = multiplier.mul(sushiPerBlock).mul(pool.allocPoint).div(totalAllocPoint); | |
sushi.mint(devaddr, sushiReward.div(10)); | |
sushi.mint(address(this), sushiReward); | |
pool.accSushiPerShare = pool.accSushiPerShare.add(sushiReward.mul(1e12).div(lpSupply)); | |
pool.lastRewardBlock = block.number; | |
} | |
// Deposit LP tokens to MasterChef for SUSHI allocation. | |
function deposit(uint256 _pid, uint256 _amount) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
updatePool(_pid); | |
if (user.amount > 0) { | |
uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt); | |
safeSushiTransfer(msg.sender, pending); | |
} | |
pool.lpToken.safeTransferFrom(address(msg.sender), address(this), _amount); | |
user.amount = user.amount.add(_amount); | |
user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12); | |
emit Deposit(msg.sender, _pid, _amount); | |
} | |
// Withdraw LP tokens from MasterChef. | |
function withdraw(uint256 _pid, uint256 _amount) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
require(user.amount >= _amount, "withdraw: not good"); | |
updatePool(_pid); | |
uint256 pending = user.amount.mul(pool.accSushiPerShare).div(1e12).sub(user.rewardDebt); | |
safeSushiTransfer(msg.sender, pending); | |
user.amount = user.amount.sub(_amount); | |
user.rewardDebt = user.amount.mul(pool.accSushiPerShare).div(1e12); | |
pool.lpToken.safeTransfer(address(msg.sender), _amount); | |
emit Withdraw(msg.sender, _pid, _amount); | |
} | |
// Withdraw without caring about rewards. EMERGENCY ONLY. | |
function emergencyWithdraw(uint256 _pid) public { | |
PoolInfo storage pool = poolInfo[_pid]; | |
UserInfo storage user = userInfo[_pid][msg.sender]; | |
pool.lpToken.safeTransfer(address(msg.sender), user.amount); | |
emit EmergencyWithdraw(msg.sender, _pid, user.amount); | |
user.amount = 0; | |
user.rewardDebt = 0; | |
} | |
// Safe sushi transfer function, just in case if rounding error causes pool to not have enough SUSHIs. | |
function safeSushiTransfer(address _to, uint256 _amount) internal { | |
uint256 sushiBal = sushi.balanceOf(address(this)); | |
if (_amount > sushiBal) { | |
sushi.transfer(_to, sushiBal); | |
} else { | |
sushi.transfer(_to, _amount); | |
} | |
} | |
// Update dev address by the previous dev. | |
function dev(address _devaddr) public { | |
require(msg.sender == devaddr, "dev: wut?"); | |
devaddr = _devaddr; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*Submitted for verification at Etherscan.io on 2020-08-26 | |
*/ | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
pragma solidity ^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. | |
*/ | |
contract Context { | |
function _msgSender() internal view returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.5.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call.value(amount)(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call.value(weiValue)(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal { } | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
pragma solidity ^0.5.0; | |
/** | |
* @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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
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. | |
*/ | |
function renounceOwnership() public onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: contracts/SushiToken.sol | |
pragma solidity ^0.5.0; | |
// SushiToken with Governance. | |
contract WhaleToken is ERC20("WhaleToken", "WHALE"), Ownable { | |
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef). | |
function mint(address _to, uint256 _amount) public onlyOwner { | |
_mint(_to, _amount); | |
_moveDelegates(address(0), _delegates[_to], _amount); | |
} | |
// Copied and modified from YAM code: | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol | |
// Which is copied and modified from COMPOUND: | |
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol | |
/// @notice A record of each accounts delegate | |
mapping (address => address) internal _delegates; | |
/// @notice A checkpoint for marking number of votes from a given block | |
struct Checkpoint { | |
uint32 fromBlock; | |
uint256 votes; | |
} | |
/// @notice A record of votes checkpoints for each account, by index | |
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; | |
/// @notice The number of checkpoints for each account | |
mapping (address => uint32) public numCheckpoints; | |
/// @notice The EIP-712 typehash for the contract's domain | |
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); | |
/// @notice The EIP-712 typehash for the delegation struct used by the contract | |
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | |
/// @notice A record of states for signing / validating signatures | |
mapping (address => uint) public nonces; | |
/// @notice An event thats emitted when an account changes its delegate | |
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); | |
/// @notice An event thats emitted when a delegate account's vote balance changes | |
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegator The address to get delegatee for | |
*/ | |
function delegates(address delegator) | |
external | |
view | |
returns (address) | |
{ | |
return _delegates[delegator]; | |
} | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegatee The address to delegate votes to | |
*/ | |
function delegate(address delegatee) external { | |
return _delegate(msg.sender, delegatee); | |
} | |
/** | |
* @notice Delegates votes from signatory to `delegatee` | |
* @param delegatee The address to delegate votes to | |
* @param nonce The contract state required to match the signature | |
* @param expiry The time at which to expire the signature | |
* @param v The recovery byte of the signature | |
* @param r Half of the ECDSA signature pair | |
* @param s Half of the ECDSA signature pair | |
*/ | |
function delegateBySig( | |
address delegatee, | |
uint nonce, | |
uint expiry, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
external | |
{ | |
bytes32 domainSeparator = keccak256( | |
abi.encode( | |
DOMAIN_TYPEHASH, | |
keccak256(bytes(name())), | |
1, | |
address(this) | |
) | |
); | |
bytes32 structHash = keccak256( | |
abi.encode( | |
DELEGATION_TYPEHASH, | |
delegatee, | |
nonce, | |
expiry | |
) | |
); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
domainSeparator, | |
structHash | |
) | |
); | |
address signatory = ecrecover(digest, v, r, s); | |
require(signatory != address(0), "SUSHI::delegateBySig: invalid signature"); | |
require(nonce == nonces[signatory]++, "SUSHI::delegateBySig: invalid nonce"); | |
require(now <= expiry, "SUSHI::delegateBySig: signature expired"); | |
return _delegate(signatory, delegatee); | |
} | |
/** | |
* @notice Gets the current votes balance for `account` | |
* @param account The address to get votes balance | |
* @return The number of current votes for `account` | |
*/ | |
function getCurrentVotes(address account) | |
external | |
view | |
returns (uint256) | |
{ | |
uint32 nCheckpoints = numCheckpoints[account]; | |
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; | |
} | |
/** | |
* @notice Determine the prior number of votes for an account as of a block number | |
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | |
* @param account The address of the account to check | |
* @param blockNumber The block number to get the vote balance at | |
* @return The number of votes the account had as of the given block | |
*/ | |
function getPriorVotes(address account, uint blockNumber) | |
external | |
view | |
returns (uint256) | |
{ | |
require(blockNumber < block.number, "SUSHI::getPriorVotes: not yet determined"); | |
uint32 nCheckpoints = numCheckpoints[account]; | |
if (nCheckpoints == 0) { | |
return 0; | |
} | |
// First check most recent balance | |
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { | |
return checkpoints[account][nCheckpoints - 1].votes; | |
} | |
// Next check implicit zero balance | |
if (checkpoints[account][0].fromBlock > blockNumber) { | |
return 0; | |
} | |
uint32 lower = 0; | |
uint32 upper = nCheckpoints - 1; | |
while (upper > lower) { | |
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow | |
Checkpoint memory cp = checkpoints[account][center]; | |
if (cp.fromBlock == blockNumber) { | |
return cp.votes; | |
} else if (cp.fromBlock < blockNumber) { | |
lower = center; | |
} else { | |
upper = center - 1; | |
} | |
} | |
return checkpoints[account][lower].votes; | |
} | |
function _delegate(address delegator, address delegatee) | |
internal | |
{ | |
address currentDelegate = _delegates[delegator]; | |
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying SUSHIs (not scaled); | |
_delegates[delegator] = delegatee; | |
emit DelegateChanged(delegator, currentDelegate, delegatee); | |
_moveDelegates(currentDelegate, delegatee, delegatorBalance); | |
} | |
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { | |
if (srcRep != dstRep && amount > 0) { | |
if (srcRep != address(0)) { | |
// decrease old representative | |
uint32 srcRepNum = numCheckpoints[srcRep]; | |
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; | |
uint256 srcRepNew = srcRepOld.sub(amount); | |
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); | |
} | |
if (dstRep != address(0)) { | |
// increase new representative | |
uint32 dstRepNum = numCheckpoints[dstRep]; | |
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; | |
uint256 dstRepNew = dstRepOld.add(amount); | |
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); | |
} | |
} | |
} | |
function _writeCheckpoint( | |
address delegatee, | |
uint32 nCheckpoints, | |
uint256 oldVotes, | |
uint256 newVotes | |
) | |
internal | |
{ | |
uint32 blockNumber = safe32(block.number, "SUSHI::_writeCheckpoint: block number exceeds 32 bits"); | |
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { | |
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; | |
} else { | |
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); | |
numCheckpoints[delegatee] = nCheckpoints + 1; | |
} | |
emit DelegateVotesChanged(delegatee, oldVotes, newVotes); | |
} | |
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { | |
require(n < 2**32, errorMessage); | |
return uint32(n); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.0 <0.6.0; | |
import "remix_tests.sol"; // this import is automatically injected by Remix. | |
// file name has to end with '_test.sol' | |
contract test_1 { | |
function beforeAll() public { | |
// here should instantiate tested contract | |
Assert.equal(uint(4), uint(3), "error in before all function"); | |
} | |
function check1() public { | |
// use 'Assert' to test the contract | |
Assert.equal(uint(2), uint(1), "error message"); | |
Assert.equal(uint(2), uint(2), "error message"); | |
} | |
function check2() public view returns (bool) { | |
// use the return value (true or false) to test the contract | |
return true; | |
} | |
} | |
contract test_2 { | |
function beforeAll() public { | |
// here should instantiate tested contract | |
Assert.equal(uint(4), uint(3), "error in before all function"); | |
} | |
function check1() public { | |
// use 'Assert' to test the contract | |
Assert.equal(uint(2), uint(1), "error message"); | |
Assert.equal(uint(2), uint(2), "error message"); | |
} | |
function check2() public view returns (bool) { | |
// use the return value (true or false) to test the contract | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.0 <0.6.0; | |
import "remix_tests.sol"; // this import is automatically injected by Remix. | |
// file name has to end with '_test.sol' | |
contract test_1 { | |
function beforeAll() public { | |
// here should instantiate tested contract | |
Assert.equal(uint(4), uint(3), "error in before all function"); | |
} | |
function check1() public { | |
// use 'Assert' to test the contract | |
Assert.equal(uint(2), uint(1), "error message"); | |
Assert.equal(uint(2), uint(2), "error message"); | |
} | |
function check2() public view returns (bool) { | |
// use the return value (true or false) to test the contract | |
return true; | |
} | |
} | |
contract test_2 { | |
function beforeAll() public { | |
// here should instantiate tested contract | |
Assert.equal(uint(4), uint(3), "error in before all function"); | |
} | |
function check1() public { | |
// use 'Assert' to test the contract | |
Assert.equal(uint(2), uint(1), "error message"); | |
Assert.equal(uint(2), uint(2), "error message"); | |
} | |
function check2() public view returns (bool) { | |
// use the return value (true or false) to test the contract | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.11; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) constant returns (uint); | |
function transfer(address to, uint value); | |
event Transfer(address indexed from, address indexed to, uint value); | |
} | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
/** | |
* @dev Fix for the ERC20 short address attack. | |
*/ | |
modifier onlyPayloadSize(uint size) { | |
if(msg.data.length < size + 4) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(msg.sender, _to, _value); | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) constant returns (uint balance) { | |
return balances[_owner]; | |
} | |
} | |
/** | |
* @title ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) constant returns (uint); | |
function transferFrom(address from, address to, uint value); | |
function approve(address spender, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implemantation of the basic standart token. | |
* @dev https://github.com/ethereum/EIPs/issues/20 | |
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
/** | |
* @dev Transfer tokens from one address to another | |
* @param _from address The address which you want to send tokens from | |
* @param _to address The address which you want to transfer to | |
* @param _value uint the amout of tokens to be transfered | |
*/ | |
function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) { | |
var _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met | |
// if (_value > _allowance) throw; | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
Transfer(_from, _to, _value); | |
} | |
/** | |
* @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender. | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint _value) { | |
// To change the approve amount you first have to reduce the addresses` | |
// allowance to zero by calling `approve(_spender, 0)` if it is not | |
// already 0 to mitigate the race condition described here: | |
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
} | |
/** | |
* @dev Function to check the amount of tokens than an owner allowed to a spender. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A uint specifing the amount of tokens still avaible for the spender. | |
*/ | |
function allowance(address _owner, address _spender) constant returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/** | |
* @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; | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
function Ownable() { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
if (msg.sender != owner) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @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 { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
} | |
} | |
} | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 | |
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol | |
*/ | |
contract MintableToken is StandardToken, Ownable { | |
event Mint(address indexed to, uint value); | |
event MintMore(address indexed to, uint value); | |
event BurnToken(address indexed to, uint value); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
uint public totalSupply = 0; | |
modifier canMint() { | |
if(mintingFinished) throw; | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will recieve the minted tokens. | |
* @param _amount The amount of tokens to mint. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) { | |
totalSupply = totalSupply.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
Mint(_to, _amount); | |
return true; | |
} | |
function addMint(uint _amount) onlyOwner returns (bool){ | |
totalSupply = totalSupply.add(_amount); | |
balances[msg.sender] = balances[msg.sender].add(_amount); | |
MintMore(msg.sender, _amount); | |
return true; | |
} | |
function burnToken(uint _amount) returns (bool) { | |
totalSupply = totalSupply.sub(_amount); | |
balances[msg.sender] = balances[msg.sender].sub(_amount); | |
require(balances[msg.sender] >= 0); | |
BurnToken(msg.sender, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() onlyOwner returns (bool) { | |
mintingFinished = true; | |
MintFinished(); | |
return true; | |
} | |
} | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev modifier to allow actions only when the contract IS paused | |
*/ | |
modifier whenNotPaused() { | |
if (paused) throw; | |
_; | |
} | |
/** | |
* @dev modifier to allow actions only when the contract IS NOT paused | |
*/ | |
modifier whenPaused { | |
if (!paused) throw; | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused returns (bool) { | |
paused = true; | |
Pause(); | |
return true; | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused returns (bool) { | |
paused = false; | |
Unpause(); | |
return true; | |
} | |
} | |
/** | |
* Pausable token | |
* | |
* Simple ERC20 Token example, with pausable token creation | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer(address _to, uint _value) whenNotPaused { | |
super.transfer(_to, _value); | |
} | |
function transferFrom(address _from, address _to, uint _value) whenNotPaused { | |
super.transferFrom(_from, _to, _value); | |
} | |
} | |
/** | |
* @title TokenTimelock | |
* @dev TokenTimelock is a token holder contract that will allow a | |
* beneficiary to extract the tokens after a time has passed | |
*/ | |
contract TokenTimelock { | |
// ERC20 basic token contract being held | |
ERC20Basic token; | |
// beneficiary of tokens after they are released | |
address beneficiary; | |
// timestamp where token release is enabled | |
uint releaseTime; | |
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) { | |
require(_releaseTime > now); | |
token = _token; | |
beneficiary = _beneficiary; | |
releaseTime = _releaseTime; | |
} | |
/** | |
* @dev beneficiary claims tokens held by time lock | |
*/ | |
function claim() { | |
require(msg.sender == beneficiary); | |
require(now >= releaseTime); | |
uint amount = token.balanceOf(this); | |
require(amount > 0); | |
token.transfer(beneficiary, amount); | |
} | |
} | |
/** | |
* @title OMGToken | |
* @dev Omise Go Token contract | |
*/ | |
contract LIKEPOINT is PausableToken, MintableToken { | |
using SafeMath for uint256; | |
string public name = "Loyalty Inspiration Token"; | |
string public symbol = "LIKE"; | |
uint public decimals = 18; | |
/** | |
* @dev mint timelocked tokens | |
*/ | |
function mintTimelocked(address _to, uint256 _amount, uint256 _releaseTime) | |
onlyOwner canMint returns (TokenTimelock) { | |
TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime); | |
mint(timelock, _amount); | |
return timelock; | |
} | |
} | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.11; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20Basic { | |
uint public totalSupply; | |
function balanceOf(address who) constant returns (uint); | |
function transfer(address to, uint value); | |
event Transfer(address indexed from, address indexed to, uint value); | |
} | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint; | |
mapping(address => uint) balances; | |
/** | |
* @dev Fix for the ERC20 short address attack. | |
*/ | |
modifier onlyPayloadSize(uint size) { | |
if(msg.data.length < size + 4) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @dev transfer token for a specified address | |
* @param _to The address to transfer to. | |
* @param _value The amount to be transferred. | |
*/ | |
function transfer(address _to, uint _value) onlyPayloadSize(2 * 32) { | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
Transfer(msg.sender, _to, _value); | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) constant returns (uint balance) { | |
return balances[_owner]; | |
} | |
} | |
/** | |
* @title ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/20 | |
*/ | |
contract ERC20 is ERC20Basic { | |
function allowance(address owner, address spender) constant returns (uint); | |
function transferFrom(address from, address to, uint value); | |
function approve(address spender, uint value); | |
event Approval(address indexed owner, address indexed spender, uint value); | |
} | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implemantation of the basic standart token. | |
* @dev https://github.com/ethereum/EIPs/issues/20 | |
* @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol | |
*/ | |
contract StandardToken is BasicToken, ERC20 { | |
mapping (address => mapping (address => uint)) allowed; | |
/** | |
* @dev Transfer tokens from one address to another | |
* @param _from address The address which you want to send tokens from | |
* @param _to address The address which you want to transfer to | |
* @param _value uint the amout of tokens to be transfered | |
*/ | |
function transferFrom(address _from, address _to, uint _value) onlyPayloadSize(3 * 32) { | |
var _allowance = allowed[_from][msg.sender]; | |
// Check is not needed because sub(_allowance, _value) will already throw if this condition is not met | |
// if (_value > _allowance) throw; | |
balances[_to] = balances[_to].add(_value); | |
balances[_from] = balances[_from].sub(_value); | |
allowed[_from][msg.sender] = _allowance.sub(_value); | |
Transfer(_from, _to, _value); | |
} | |
/** | |
* @dev Aprove the passed address to spend the specified amount of tokens on beahlf of msg.sender. | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint _value) { | |
// To change the approve amount you first have to reduce the addresses` | |
// allowance to zero by calling `approve(_spender, 0)` if it is not | |
// already 0 to mitigate the race condition described here: | |
// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 | |
if ((_value != 0) && (allowed[msg.sender][_spender] != 0)) throw; | |
allowed[msg.sender][_spender] = _value; | |
Approval(msg.sender, _spender, _value); | |
} | |
/** | |
* @dev Function to check the amount of tokens than an owner allowed to a spender. | |
* @param _owner address The address which owns the funds. | |
* @param _spender address The address which will spend the funds. | |
* @return A uint specifing the amount of tokens still avaible for the spender. | |
*/ | |
function allowance(address _owner, address _spender) constant returns (uint remaining) { | |
return allowed[_owner][_spender]; | |
} | |
} | |
/** | |
* @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; | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
function Ownable() { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
if (msg.sender != owner) { | |
throw; | |
} | |
_; | |
} | |
/** | |
* @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 { | |
if (newOwner != address(0)) { | |
owner = newOwner; | |
} | |
} | |
} | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120 | |
* Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol | |
*/ | |
contract MintableToken is StandardToken, Ownable { | |
event Mint(address indexed to, uint value); | |
event MintMore(address indexed to, uint value); | |
event BurnToken(address indexed to, uint value); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
uint public totalSupply = 0; | |
modifier canMint() { | |
if(mintingFinished) throw; | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will recieve the minted tokens. | |
* @param _amount The amount of tokens to mint. | |
* @return A boolean that indicates if the operation was successful. | |
*/ | |
function mint(address _to, uint _amount) onlyOwner canMint returns (bool) { | |
totalSupply = totalSupply.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
Mint(_to, _amount); | |
return true; | |
} | |
function addMint(uint _amount) onlyOwner returns (bool){ | |
totalSupply = totalSupply.add(_amount); | |
balances[msg.sender] = balances[msg.sender].add(_amount); | |
MintMore(msg.sender, _amount); | |
return true; | |
} | |
function burnToken(uint _amount) returns (bool) { | |
totalSupply = totalSupply.sub(_amount); | |
balances[msg.sender] = balances[msg.sender].sub(_amount); | |
require(balances[msg.sender] >= 0); | |
BurnToken(msg.sender, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() onlyOwner returns (bool) { | |
mintingFinished = true; | |
MintFinished(); | |
return true; | |
} | |
} | |
/** | |
* @title Pausable | |
* @dev Base contract which allows children to implement an emergency stop mechanism. | |
*/ | |
contract Pausable is Ownable { | |
event Pause(); | |
event Unpause(); | |
bool public paused = false; | |
/** | |
* @dev modifier to allow actions only when the contract IS paused | |
*/ | |
modifier whenNotPaused() { | |
if (paused) throw; | |
_; | |
} | |
/** | |
* @dev modifier to allow actions only when the contract IS NOT paused | |
*/ | |
modifier whenPaused { | |
if (!paused) throw; | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused returns (bool) { | |
paused = true; | |
Pause(); | |
return true; | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused returns (bool) { | |
paused = false; | |
Unpause(); | |
return true; | |
} | |
} | |
/** | |
* Pausable token | |
* | |
* Simple ERC20 Token example, with pausable token creation | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer(address _to, uint _value) whenNotPaused { | |
super.transfer(_to, _value); | |
} | |
function transferFrom(address _from, address _to, uint _value) whenNotPaused { | |
super.transferFrom(_from, _to, _value); | |
} | |
} | |
/** | |
* @title TokenTimelock | |
* @dev TokenTimelock is a token holder contract that will allow a | |
* beneficiary to extract the tokens after a time has passed | |
*/ | |
contract TokenTimelock { | |
// ERC20 basic token contract being held | |
ERC20Basic token; | |
// beneficiary of tokens after they are released | |
address beneficiary; | |
// timestamp where token release is enabled | |
uint releaseTime; | |
function TokenTimelock(ERC20Basic _token, address _beneficiary, uint _releaseTime) { | |
require(_releaseTime > now); | |
token = _token; | |
beneficiary = _beneficiary; | |
releaseTime = _releaseTime; | |
} | |
/** | |
* @dev beneficiary claims tokens held by time lock | |
*/ | |
function claim() { | |
require(msg.sender == beneficiary); | |
require(now >= releaseTime); | |
uint amount = token.balanceOf(this); | |
require(amount > 0); | |
token.transfer(beneficiary, amount); | |
} | |
} | |
/** | |
* @title OMGToken | |
* @dev Omise Go Token contract | |
*/ | |
contract LIKEPOINT is PausableToken, MintableToken { | |
using SafeMath for uint256; | |
string public name = "Loyalty Inspiration Token"; | |
string public symbol = "LIKE"; | |
uint public decimals = 18; | |
/** | |
* @dev mint timelocked tokens | |
*/ | |
function mintTimelocked(address _to, uint256 _amount, uint256 _releaseTime) | |
onlyOwner canMint returns (TokenTimelock) { | |
TokenTimelock timelock = new TokenTimelock(this, _to, _releaseTime); | |
mint(timelock, _amount); | |
return timelock; | |
} | |
} | |
//version 4.19 | |
//0xb1b4615508528de75012e38a0e1c07e0143c0c5d | |
//code: 606060409081526003805460a060020a61ffff021916905560006004558051908101604052601981527f4c6f79616c747920496e737069726174696f6e20546f6b656e00000000000000602082015260059080516100619291602001906100cf565b5060408051908101604052600481527f4c494b4500000000000000000000000000000000000000000000000000000000602082015260069080516100a99291602001906100cf565b50601260075560038054600160a060020a03191633600160a060020a031617905561016a565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061011057805160ff191683800117855561013d565b8280016001018555821561013d579182015b8281111561013d578251825591602001919060010190610122565b5061014992915061014d565b5090565b61016791905b808211156101495760008155600101610153565b90565b610f9a806101796000396000f3006060604052600436106101115763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166305d2035b811461011657806306fdde031461013d578063095ea7b3146101c757806318160ddd146101eb57806323b872dd14610210578063313ce567146102385780633f4ba83a1461024b578063403398301461025e57806340c10f19146102745780635c975abb1461029657806370a08231146102a95780637b47ec1a146102c85780637d64bcb4146102de5780638456cb59146102f15780638da5cb5b1461030457806395d89b4114610333578063a9059cbb14610346578063c14a3b8c14610368578063dd62ed3e1461038d578063f2fde38b146103b2575b600080fd5b341561012157600080fd5b6101296103d1565b604051901515815260200160405180910390f35b341561014857600080fd5b6101506103e1565b60405160208082528190810183818151815260200191508051906020019080838360005b8381101561018c578082015183820152602001610174565b50505050905090810190601f1680156101b95780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156101d257600080fd5b6101e9600160a060020a036004351660243561047f565b005b34156101f657600080fd5b6101fe610520565b60405190815260200160405180910390f35b341561021b57600080fd5b6101e9600160a060020a0360043581169060243516604435610526565b341561024357600080fd5b6101fe61054d565b341561025657600080fd5b610129610553565b341561026957600080fd5b6101296004356105d9565b341561027f57600080fd5b610129600160a060020a0360043516602435610690565b34156102a157600080fd5b61012961075f565b34156102b457600080fd5b6101fe600160a060020a036004351661076f565b34156102d357600080fd5b61012960043561078a565b34156102e957600080fd5b610129610838565b34156102fc57600080fd5b6101296108ad565b341561030f57600080fd5b610317610938565b604051600160a060020a03909116815260200160405180910390f35b341561033e57600080fd5b610150610947565b341561035157600080fd5b6101e9600160a060020a03600435166024356109b2565b341561037357600080fd5b610317600160a060020a03600435166024356044356109d7565b341561039857600080fd5b6101fe600160a060020a0360043581169060243516610a65565b34156103bd57600080fd5b6101e9600160a060020a0360043516610a90565b60035460a860020a900460ff1681565b60058054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104775780601f1061044c57610100808354040283529160200191610477565b820191906000526020600020905b81548152906001019060200180831161045a57829003601f168201915b505050505081565b80158015906104b25750600160a060020a0333811660009081526002602090815260408083209386168352929052205415155b156104bc57600080fd5b600160a060020a03338116600081815260026020908152604080832094871680845294909152908190208490557f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259084905190815260200160405180910390a35050565b60045481565b60035460a060020a900460ff161561053d57600080fd5b610548838383610ae6565b505050565b60075481565b60035460009033600160a060020a0390811691161461057157600080fd5b60035460a060020a900460ff16151561058957600080fd5b6003805474ff0000000000000000000000000000000000000000191690557f7805862f689e2f13df9f062ff482ad3ad112aca9e0847911ed832e158c525b3360405160405180910390a150600190565b60035460009033600160a060020a039081169116146105f757600080fd5b60045461060a908363ffffffff610c0716565b600455600160a060020a033316600090815260016020526040902054610636908363ffffffff610c0716565b600160a060020a0333166000818152600160205260409081902092909255907f1c5e0744c1da3cb41b315608a34ba72e62d5ee9d526850e1762deb049e2715e59084905190815260200160405180910390a2506001919050565b60035460009033600160a060020a039081169116146106ae57600080fd5b60035460a860020a900460ff16156106c557600080fd5b6004546106d8908363ffffffff610c0716565b600455600160a060020a038316600090815260016020526040902054610704908363ffffffff610c0716565b600160a060020a0384166000818152600160205260409081902092909255907f0f6798a560793a54c3bcfe86a93cde1e73087d944c0ea20544137d41213968859084905190815260200160405180910390a250600192915050565b60035460a060020a900460ff1681565b600160a060020a031660009081526001602052604090205490565b6004546000906107a0908363ffffffff610c1f16565b600455600160a060020a0333166000908152600160205260409020546107cc908363ffffffff610c1f16565b600160a060020a03331660009081526001602052604081208290559010156107f357600080fd5b33600160a060020a03167fe12923b90d8a6ca7dc57994322d2afba0be75f98e97e2b892fd34c0d7c6229698360405190815260200160405180910390a2506001919050565b60035460009033600160a060020a0390811691161461085657600080fd5b6003805475ff000000000000000000000000000000000000000000191660a860020a1790557fae5184fba832cb2b1f702aca6117b8d265eaf03ad33eb133f19dde0f5920fa0860405160405180910390a150600190565b60035460009033600160a060020a039081169116146108cb57600080fd5b60035460a060020a900460ff16156108e257600080fd5b6003805474ff0000000000000000000000000000000000000000191660a060020a1790557f6985a02210a168e66602d3235cb6db0e70f92b3ba4d376a33c0f3d9434bff62560405160405180910390a150600190565b600354600160a060020a031681565b60068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104775780601f1061044c57610100808354040283529160200191610477565b60035460a060020a900460ff16156109c957600080fd5b6109d38282610c33565b5050565b600354600090819033600160a060020a039081169116146109f757600080fd5b60035460a860020a900460ff1615610a0e57600080fd5b308584610a19610d0a565b600160a060020a0393841681529190921660208201526040808201929092526060019051809103906000f0801515610a5057600080fd5b9050610a5c8185610690565b50949350505050565b600160a060020a03918216600090815260026020908152604080832093909416825291909152205490565b60035433600160a060020a03908116911614610aab57600080fd5b600160a060020a03811615610ae3576003805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0383161790555b50565b600060606064361015610af857600080fd5b600160a060020a038086166000908152600260209081526040808320338516845282528083205493881683526001909152902054909250610b3f908463ffffffff610c0716565b600160a060020a038086166000908152600160205260408082209390935590871681522054610b74908463ffffffff610c1f16565b600160a060020a038616600090815260016020526040902055610b9d828463ffffffff610c1f16565b600160a060020a03808716600081815260026020908152604080832033861684529091529081902093909355908616917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9086905190815260200160405180910390a35050505050565b6000828201610c1884821015610cfe565b9392505050565b6000610c2d83831115610cfe565b50900390565b60406044361015610c4357600080fd5b600160a060020a033316600090815260016020526040902054610c6c908363ffffffff610c1f16565b600160a060020a033381166000908152600160205260408082209390935590851681522054610ca1908363ffffffff610c0716565b600160a060020a0380851660008181526001602052604090819020939093559133909116907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a3505050565b801515610ae357600080fd5b60405161025480610d1b8339019056006060604052341561000f57600080fd5b60405160608061025483398101604052808051919060200180519190602001805191505042811161003f57600080fd5b60008054600160a060020a03948516600160a060020a03199182161790915560018054939094169216919091179091556002556101d3806100816000396000f3006060604052600436106100275763ffffffff60e060020a6000350416634e71d92d811461002c575b600080fd5b341561003757600080fd5b61003f610041565b005b6001546000903373ffffffffffffffffffffffffffffffffffffffff90811691161461006c57600080fd5b60025442101561007b57600080fd5b6000805473ffffffffffffffffffffffffffffffffffffffff16906370a082319030906040516020015260405160e060020a63ffffffff841602815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401602060405180830381600087803b15156100f057600080fd5b6102c65a03f1151561010157600080fd5b50505060405180519150506000811161011957600080fd5b60005460015473ffffffffffffffffffffffffffffffffffffffff9182169163a9059cbb91168360405160e060020a63ffffffff851602815273ffffffffffffffffffffffffffffffffffffffff90921660048301526024820152604401600060405180830381600087803b151561019057600080fd5b6102c65a03f115156101a157600080fd5b505050505600a165627a7a72305820273b6131ccc5a3d10e53aa0b405431f6b055209045b8762e9df8a8623b5b95cf0029a165627a7a723058201aceca8567c5b6b870ef51f9081176993ce7fb3550ed9b847d422aff70f4e9db0029 | |
//abi : [ { "constant": false, "inputs": [ { "name": "_amount", "type": "uint256" } ], "name": "addMint", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_spender", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "approve", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_amount", "type": "uint256" } ], "name": "burnToken", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [], "name": "finishMinting", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_amount", "type": "uint256" } ], "name": "mint", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_amount", "type": "uint256" }, { "name": "_releaseTime", "type": "uint256" } ], "name": "mintTimelocked", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [], "name": "pause", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transfer", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "_from", "type": "address" }, { "name": "_to", "type": "address" }, { "name": "_value", "type": "uint256" } ], "name": "transferFrom", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [ { "name": "newOwner", "type": "address" } ], "name": "transferOwnership", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "constant": false, "inputs": [], "name": "unpause", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Mint", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "MintMore", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "BurnToken", "type": "event" }, { "anonymous": false, "inputs": [], "name": "MintFinished", "type": "event" }, { "anonymous": false, "inputs": [], "name": "Pause", "type": "event" }, { "anonymous": false, "inputs": [], "name": "Unpause", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "owner", "type": "address" }, { "indexed": true, "name": "spender", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Approval", "type": "event" }, { "anonymous": false, "inputs": [ { "indexed": true, "name": "from", "type": "address" }, { "indexed": true, "name": "to", "type": "address" }, { "indexed": false, "name": "value", "type": "uint256" } ], "name": "Transfer", "type": "event" }, { "constant": true, "inputs": [ { "name": "_owner", "type": "address" }, { "name": "_spender", "type": "address" } ], "name": "allowance", "outputs": [ { "name": "remaining", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [ { "name": "_owner", "type": "address" } ], "name": "balanceOf", "outputs": [ { "name": "balance", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "decimals", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "mintingFinished", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "name", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "owner", "outputs": [ { "name": "", "type": "address" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "paused", "outputs": [ { "name": "", "type": "bool" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "symbol", "outputs": [ { "name": "", "type": "string" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": true, "inputs": [], "name": "totalSupply", "outputs": [ { "name": "", "type": "uint256" } ], "payable": false, "stateMutability": "view", "type": "function" } ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
*Submitted for verification at Etherscan.io on 2020-09-05 | |
*/ | |
// File: @openzeppelin/contracts/GSN/Context.sol | |
pragma solidity ^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. | |
*/ | |
abstract contract Context { | |
function _msgSender() internal view virtual returns (address payable) { | |
return msg.sender; | |
} | |
function _msgData() internal view virtual returns (bytes memory) { | |
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 | |
return msg.data; | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Interface of the ERC20 standard as defined in the EIP. | |
*/ | |
interface IERC20 { | |
/** | |
* @dev Returns the amount of tokens in existence. | |
*/ | |
function totalSupply() external view returns (uint256); | |
/** | |
* @dev Returns the amount of tokens owned by `account`. | |
*/ | |
function balanceOf(address account) external view returns (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. | |
*/ | |
function transfer(address recipient, uint256 amount) external returns (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. | |
*/ | |
function allowance(address owner, address spender) external view returns (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. | |
*/ | |
function approve(address spender, uint256 amount) external returns (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. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); | |
/** | |
* @dev Emitted when `value` tokens are moved from one account (`from`) to | |
* another (`to`). | |
* | |
* Note that `value` may be zero. | |
*/ | |
event Transfer(address indexed from, address indexed 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. | |
*/ | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
} | |
// File: @openzeppelin/contracts/math/SafeMath.sol | |
pragma solidity ^0.6.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. | |
*/ | |
library SafeMath { | |
/** | |
* @dev Returns the addition of two unsigned integers, reverting on | |
* overflow. | |
* | |
* Counterpart to Solidity's `+` operator. | |
* | |
* Requirements: | |
* | |
* - Addition cannot overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (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. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (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/522 | |
if (a == 0) { | |
return 0; | |
} | |
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. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b > 0, errorMessage); | |
uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return 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. | |
*/ | |
function mod(uint256 a, uint256 b) internal pure returns (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. | |
*/ | |
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { | |
require(b != 0, errorMessage); | |
return a % b; | |
} | |
} | |
// File: @openzeppelin/contracts/utils/Address.sol | |
pragma solidity ^0.6.2; | |
/** | |
* @dev Collection of functions related to the address type | |
*/ | |
library Address { | |
/** | |
* @dev Returns true if `account` is a contract. | |
* | |
* [IMPORTANT] | |
* ==== | |
* It is unsafe to assume that an address for which this function returns | |
* false is an externally-owned account (EOA) and not a contract. | |
* | |
* Among others, `isContract` will return false for the following | |
* types of addresses: | |
* | |
* - an externally-owned account | |
* - a contract in construction | |
* - an address where a contract will be created | |
* - an address where a contract lived, but was destroyed | |
* ==== | |
*/ | |
function isContract(address account) internal view returns (bool) { | |
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts | |
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned | |
// for accounts without code, i.e. `keccak256('')` | |
bytes32 codehash; | |
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; | |
// solhint-disable-next-line no-inline-assembly | |
assembly { codehash := extcodehash(account) } | |
return (codehash != accountHash && codehash != 0x0); | |
} | |
/** | |
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to | |
* `recipient`, forwarding all available gas and reverting on errors. | |
* | |
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost | |
* of certain opcodes, possibly making contracts go over the 2300 gas limit | |
* imposed by `transfer`, making them unable to receive funds via | |
* `transfer`. {sendValue} removes this limitation. | |
* | |
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. | |
* | |
* IMPORTANT: because control is transferred to `recipient`, care must be | |
* taken to not create reentrancy vulnerabilities. Consider using | |
* {ReentrancyGuard} or the | |
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. | |
*/ | |
function sendValue(address payable recipient, uint256 amount) internal { | |
require(address(this).balance >= amount, "Address: insufficient balance"); | |
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value | |
(bool success, ) = recipient.call{ value: amount }(""); | |
require(success, "Address: unable to send value, recipient may have reverted"); | |
} | |
/** | |
* @dev Performs a Solidity function call using a low level `call`. A | |
* plain`call` is an unsafe replacement for a function call: use this | |
* function instead. | |
* | |
* If `target` reverts with a revert reason, it is bubbled up by this | |
* function (like regular Solidity function calls). | |
* | |
* Returns the raw returned data. To convert to the expected return value, | |
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. | |
* | |
* Requirements: | |
* | |
* - `target` must be a contract. | |
* - calling `target` with `data` must not revert. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data) internal returns (bytes memory) { | |
return functionCall(target, data, "Address: low-level call failed"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with | |
* `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { | |
return _functionCallWithValue(target, data, 0, errorMessage); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], | |
* but also transferring `value` wei to `target`. | |
* | |
* Requirements: | |
* | |
* - the calling contract must have an ETH balance of at least `value`. | |
* - the called Solidity function must be `payable`. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
} | |
/** | |
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but | |
* with `errorMessage` as a fallback revert reason when `target` reverts. | |
* | |
* _Available since v3.1._ | |
*/ | |
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"); | |
return _functionCallWithValue(target, data, value, errorMessage); | |
} | |
function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { | |
require(isContract(target), "Address: call to non-contract"); | |
// solhint-disable-next-line avoid-low-level-calls | |
(bool success, bytes memory returndata) = target.call{ value: weiValue }(data); | |
if (success) { | |
return returndata; | |
} else { | |
// Look for revert reason and bubble it up if present | |
if (returndata.length > 0) { | |
// The easiest way to bubble the revert reason is using memory via assembly | |
// solhint-disable-next-line no-inline-assembly | |
assembly { | |
let returndata_size := mload(returndata) | |
revert(add(32, returndata), returndata_size) | |
} | |
} else { | |
revert(errorMessage); | |
} | |
} | |
} | |
} | |
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @dev Implementation of the {IERC20} interface. | |
* | |
* This implementation is agnostic to the way tokens are created. This means | |
* that a supply mechanism has to be added in a derived contract using {_mint}. | |
* For a generic mechanism see {ERC20PresetMinterPauser}. | |
* | |
* TIP: For a detailed writeup see our guide | |
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How | |
* to implement supply mechanisms]. | |
* | |
* We have followed general OpenZeppelin guidelines: functions revert instead | |
* of returning `false` on failure. This behavior is nonetheless conventional | |
* and does not conflict with the expectations of ERC20 applications. | |
* | |
* Additionally, an {Approval} event is emitted on calls to {transferFrom}. | |
* This allows applications to reconstruct the allowance for all accounts just | |
* by listening to said events. Other implementations of the EIP may not emit | |
* these events, as it isn't required by the specification. | |
* | |
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance} | |
* functions have been added to mitigate the well-known issues around setting | |
* allowances. See {IERC20-approve}. | |
*/ | |
contract ERC20 is Context, IERC20 { | |
using SafeMath for uint256; | |
using Address for address; | |
mapping (address => uint256) private _balances; | |
mapping (address => mapping (address => uint256)) private _allowances; | |
uint256 private _totalSupply; | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
/** | |
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with | |
* a default value of 18. | |
* | |
* To select a different value for {decimals}, use {_setupDecimals}. | |
* | |
* All three of these values are immutable: they can only be set once during | |
* construction. | |
*/ | |
constructor (string memory name, string memory symbol) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = 18; | |
} | |
/** | |
* @dev Returns the name of the token. | |
*/ | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
/** | |
* @dev Returns the symbol of the token, usually a shorter version of the | |
* name. | |
*/ | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
/** | |
* @dev Returns the number of decimals used to get its user representation. | |
* For example, if `decimals` equals `2`, a balance of `505` tokens should | |
* be displayed to a user as `5,05` (`505 / 10 ** 2`). | |
* | |
* Tokens usually opt for a value of 18, imitating the relationship between | |
* Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is | |
* called. | |
* | |
* NOTE: This information is only used for _display_ purposes: it in | |
* no way affects any of the arithmetic of the contract, including | |
* {IERC20-balanceOf} and {IERC20-transfer}. | |
*/ | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
/** | |
* @dev See {IERC20-totalSupply}. | |
*/ | |
function totalSupply() public view override returns (uint256) { | |
return _totalSupply; | |
} | |
/** | |
* @dev See {IERC20-balanceOf}. | |
*/ | |
function balanceOf(address account) public view override returns (uint256) { | |
return _balances[account]; | |
} | |
/** | |
* @dev See {IERC20-transfer}. | |
* | |
* Requirements: | |
* | |
* - `recipient` cannot be the zero address. | |
* - the caller must have a balance of at least `amount`. | |
*/ | |
function transfer(address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(_msgSender(), recipient, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-allowance}. | |
*/ | |
function allowance(address owner, address spender) public view virtual override returns (uint256) { | |
return _allowances[owner][spender]; | |
} | |
/** | |
* @dev See {IERC20-approve}. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function approve(address spender, uint256 amount) public virtual override returns (bool) { | |
_approve(_msgSender(), spender, amount); | |
return true; | |
} | |
/** | |
* @dev See {IERC20-transferFrom}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. This is not | |
* required by the EIP. See the note at the beginning of {ERC20}; | |
* | |
* Requirements: | |
* - `sender` and `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
* - the caller must have allowance for ``sender``'s tokens of at least | |
* `amount`. | |
*/ | |
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { | |
_transfer(sender, recipient, amount); | |
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); | |
return true; | |
} | |
/** | |
* @dev Atomically increases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
*/ | |
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); | |
return true; | |
} | |
/** | |
* @dev Atomically decreases the allowance granted to `spender` by the caller. | |
* | |
* This is an alternative to {approve} that can be used as a mitigation for | |
* problems described in {IERC20-approve}. | |
* | |
* Emits an {Approval} event indicating the updated allowance. | |
* | |
* Requirements: | |
* | |
* - `spender` cannot be the zero address. | |
* - `spender` must have allowance for the caller of at least | |
* `subtractedValue`. | |
*/ | |
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { | |
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); | |
return true; | |
} | |
/** | |
* @dev Moves tokens `amount` from `sender` to `recipient`. | |
* | |
* This is internal function is equivalent to {transfer}, and can be used to | |
* e.g. implement automatic token fees, slashing mechanisms, etc. | |
* | |
* Emits a {Transfer} event. | |
* | |
* Requirements: | |
* | |
* - `sender` cannot be the zero address. | |
* - `recipient` cannot be the zero address. | |
* - `sender` must have a balance of at least `amount`. | |
*/ | |
function _transfer(address sender, address recipient, uint256 amount) internal virtual { | |
require(sender != address(0), "ERC20: transfer from the zero address"); | |
require(recipient != address(0), "ERC20: transfer to the zero address"); | |
_beforeTokenTransfer(sender, recipient, amount); | |
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); | |
_balances[recipient] = _balances[recipient].add(amount); | |
emit Transfer(sender, recipient, amount); | |
} | |
/** @dev Creates `amount` tokens and assigns them to `account`, increasing | |
* the total supply. | |
* | |
* Emits a {Transfer} event with `from` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `to` cannot be the zero address. | |
*/ | |
function _mint(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: mint to the zero address"); | |
_beforeTokenTransfer(address(0), account, amount); | |
_totalSupply = _totalSupply.add(amount); | |
_balances[account] = _balances[account].add(amount); | |
emit Transfer(address(0), account, amount); | |
} | |
/** | |
* @dev Destroys `amount` tokens from `account`, reducing the | |
* total supply. | |
* | |
* Emits a {Transfer} event with `to` set to the zero address. | |
* | |
* Requirements | |
* | |
* - `account` cannot be the zero address. | |
* - `account` must have at least `amount` tokens. | |
*/ | |
function _burn(address account, uint256 amount) internal virtual { | |
require(account != address(0), "ERC20: burn from the zero address"); | |
_beforeTokenTransfer(account, address(0), amount); | |
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); | |
_totalSupply = _totalSupply.sub(amount); | |
emit Transfer(account, address(0), amount); | |
} | |
/** | |
* @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. | |
* | |
* This is internal function is equivalent to `approve`, and can be used to | |
* e.g. set automatic allowances for certain subsystems, etc. | |
* | |
* Emits an {Approval} event. | |
* | |
* Requirements: | |
* | |
* - `owner` cannot be the zero address. | |
* - `spender` cannot be the zero address. | |
*/ | |
function _approve(address owner, address spender, uint256 amount) internal virtual { | |
require(owner != address(0), "ERC20: approve from the zero address"); | |
require(spender != address(0), "ERC20: approve to the zero address"); | |
_allowances[owner][spender] = amount; | |
emit Approval(owner, spender, amount); | |
} | |
/** | |
* @dev Sets {decimals} to a value other than the default one of 18. | |
* | |
* WARNING: This function should only be called from the constructor. Most | |
* applications that interact with token contracts will not expect | |
* {decimals} to ever change, and may work incorrectly if it does. | |
*/ | |
function _setupDecimals(uint8 decimals_) internal { | |
_decimals = decimals_; | |
} | |
/** | |
* @dev Hook that is called before any transfer of tokens. This includes | |
* minting and burning. | |
* | |
* Calling conditions: | |
* | |
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens | |
* will be to transferred to `to`. | |
* - when `from` is zero, `amount` tokens will be minted for `to`. | |
* - when `to` is zero, `amount` of ``from``'s tokens will be burned. | |
* - `from` and `to` are never both zero. | |
* | |
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. | |
*/ | |
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } | |
} | |
// File: @openzeppelin/contracts/access/Ownable.sol | |
pragma solidity ^0.6.0; | |
/** | |
* @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. | |
*/ | |
contract Ownable is Context { | |
address private _owner; | |
event OwnershipTransferred(address indexed previousOwner, address indexed 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. | |
*/ | |
function owner() public view returns (address) { | |
return _owner; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
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. | |
*/ | |
function renounceOwnership() public virtual onlyOwner { | |
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. | |
*/ | |
function transferOwnership(address newOwner) public virtual onlyOwner { | |
require(newOwner != address(0), "Ownable: new owner is the zero address"); | |
emit OwnershipTransferred(_owner, newOwner); | |
_owner = newOwner; | |
} | |
} | |
// File: contracts/TomYumKung.sol | |
pragma solidity 0.6.12; | |
// TomYumKungToken with Governance. | |
contract TomYumKungToken is ERC20("TomYumKungToken", "TOMYUMKUNG"), Ownable { | |
/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (MasterChef). | |
function mint(address _to, uint256 _amount) public onlyOwner { | |
_mint(_to, _amount); | |
_moveDelegates(address(0), _delegates[_to], _amount); | |
} | |
// Copied and modified from YAM code: | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernanceStorage.sol | |
// https://github.com/yam-finance/yam-protocol/blob/master/contracts/token/YAMGovernance.sol | |
// Which is copied and modified from COMPOUND: | |
// https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/Comp.sol | |
/// @notice A record of each accounts delegate | |
mapping (address => address) internal _delegates; | |
/// @notice A checkpoint for marking number of votes from a given block | |
struct Checkpoint { | |
uint32 fromBlock; | |
uint256 votes; | |
} | |
/// @notice A record of votes checkpoints for each account, by index | |
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints; | |
/// @notice The number of checkpoints for each account | |
mapping (address => uint32) public numCheckpoints; | |
/// @notice The EIP-712 typehash for the contract's domain | |
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); | |
/// @notice The EIP-712 typehash for the delegation struct used by the contract | |
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)"); | |
/// @notice A record of states for signing / validating signatures | |
mapping (address => uint) public nonces; | |
/// @notice An event thats emitted when an account changes its delegate | |
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate); | |
/// @notice An event thats emitted when a delegate account's vote balance changes | |
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance); | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegator The address to get delegatee for | |
*/ | |
function delegates(address delegator) | |
external | |
view | |
returns (address) | |
{ | |
return _delegates[delegator]; | |
} | |
/** | |
* @notice Delegate votes from `msg.sender` to `delegatee` | |
* @param delegatee The address to delegate votes to | |
*/ | |
function delegate(address delegatee) external { | |
return _delegate(msg.sender, delegatee); | |
} | |
/** | |
* @notice Delegates votes from signatory to `delegatee` | |
* @param delegatee The address to delegate votes to | |
* @param nonce The contract state required to match the signature | |
* @param expiry The time at which to expire the signature | |
* @param v The recovery byte of the signature | |
* @param r Half of the ECDSA signature pair | |
* @param s Half of the ECDSA signature pair | |
*/ | |
function delegateBySig( | |
address delegatee, | |
uint nonce, | |
uint expiry, | |
uint8 v, | |
bytes32 r, | |
bytes32 s | |
) | |
external | |
{ | |
bytes32 domainSeparator = keccak256( | |
abi.encode( | |
DOMAIN_TYPEHASH, | |
keccak256(bytes(name())), | |
getChainId(), | |
address(this) | |
) | |
); | |
bytes32 structHash = keccak256( | |
abi.encode( | |
DELEGATION_TYPEHASH, | |
delegatee, | |
nonce, | |
expiry | |
) | |
); | |
bytes32 digest = keccak256( | |
abi.encodePacked( | |
"\x19\x01", | |
domainSeparator, | |
structHash | |
) | |
); | |
address signatory = ecrecover(digest, v, r, s); | |
require(signatory != address(0), "TOMYUMKUNG::delegateBySig: invalid signature"); | |
require(nonce == nonces[signatory]++, "TOMYUMKUNG::delegateBySig: invalid nonce"); | |
require(now <= expiry, "TOMYUMKUNG::delegateBySig: signature expired"); | |
return _delegate(signatory, delegatee); | |
} | |
/** | |
* @notice Gets the current votes balance for `account` | |
* @param account The address to get votes balance | |
* @return The number of current votes for `account` | |
*/ | |
function getCurrentVotes(address account) | |
external | |
view | |
returns (uint256) | |
{ | |
uint32 nCheckpoints = numCheckpoints[account]; | |
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0; | |
} | |
/** | |
* @notice Determine the prior number of votes for an account as of a block number | |
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation. | |
* @param account The address of the account to check | |
* @param blockNumber The block number to get the vote balance at | |
* @return The number of votes the account had as of the given block | |
*/ | |
function getPriorVotes(address account, uint blockNumber) | |
external | |
view | |
returns (uint256) | |
{ | |
require(blockNumber < block.number, "TOMYUMKUNG::getPriorVotes: not yet determined"); | |
uint32 nCheckpoints = numCheckpoints[account]; | |
if (nCheckpoints == 0) { | |
return 0; | |
} | |
// First check most recent balance | |
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) { | |
return checkpoints[account][nCheckpoints - 1].votes; | |
} | |
// Next check implicit zero balance | |
if (checkpoints[account][0].fromBlock > blockNumber) { | |
return 0; | |
} | |
uint32 lower = 0; | |
uint32 upper = nCheckpoints - 1; | |
while (upper > lower) { | |
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow | |
Checkpoint memory cp = checkpoints[account][center]; | |
if (cp.fromBlock == blockNumber) { | |
return cp.votes; | |
} else if (cp.fromBlock < blockNumber) { | |
lower = center; | |
} else { | |
upper = center - 1; | |
} | |
} | |
return checkpoints[account][lower].votes; | |
} | |
function _delegate(address delegator, address delegatee) | |
internal | |
{ | |
address currentDelegate = _delegates[delegator]; | |
uint256 delegatorBalance = balanceOf(delegator); // balance of underlying TOMYUMKUNGs (not scaled); | |
_delegates[delegator] = delegatee; | |
emit DelegateChanged(delegator, currentDelegate, delegatee); | |
_moveDelegates(currentDelegate, delegatee, delegatorBalance); | |
} | |
function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal { | |
if (srcRep != dstRep && amount > 0) { | |
if (srcRep != address(0)) { | |
// decrease old representative | |
uint32 srcRepNum = numCheckpoints[srcRep]; | |
uint256 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0; | |
uint256 srcRepNew = srcRepOld.sub(amount); | |
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew); | |
} | |
if (dstRep != address(0)) { | |
// increase new representative | |
uint32 dstRepNum = numCheckpoints[dstRep]; | |
uint256 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0; | |
uint256 dstRepNew = dstRepOld.add(amount); | |
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew); | |
} | |
} | |
} | |
function _writeCheckpoint( | |
address delegatee, | |
uint32 nCheckpoints, | |
uint256 oldVotes, | |
uint256 newVotes | |
) | |
internal | |
{ | |
uint32 blockNumber = safe32(block.number, "TOMYUMKUNG::_writeCheckpoint: block number exceeds 32 bits"); | |
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) { | |
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes; | |
} else { | |
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes); | |
numCheckpoints[delegatee] = nCheckpoints + 1; | |
} | |
emit DelegateVotesChanged(delegatee, oldVotes, newVotes); | |
} | |
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) { | |
require(n < 2**32, errorMessage); | |
return uint32(n); | |
} | |
function getChainId() internal pure returns (uint) { | |
uint256 chainId; | |
assembly { chainId := chainid() } | |
return chainId; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
contract TRC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract TransferWithMessageTRC20 { | |
event TransferMessage(address trc20, address _from, address _to, uint _value, string message); | |
function transferMessage(address trc20, address _to, uint _value, string message) public returns (bool) { | |
if(_value > TRC20_Interface(trc20).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
TRC20_Interface(trc20).transferFrom(msg.sender, _to, _value); | |
TransferMessage(trc20, msg.sender, _to, _value, message); | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity >=0.4.22 <0.5.0.; | |
library SafeMath { | |
function mul(uint a, uint b) internal pure returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal pure returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal pure returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal pure returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal pure returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal pure returns (uint256) { | |
return a < b ? a : b; | |
} | |
} | |
interface ITRC21 { | |
function totalSupply() external view returns (uint256); | |
function balanceOf(address who) external view returns (uint256); | |
function estimateFee(uint256 value) external view returns (uint256); | |
function issuer() external view returns (address); | |
function decimals() external view returns (uint8); | |
function allowance(address owner, address spender) external view returns (uint256); | |
function transfer(address to, uint256 value) external returns (bool); | |
function approve(address spender, uint256 value) external returns (bool); | |
function transferFrom(address from, address to, uint256 value) external returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
event Approval(address indexed owner, address indexed spender, uint256 value); | |
event Fee(address indexed from, address indexed to, address indexed issuer, uint256 value); | |
} | |
contract Ownable is ITRC21 { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
emit transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract TRC21 is Ownable { | |
using SafeMath for uint256; | |
mapping (address => uint256) private _balances; | |
uint256 private _minFee; | |
address private _issuer; | |
mapping (address => mapping (address => uint256)) private _allowed; | |
uint256 private _totalSupply; | |
address private newissuer; | |
event TransferIssuer(address indexed issuer); | |
function totalSupply() public view returns (uint256) { | |
return _totalSupply; | |
} | |
function minFee() public view returns (uint256) { | |
return _minFee; | |
} | |
function issuer() public view returns (address) { | |
return _issuer; | |
} | |
function balanceOf(address owner) public view returns (uint256) { | |
return _balances[owner]; | |
} | |
function estimateFee(uint256 value) public view returns (uint256) { | |
return value.mul(0).add(_minFee); | |
} | |
function allowance(address owner,address spender) public view returns (uint256){ | |
return _allowed[owner][spender]; | |
} | |
function transfer(address to, uint256 value) public returns (bool) { | |
uint256 total = value.add(_minFee); | |
require(to != address(0)); | |
require(value <= total); | |
_transfer(msg.sender, to, value); | |
_transfer(msg.sender, _issuer, _minFee); | |
emit Fee(msg.sender, to, _issuer, _minFee); | |
return true; | |
} | |
function approve(address spender, uint256 value) public returns (bool) { | |
require(spender != address(0)); | |
require(_balances[msg.sender]>=_minFee); | |
_allowed[msg.sender][spender] = value; | |
_transfer(msg.sender, _issuer, _minFee); | |
emit Approval(msg.sender, spender, value); | |
return true; | |
} | |
function transferFrom(address from, address to, uint256 value) public returns (bool) { | |
uint256 total = value.add(_minFee); | |
require(to != address(0)); | |
require(value <= total); | |
require(total <= _allowed[from][msg.sender]); | |
_allowed[from][msg.sender] = _allowed[from][msg.sender].sub(total); | |
_transfer(from, to, value); | |
_transfer(from, _issuer, _minFee); | |
emit Fee(msg.sender, to, _issuer, _minFee); | |
return true; | |
} | |
function _transfer(address from, address to, uint256 value) internal { | |
require(value <= _balances[from]); | |
require(to != address(0)); | |
_balances[from] = _balances[from].sub(value); | |
_balances[to] = _balances[to].add(value); | |
emit Transfer(from, to, value); | |
} | |
function _mint(address account, uint256 value) internal { | |
require(account != 0); | |
_totalSupply = _totalSupply.add(value); | |
_balances[account] = _balances[account].add(value); | |
emit Transfer(address(0), account, value); | |
} | |
function _changeIssuer(address newIssuer) internal { | |
require(newIssuer != address(0)); | |
_issuer = newIssuer; | |
} | |
function _changeMinFee(uint256 value) internal { | |
_minFee = value; | |
} | |
function OwnerChangeMinFee(uint256 value) onlyOwner public { | |
_minFee = value; | |
} | |
function transferIssuer(address newIssuer) onlyOwner public { | |
if (_issuer != address(0)) { | |
newissuer = newIssuer; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptIssuer() public { | |
if(newissuer == msg.sender) { | |
_issuer = msg.sender; | |
emit TransferIssuer(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract MyToken is TRC21 { | |
string private _name; | |
string private _symbol; | |
uint8 private _decimals; | |
constructor (string memory name, string memory symbol, uint8 decimals, uint256 cap, uint256 minFee) public { | |
_name = name; | |
_symbol = symbol; | |
_decimals = decimals; | |
_mint(msg.sender, cap); | |
_changeIssuer(msg.sender); | |
_changeMinFee(minFee); | |
owner = msg.sender; | |
} | |
function name() public view returns (string memory) { | |
return _name; | |
} | |
function symbol() public view returns (string memory) { | |
return _symbol; | |
} | |
function decimals() public view returns (uint8) { | |
return _decimals; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.11; | |
/** | |
* Math operations with safety checks | |
*/ | |
library SafeMath { | |
function mul(uint a, uint b) internal returns (uint) { | |
uint c = a * b; | |
assert(a == 0 || c / a == b); | |
return c; | |
} | |
function div(uint a, uint b) internal returns (uint) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
uint c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return c; | |
} | |
function sub(uint a, uint b) internal returns (uint) { | |
assert(b <= a); | |
return a - b; | |
} | |
function add(uint a, uint b) internal returns (uint) { | |
uint c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
function max64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a >= b ? a : b; | |
} | |
function min64(uint64 a, uint64 b) internal constant returns (uint64) { | |
return a < b ? a : b; | |
} | |
function max256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a >= b ? a : b; | |
} | |
function min256(uint256 a, uint256 b) internal constant returns (uint256) { | |
return a < b ? a : b; | |
} | |
function assert(bool assertion) internal { | |
if (!assertion) { | |
throw; | |
} | |
} | |
} | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
//oracle address for feed total lock and reward this address is oracle | |
address public oracleAddress; | |
mapping(address => uint256) public pricePerticket; | |
mapping(address => uint256) public prize; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
modifier onlyOracleAddress() { | |
require(oracleAddress == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
function transferOracleAddress(address newOracle) onlyOwner public { | |
if (newOracle != address(0)) { | |
oracleAddress = newOracle; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract SlotMachine is Ownable{ | |
//this ticket is return number of owner ticket | |
mapping(address => mapping(address => uint256)) public ticket; | |
using SafeMath for uint; | |
mapping (address => uint256) public balanceToken; | |
event AdminDepositToken(address contractAddress, address sender, uint256 amount, string message); | |
event AdminWithdrawToken(address contractAddress, address sender, uint256 amount, string message); | |
event BuyTicket(address contractAddress, address _buyer, uint256 amount, string message); | |
event SubTicket(address contractAddress, address _buyer, uint256 ticket, string message); | |
event ChangePrice(address contractAddress, address _owner, uint256 newPrice); | |
event ChangePrize(address contractAddress, address _owner, uint256 _prize); | |
event TransferTicket(address contractAddress, address _sender, address _receiver, uint256 ticket); | |
event ClaimReward(address contractAddress, address _lucker, uint256 amount, string message); | |
function changePrice(address likeAddr, uint256 newPrice) onlyOwner public { | |
pricePerticket[likeAddr] = newPrice; | |
ChangePrice(likeAddr, msg.sender, newPrice); | |
} | |
function changePrize(address likeAddr, uint256 _prize) onlyOwner public { | |
prize[likeAddr] = _prize; | |
ChangePrize(likeAddr, msg.sender, _prize); | |
} | |
function SlotMachine(address likeAddr, address oracle, uint256 price, uint256 _prize) public { | |
oracleAddress = oracle; | |
pricePerticket[likeAddr] = price; | |
prize[likeAddr] = _prize; | |
} | |
function buyTicket(address likeAddr, uint amount, string message) public returns (bool){ | |
require(amount >= pricePerticket[likeAddr]); | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
uint256 numTicket = amount/pricePerticket[likeAddr]; | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
ticket[likeAddr][msg.sender] = ticket[likeAddr][msg.sender].add(numTicket); | |
BuyTicket(likeAddr, msg.sender, amount, message); | |
return true; | |
} | |
function transferTicket(address likeAddr, address _address, uint _ticket) public returns (bool){ | |
require(ticket[likeAddr][msg.sender] > _ticket); | |
ticket[likeAddr][msg.sender].sub(_ticket); | |
ticket[likeAddr][_address].add(_ticket); | |
TransferTicket(likeAddr, msg.sender, _address, _ticket); | |
return true; | |
} | |
function subTicket(address likeAddr, uint _ticket, string message) public returns (bool){ | |
require(ticket[likeAddr][msg.sender] >= _ticket); | |
ticket[likeAddr][msg.sender] = ticket[likeAddr][msg.sender].sub(_ticket); | |
SubTicket(likeAddr, msg.sender, ticket[likeAddr][msg.sender], message); | |
return true; | |
} | |
function adminWithdrawToken(address likeAddr, uint amount, string message) onlyOwner public returns(bool) { | |
require(amount <= balanceToken[likeAddr]); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(amount); | |
ERC20_Interface(likeAddr).transfer(msg.sender, amount); | |
AdminWithdrawToken(likeAddr, msg.sender, amount, message); | |
return true; | |
} | |
function adminDepositToken(address likeAddr, uint amount, string message) onlyOwner public returns(bool) { | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, address(this), amount); | |
balanceToken[likeAddr] = balanceToken[likeAddr].add(amount); | |
AdminDepositToken(likeAddr, msg.sender, amount, message); | |
return true; | |
} | |
function claimReward(address likeAddr, address _lucker, string message) onlyOracleAddress public returns(bool) { | |
require(prize[likeAddr] < balanceToken[likeAddr]); | |
balanceToken[likeAddr] = balanceToken[likeAddr].sub(prize[likeAddr]); | |
ERC20_Interface(likeAddr).transfer(_lucker, prize[likeAddr]); | |
ClaimReward(likeAddr, _lucker, prize[likeAddr], message); | |
return true; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.19; | |
contract ERC20_Interface { | |
function totalSupply() public view returns (uint); | |
function balanceOf(address tokenOwner) public view returns (uint balance); | |
function allowance(address tokenOwner, address spender) public view returns (uint remaining); | |
function transfer(address to, uint tokens) public returns (bool success); | |
function approve(address spender, uint tokens) public returns (bool success); | |
function transferFrom(address from, address to, uint tokens) public returns (bool success); | |
event Transfer(address indexed from, address indexed to, uint tokens); | |
event Approval(address indexed tokenOwner, address indexed spender, uint tokens); | |
} | |
contract Ownable { | |
address public owner; | |
address public waitNewOwner; | |
event transferOwner(address newOwner); | |
function Ownable() public{ | |
owner = msg.sender; | |
} | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(owner == msg.sender); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to transfer control of the contract to a newOwner. | |
* @param newOwner The address to transfer ownership to. | |
* and safe new contract new owner will be accept owner | |
*/ | |
function transferOwnership(address newOwner) onlyOwner public { | |
if (newOwner != address(0)) { | |
waitNewOwner = newOwner; | |
} | |
} | |
/** | |
* this function accept when transfer to new owner and new owner will be accept owner for safe contract free owner | |
*/ | |
function acceptOwnership() public { | |
if(waitNewOwner == msg.sender) { | |
owner = msg.sender; | |
transferOwner(msg.sender); | |
}else{ | |
revert(); | |
} | |
} | |
} | |
contract VendingMachine is Ownable{ | |
address public shopAddr = 0x222f6109001A65C783F555399D4b07DB73531A3c; | |
event Transfer_Vending(address likeAddr, address _buyer, address _shopAddr, uint256 amount, string ref_code, bytes32 payment_id256, string payment_id, string machine_id); | |
function changeShopAddr(address _newshop) onlyOwner public returns (bool) { | |
shopAddr = _newshop; | |
return true; | |
} | |
function transfer_vending(string machine_id, uint256 amount, address likeAddr, string ref_code, string payment_id) public returns (bool){ | |
if(amount > ERC20_Interface(likeAddr).allowance(msg.sender, address(this))) { | |
revert(); | |
} | |
ERC20_Interface(likeAddr).transferFrom(msg.sender, shopAddr, amount); | |
Transfer_Vending(likeAddr, msg.sender, shopAddr, amount, ref_code, sha256(payment_id), payment_id, machine_id); | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment