Created
August 20, 2018 01:38
-
-
Save edmundmiller/6011779cd5c61a8af7a3573c99fb81d6 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.24+commit.e67f0147.js&optimize=false&gist=
This file contains 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.23; | |
/** | |
* Utility library of inline functions on addresses | |
*/ | |
library AddressUtils { | |
/** | |
* Returns whether the target address is a contract | |
* @dev This function will return false if invoked during the constructor of a contract, | |
* as the code is not actually created until after the constructor finishes. | |
* @param addr address to check | |
* @return whether the target address is a contract | |
*/ | |
function isContract(address addr) internal view returns (bool) { | |
uint256 size; | |
// XXX Currently there is no better way to check if there is a contract in an address | |
// than to check the size of the code at that address. | |
// See https://ethereum.stackexchange.com/a/14016/36603 | |
// for more details about how this works. | |
// TODO Check this again before the Serenity release, because all addresses will be | |
// contracts then. | |
// solium-disable-next-line security/no-inline-assembly | |
assembly { size := extcodesize(addr) } | |
return size > 0; | |
} | |
} |
This file contains 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.23; | |
import "./ERC20Basic.sol"; | |
import "./SafeMath.sol"; | |
/** | |
* @title Basic token | |
* @dev Basic version of StandardToken, with no allowances. | |
*/ | |
contract BasicToken is ERC20Basic { | |
using SafeMath for uint256; | |
mapping(address => uint256) balances; | |
uint256 totalSupply_; | |
/** | |
* @dev total number of tokens in existence | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return totalSupply_; | |
} | |
/** | |
* @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, uint256 _value) public returns (bool) { | |
require(_to != address(0)); | |
require(_value <= balances[msg.sender]); | |
balances[msg.sender] = balances[msg.sender].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
emit Transfer(msg.sender, _to, _value); | |
return true; | |
} | |
/** | |
* @dev Gets the balance of the specified address. | |
* @param _owner The address to query the the balance of. | |
* @return An uint256 representing the amount owned by the passed address. | |
*/ | |
function balanceOf(address _owner) public view returns (uint256) { | |
return balances[_owner]; | |
} | |
} |
This file contains 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.23; | |
import "./BasicToken.sol"; | |
/** | |
* @title Burnable Token | |
* @dev Token that can be irreversibly burned (destroyed). | |
*/ | |
contract BurnableToken is BasicToken { | |
event Burn(address indexed burner, uint256 value); | |
/** | |
* @dev Burns a specific amount of tokens. | |
* @param _value The amount of token to be burned. | |
*/ | |
function burn(uint256 _value) public { | |
_burn(msg.sender, _value); | |
} | |
function _burn(address _who, uint256 _value) internal { | |
require(_value <= balances[_who]); | |
// no need to require value <= totalSupply, since that would imply the | |
// sender's balance is greater than the totalSupply, which *should* be an assertion failure | |
balances[_who] = balances[_who].sub(_value); | |
totalSupply_ = totalSupply_.sub(_value); | |
emit Burn(_who, _value); | |
emit Transfer(_who, address(0), _value); | |
} | |
} |
This file contains 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.23; | |
import "./MintableToken.sol"; | |
/** | |
* @title Capped token | |
* @dev Mintable token with a token cap. | |
*/ | |
contract CappedToken is MintableToken { | |
uint256 public cap; | |
constructor(uint256 _cap) public { | |
require(_cap > 0); | |
cap = _cap; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will receive 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, | |
uint256 _amount | |
) | |
onlyOwner | |
canMint | |
public | |
returns (bool) | |
{ | |
require(totalSupply_.add(_amount) <= cap); | |
return super.mint(_to, _amount); | |
} | |
} |
This file contains 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.23; | |
import "./ERC721.sol"; | |
/** | |
* @title ERC-721 methods shipped in OpenZeppelin v1.7.0, removed in the latest version of the standard | |
* @dev Only use this interface for compatibility with previously deployed contracts | |
* @dev Use ERC721 for interacting with new contracts which are standard-compliant | |
*/ | |
contract DeprecatedERC721 is ERC721 { | |
function takeOwnership(uint256 _tokenId) public; | |
function transfer(address _to, uint256 _tokenId) public; | |
function tokensOf(address _owner) public view returns (uint256[]); | |
} |
This file contains 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.23; | |
import "./ERC20.sol"; | |
/** | |
* @title DetailedERC20 token | |
* @dev The decimals are only for visualization purposes. | |
* All the operations are done using the smallest and indivisible token unit, | |
* just as on Ethereum all the operations are done in wei. | |
*/ | |
contract DetailedERC20 is ERC20 { | |
string public name; | |
string public symbol; | |
uint8 public decimals; | |
constructor(string _name, string _symbol, uint8 _decimals) public { | |
name = _name; | |
symbol = _symbol; | |
decimals = _decimals; | |
} | |
} |
This file contains 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.23; | |
import "./ERC20Basic.sol"; | |
/** | |
* @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 (uint256); | |
function transferFrom(address from, address to, uint256 value) | |
public returns (bool); | |
function approve(address spender, uint256 value) public returns (bool); | |
event Approval( | |
address indexed owner, | |
address indexed spender, | |
uint256 value | |
); | |
} |
This file contains 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.23; | |
/** | |
* @title ERC20Basic | |
* @dev Simpler version of ERC20 interface | |
* @dev see https://github.com/ethereum/EIPs/issues/179 | |
*/ | |
contract ERC20Basic { | |
function totalSupply() public view returns (uint256); | |
function balanceOf(address who) public view returns (uint256); | |
function transfer(address to, uint256 value) public returns (bool); | |
event Transfer(address indexed from, address indexed to, uint256 value); | |
} |
This file contains 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.23; | |
import "./ERC721Basic.sol"; | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional enumeration extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721Enumerable is ERC721Basic { | |
function totalSupply() public view returns (uint256); | |
function tokenOfOwnerByIndex( | |
address _owner, | |
uint256 _index | |
) | |
public | |
view | |
returns (uint256 _tokenId); | |
function tokenByIndex(uint256 _index) public view returns (uint256); | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, optional metadata extension | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721Metadata is ERC721Basic { | |
function name() public view returns (string _name); | |
function symbol() public view returns (string _symbol); | |
function tokenURI(uint256 _tokenId) public view returns (string); | |
} | |
/** | |
* @title ERC-721 Non-Fungible Token Standard, full implementation interface | |
* @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata { | |
} |
This file contains 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.23; | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic interface | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721Basic { | |
event Transfer( | |
address indexed _from, | |
address indexed _to, | |
uint256 _tokenId | |
); | |
event Approval( | |
address indexed _owner, | |
address indexed _approved, | |
uint256 _tokenId | |
); | |
event ApprovalForAll( | |
address indexed _owner, | |
address indexed _operator, | |
bool _approved | |
); | |
function balanceOf(address _owner) public view returns (uint256 _balance); | |
function ownerOf(uint256 _tokenId) public view returns (address _owner); | |
function exists(uint256 _tokenId) public view returns (bool _exists); | |
function approve(address _to, uint256 _tokenId) public; | |
function getApproved(uint256 _tokenId) | |
public view returns (address _operator); | |
function setApprovalForAll(address _operator, bool _approved) public; | |
function isApprovedForAll(address _owner, address _operator) | |
public view returns (bool); | |
function transferFrom(address _from, address _to, uint256 _tokenId) public; | |
function safeTransferFrom(address _from, address _to, uint256 _tokenId) | |
public; | |
function safeTransferFrom( | |
address _from, | |
address _to, | |
uint256 _tokenId, | |
bytes _data | |
) | |
public; | |
} |
This file contains 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.23; | |
import "./ERC721Basic.sol"; | |
import "./ERC721Receiver.sol"; | |
import "./SafeMath.sol"; | |
import "./AddressUtils.sol"; | |
/** | |
* @title ERC721 Non-Fungible Token Standard basic implementation | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721BasicToken is ERC721Basic { | |
using SafeMath for uint256; | |
using AddressUtils for address; | |
// Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))` | |
// which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` | |
bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba; | |
// Mapping from token ID to owner | |
mapping (uint256 => address) internal tokenOwner; | |
// Mapping from token ID to approved address | |
mapping (uint256 => address) internal tokenApprovals; | |
// Mapping from owner to number of owned token | |
mapping (address => uint256) internal ownedTokensCount; | |
// Mapping from owner to operator approvals | |
mapping (address => mapping (address => bool)) internal operatorApprovals; | |
/** | |
* @dev Guarantees msg.sender is owner of the given token | |
* @param _tokenId uint256 ID of the token to validate its ownership belongs to msg.sender | |
*/ | |
modifier onlyOwnerOf(uint256 _tokenId) { | |
require(ownerOf(_tokenId) == msg.sender); | |
_; | |
} | |
/** | |
* @dev Checks msg.sender can transfer a token, by being owner, approved, or operator | |
* @param _tokenId uint256 ID of the token to validate | |
*/ | |
modifier canTransfer(uint256 _tokenId) { | |
require(isApprovedOrOwner(msg.sender, _tokenId)); | |
_; | |
} | |
/** | |
* @dev Gets the balance of the specified address | |
* @param _owner address to query the balance of | |
* @return uint256 representing the amount owned by the passed address | |
*/ | |
function balanceOf(address _owner) public view returns (uint256) { | |
require(_owner != address(0)); | |
return ownedTokensCount[_owner]; | |
} | |
/** | |
* @dev Gets the owner of the specified token ID | |
* @param _tokenId uint256 ID of the token to query the owner of | |
* @return owner address currently marked as the owner of the given token ID | |
*/ | |
function ownerOf(uint256 _tokenId) public view returns (address) { | |
address owner = tokenOwner[_tokenId]; | |
require(owner != address(0)); | |
return owner; | |
} | |
/** | |
* @dev Returns whether the specified token exists | |
* @param _tokenId uint256 ID of the token to query the existence of | |
* @return whether the token exists | |
*/ | |
function exists(uint256 _tokenId) public view returns (bool) { | |
address owner = tokenOwner[_tokenId]; | |
return owner != address(0); | |
} | |
/** | |
* @dev Approves another address to transfer the given token ID | |
* @dev The zero address indicates there is no approved address. | |
* @dev There can only be one approved address per token at a given time. | |
* @dev Can only be called by the token owner or an approved operator. | |
* @param _to address to be approved for the given token ID | |
* @param _tokenId uint256 ID of the token to be approved | |
*/ | |
function approve(address _to, uint256 _tokenId) public { | |
address owner = ownerOf(_tokenId); | |
require(_to != owner); | |
require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); | |
if (getApproved(_tokenId) != address(0) || _to != address(0)) { | |
tokenApprovals[_tokenId] = _to; | |
emit Approval(owner, _to, _tokenId); | |
} | |
} | |
/** | |
* @dev Gets the approved address for a token ID, or zero if no address set | |
* @param _tokenId uint256 ID of the token to query the approval of | |
* @return address currently approved for the given token ID | |
*/ | |
function getApproved(uint256 _tokenId) public view returns (address) { | |
return tokenApprovals[_tokenId]; | |
} | |
/** | |
* @dev Sets or unsets the approval of a given operator | |
* @dev An operator is allowed to transfer all tokens of the sender on their behalf | |
* @param _to operator address to set the approval | |
* @param _approved representing the status of the approval to be set | |
*/ | |
function setApprovalForAll(address _to, bool _approved) public { | |
require(_to != msg.sender); | |
operatorApprovals[msg.sender][_to] = _approved; | |
emit ApprovalForAll(msg.sender, _to, _approved); | |
} | |
/** | |
* @dev Tells whether an operator is approved by a given owner | |
* @param _owner owner address which you want to query the approval of | |
* @param _operator operator address which you want to query the approval of | |
* @return bool whether the given operator is approved by the given owner | |
*/ | |
function isApprovedForAll( | |
address _owner, | |
address _operator | |
) | |
public | |
view | |
returns (bool) | |
{ | |
return operatorApprovals[_owner][_operator]; | |
} | |
/** | |
* @dev Transfers the ownership of a given token ID to another address | |
* @dev Usage of this method is discouraged, use `safeTransferFrom` whenever possible | |
* @dev Requires the msg sender to be the owner, approved, or operator | |
* @param _from current owner of the token | |
* @param _to address to receive the ownership of the given token ID | |
* @param _tokenId uint256 ID of the token to be transferred | |
*/ | |
function transferFrom( | |
address _from, | |
address _to, | |
uint256 _tokenId | |
) | |
public | |
canTransfer(_tokenId) | |
{ | |
require(_from != address(0)); | |
require(_to != address(0)); | |
clearApproval(_from, _tokenId); | |
removeTokenFrom(_from, _tokenId); | |
addTokenTo(_to, _tokenId); | |
emit Transfer(_from, _to, _tokenId); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* @dev If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* @dev Requires the msg sender to be the owner, approved, or operator | |
* @param _from current owner of the token | |
* @param _to address to receive the ownership of the given token ID | |
* @param _tokenId uint256 ID of the token to be transferred | |
*/ | |
function safeTransferFrom( | |
address _from, | |
address _to, | |
uint256 _tokenId | |
) | |
public | |
canTransfer(_tokenId) | |
{ | |
// solium-disable-next-line arg-overflow | |
safeTransferFrom(_from, _to, _tokenId, ""); | |
} | |
/** | |
* @dev Safely transfers the ownership of a given token ID to another address | |
* @dev If the target address is a contract, it must implement `onERC721Received`, | |
* which is called upon a safe transfer, and return the magic value | |
* `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`; otherwise, | |
* the transfer is reverted. | |
* @dev Requires the msg sender to be the owner, approved, or operator | |
* @param _from current owner of the token | |
* @param _to address to receive the ownership of the given token ID | |
* @param _tokenId uint256 ID of the token to be transferred | |
* @param _data bytes data to send along with a safe transfer check | |
*/ | |
function safeTransferFrom( | |
address _from, | |
address _to, | |
uint256 _tokenId, | |
bytes _data | |
) | |
public | |
canTransfer(_tokenId) | |
{ | |
transferFrom(_from, _to, _tokenId); | |
// solium-disable-next-line arg-overflow | |
require(checkAndCallSafeTransfer(_from, _to, _tokenId, _data)); | |
} | |
/** | |
* @dev Returns whether the given spender can transfer a given token ID | |
* @param _spender address of the spender to query | |
* @param _tokenId uint256 ID of the token to be transferred | |
* @return bool whether the msg.sender is approved for the given token ID, | |
* is an operator of the owner, or is the owner of the token | |
*/ | |
function isApprovedOrOwner( | |
address _spender, | |
uint256 _tokenId | |
) | |
internal | |
view | |
returns (bool) | |
{ | |
address owner = ownerOf(_tokenId); | |
// Disable solium check because of | |
// https://github.com/duaraghav8/Solium/issues/175 | |
// solium-disable-next-line operator-whitespace | |
return ( | |
_spender == owner || | |
getApproved(_tokenId) == _spender || | |
isApprovedForAll(owner, _spender) | |
); | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* @dev Reverts if the given token ID already exists | |
* @param _to The address that will own the minted token | |
* @param _tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address _to, uint256 _tokenId) internal { | |
require(_to != address(0)); | |
addTokenTo(_to, _tokenId); | |
emit Transfer(address(0), _to, _tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* @dev Reverts if the token does not exist | |
* @param _tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address _owner, uint256 _tokenId) internal { | |
clearApproval(_owner, _tokenId); | |
removeTokenFrom(_owner, _tokenId); | |
emit Transfer(_owner, address(0), _tokenId); | |
} | |
/** | |
* @dev Internal function to clear current approval of a given token ID | |
* @dev Reverts if the given address is not indeed the owner of the token | |
* @param _owner owner of the token | |
* @param _tokenId uint256 ID of the token to be transferred | |
*/ | |
function clearApproval(address _owner, uint256 _tokenId) internal { | |
require(ownerOf(_tokenId) == _owner); | |
if (tokenApprovals[_tokenId] != address(0)) { | |
tokenApprovals[_tokenId] = address(0); | |
emit Approval(_owner, address(0), _tokenId); | |
} | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* @param _to address representing the new owner of the given token ID | |
* @param _tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function addTokenTo(address _to, uint256 _tokenId) internal { | |
require(tokenOwner[_tokenId] == address(0)); | |
tokenOwner[_tokenId] = _to; | |
ownedTokensCount[_to] = ownedTokensCount[_to].add(1); | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* @param _from address representing the previous owner of the given token ID | |
* @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function removeTokenFrom(address _from, uint256 _tokenId) internal { | |
require(ownerOf(_tokenId) == _from); | |
ownedTokensCount[_from] = ownedTokensCount[_from].sub(1); | |
tokenOwner[_tokenId] = address(0); | |
} | |
/** | |
* @dev Internal function to invoke `onERC721Received` on a target address | |
* @dev The call is not executed if the target address is not a contract | |
* @param _from address representing the previous owner of the given token ID | |
* @param _to target address that will receive the tokens | |
* @param _tokenId uint256 ID of the token to be transferred | |
* @param _data bytes optional data to send along with the call | |
* @return whether the call correctly returned the expected magic value | |
*/ | |
function checkAndCallSafeTransfer( | |
address _from, | |
address _to, | |
uint256 _tokenId, | |
bytes _data | |
) | |
internal | |
returns (bool) | |
{ | |
if (!_to.isContract()) { | |
return true; | |
} | |
bytes4 retval = ERC721Receiver(_to).onERC721Received( | |
_from, _tokenId, _data); | |
return (retval == ERC721_RECEIVED); | |
} | |
} |
This file contains 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.23; | |
import "./ERC721Receiver.sol"; | |
contract ERC721Holder is ERC721Receiver { | |
function onERC721Received(address, uint256, bytes) public returns(bytes4) { | |
return ERC721_RECEIVED; | |
} | |
} |
This file contains 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.23; | |
/** | |
* @title ERC721 token receiver interface | |
* @dev Interface for any contract that wants to support safeTransfers | |
* from ERC721 asset contracts. | |
*/ | |
contract ERC721Receiver { | |
/** | |
* @dev Magic value to be returned upon successful reception of an NFT | |
* Equals to `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`, | |
* which can be also obtained as `ERC721Receiver(0).onERC721Received.selector` | |
*/ | |
bytes4 constant ERC721_RECEIVED = 0xf0b9e5ba; | |
/** | |
* @notice Handle the receipt of an NFT | |
* @dev The ERC721 smart contract calls this function on the recipient | |
* after a `safetransfer`. This function MAY throw to revert and reject the | |
* transfer. This function MUST use 50,000 gas or less. Return of other | |
* than the magic value MUST result in the transaction being reverted. | |
* Note: the contract address is always the message sender. | |
* @param _from The sending address | |
* @param _tokenId The NFT identifier which is being transfered | |
* @param _data Additional data with no specified format | |
* @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))` | |
*/ | |
function onERC721Received( | |
address _from, | |
uint256 _tokenId, | |
bytes _data | |
) | |
public | |
returns(bytes4); | |
} |
This file contains 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.23; | |
import "./ERC721.sol"; | |
import "./ERC721BasicToken.sol"; | |
/** | |
* @title Full ERC721 Token | |
* This implementation includes all the required and some optional functionality of the ERC721 standard | |
* Moreover, it includes approve all functionality using operator terminology | |
* @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md | |
*/ | |
contract ERC721Token is ERC721, ERC721BasicToken { | |
// Token name | |
string internal name_; | |
// Token symbol | |
string internal symbol_; | |
// Mapping from owner to list of owned token IDs | |
mapping(address => uint256[]) internal ownedTokens; | |
// Mapping from token ID to index of the owner tokens list | |
mapping(uint256 => uint256) internal ownedTokensIndex; | |
// Array with all token ids, used for enumeration | |
uint256[] internal allTokens; | |
// Mapping from token id to position in the allTokens array | |
mapping(uint256 => uint256) internal allTokensIndex; | |
// Optional mapping for token URIs | |
mapping(uint256 => string) internal tokenURIs; | |
/** | |
* @dev Constructor function | |
*/ | |
constructor(string _name, string _symbol) public { | |
name_ = _name; | |
symbol_ = _symbol; | |
} | |
/** | |
* @dev Gets the token name | |
* @return string representing the token name | |
*/ | |
function name() public view returns (string) { | |
return name_; | |
} | |
/** | |
* @dev Gets the token symbol | |
* @return string representing the token symbol | |
*/ | |
function symbol() public view returns (string) { | |
return symbol_; | |
} | |
/** | |
* @dev Returns an URI for a given token ID | |
* @dev Throws if the token ID does not exist. May return an empty string. | |
* @param _tokenId uint256 ID of the token to query | |
*/ | |
function tokenURI(uint256 _tokenId) public view returns (string) { | |
require(exists(_tokenId)); | |
return tokenURIs[_tokenId]; | |
} | |
/** | |
* @dev Gets the token ID at a given index of the tokens list of the requested owner | |
* @param _owner address owning the tokens list to be accessed | |
* @param _index uint256 representing the index to be accessed of the requested tokens list | |
* @return uint256 token ID at the given index of the tokens list owned by the requested address | |
*/ | |
function tokenOfOwnerByIndex( | |
address _owner, | |
uint256 _index | |
) | |
public | |
view | |
returns (uint256) | |
{ | |
require(_index < balanceOf(_owner)); | |
return ownedTokens[_owner][_index]; | |
} | |
/** | |
* @dev Gets the total amount of tokens stored by the contract | |
* @return uint256 representing the total amount of tokens | |
*/ | |
function totalSupply() public view returns (uint256) { | |
return allTokens.length; | |
} | |
/** | |
* @dev Gets the token ID at a given index of all the tokens in this contract | |
* @dev Reverts if the index is greater or equal to the total number of tokens | |
* @param _index uint256 representing the index to be accessed of the tokens list | |
* @return uint256 token ID at the given index of the tokens list | |
*/ | |
function tokenByIndex(uint256 _index) public view returns (uint256) { | |
require(_index < totalSupply()); | |
return allTokens[_index]; | |
} | |
/** | |
* @dev Internal function to set the token URI for a given token | |
* @dev Reverts if the token ID does not exist | |
* @param _tokenId uint256 ID of the token to set its URI | |
* @param _uri string URI to assign | |
*/ | |
function _setTokenURI(uint256 _tokenId, string _uri) internal { | |
require(exists(_tokenId)); | |
tokenURIs[_tokenId] = _uri; | |
} | |
/** | |
* @dev Internal function to add a token ID to the list of a given address | |
* @param _to address representing the new owner of the given token ID | |
* @param _tokenId uint256 ID of the token to be added to the tokens list of the given address | |
*/ | |
function addTokenTo(address _to, uint256 _tokenId) internal { | |
super.addTokenTo(_to, _tokenId); | |
uint256 length = ownedTokens[_to].length; | |
ownedTokens[_to].push(_tokenId); | |
ownedTokensIndex[_tokenId] = length; | |
} | |
/** | |
* @dev Internal function to remove a token ID from the list of a given address | |
* @param _from address representing the previous owner of the given token ID | |
* @param _tokenId uint256 ID of the token to be removed from the tokens list of the given address | |
*/ | |
function removeTokenFrom(address _from, uint256 _tokenId) internal { | |
super.removeTokenFrom(_from, _tokenId); | |
uint256 tokenIndex = ownedTokensIndex[_tokenId]; | |
uint256 lastTokenIndex = ownedTokens[_from].length.sub(1); | |
uint256 lastToken = ownedTokens[_from][lastTokenIndex]; | |
ownedTokens[_from][tokenIndex] = lastToken; | |
ownedTokens[_from][lastTokenIndex] = 0; | |
// Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to | |
// be zero. Then we can make sure that we will remove _tokenId from the ownedTokens list since we are first swapping | |
// the lastToken to the first position, and then dropping the element placed in the last position of the list | |
ownedTokens[_from].length--; | |
ownedTokensIndex[_tokenId] = 0; | |
ownedTokensIndex[lastToken] = tokenIndex; | |
} | |
/** | |
* @dev Internal function to mint a new token | |
* @dev Reverts if the given token ID already exists | |
* @param _to address the beneficiary that will own the minted token | |
* @param _tokenId uint256 ID of the token to be minted by the msg.sender | |
*/ | |
function _mint(address _to, uint256 _tokenId) internal { | |
super._mint(_to, _tokenId); | |
allTokensIndex[_tokenId] = allTokens.length; | |
allTokens.push(_tokenId); | |
} | |
/** | |
* @dev Internal function to burn a specific token | |
* @dev Reverts if the token does not exist | |
* @param _owner owner of the token to burn | |
* @param _tokenId uint256 ID of the token being burned by the msg.sender | |
*/ | |
function _burn(address _owner, uint256 _tokenId) internal { | |
super._burn(_owner, _tokenId); | |
// Clear metadata (if any) | |
if (bytes(tokenURIs[_tokenId]).length != 0) { | |
delete tokenURIs[_tokenId]; | |
} | |
// Reorg all tokens array | |
uint256 tokenIndex = allTokensIndex[_tokenId]; | |
uint256 lastTokenIndex = allTokens.length.sub(1); | |
uint256 lastToken = allTokens[lastTokenIndex]; | |
allTokens[tokenIndex] = lastToken; | |
allTokens[lastTokenIndex] = 0; | |
allTokens.length--; | |
allTokensIndex[_tokenId] = 0; | |
allTokensIndex[lastToken] = tokenIndex; | |
} | |
} |
This file contains 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; | |
import "./MintableToken.sol"; | |
import "./DetailedERC20.sol"; | |
/** | |
* The InvestorToken contract creates new ERC20 that property investors will hold | |
*/ | |
contract InvestorToken is MintableToken, DetailedERC20 { | |
constructor( | |
string _name, | |
string _symbol, | |
uint8 _decimals) | |
DetailedERC20( | |
_name, | |
_symbol, | |
_decimals) public {} | |
} |
This file contains 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.23; | |
import "./StandardToken.sol"; | |
import "./Ownable.sol"; | |
/** | |
* @title Mintable token | |
* @dev Simple ERC20 Token example, with mintable token creation | |
* @dev Issue: * https://github.com/OpenZeppelin/openzeppelin-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, uint256 amount); | |
event MintFinished(); | |
bool public mintingFinished = false; | |
modifier canMint() { | |
require(!mintingFinished); | |
_; | |
} | |
modifier hasMintPermission() { | |
require(msg.sender == owner); | |
_; | |
} | |
/** | |
* @dev Function to mint tokens | |
* @param _to The address that will receive 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, | |
uint256 _amount | |
) | |
hasMintPermission | |
canMint | |
public | |
returns (bool) | |
{ | |
totalSupply_ = totalSupply_.add(_amount); | |
balances[_to] = balances[_to].add(_amount); | |
emit Mint(_to, _amount); | |
emit Transfer(address(0), _to, _amount); | |
return true; | |
} | |
/** | |
* @dev Function to stop minting new tokens. | |
* @return True if the operation was successful. | |
*/ | |
function finishMinting() onlyOwner canMint public returns (bool) { | |
mintingFinished = true; | |
emit MintFinished(); | |
return true; | |
} | |
} |
This file contains 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.23; | |
/** | |
* @title Ownable | |
* @dev The Ownable contract has an owner address, and provides basic authorization control | |
* functions, this simplifies the implementation of "user permissions". | |
*/ | |
contract Ownable { | |
address public owner; | |
event OwnershipRenounced(address indexed previousOwner); | |
event OwnershipTransferred( | |
address indexed previousOwner, | |
address indexed newOwner | |
); | |
/** | |
* @dev The Ownable constructor sets the original `owner` of the contract to the sender | |
* account. | |
*/ | |
constructor() public { | |
owner = msg.sender; | |
} | |
/** | |
* @dev Throws if called by any account other than the owner. | |
*/ | |
modifier onlyOwner() { | |
require(msg.sender == owner); | |
_; | |
} | |
/** | |
* @dev Allows the current owner to relinquish control of the contract. | |
*/ | |
function renounceOwnership() public onlyOwner { | |
emit OwnershipRenounced(owner); | |
owner = address(0); | |
} | |
/** | |
* @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 { | |
_transferOwnership(_newOwner); | |
} | |
/** | |
* @dev Transfers control of the contract to a newOwner. | |
* @param _newOwner The address to transfer ownership to. | |
*/ | |
function _transferOwnership(address _newOwner) internal { | |
require(_newOwner != address(0)); | |
emit OwnershipTransferred(owner, _newOwner); | |
owner = _newOwner; | |
} | |
} |
This file contains 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.23; | |
import "./Ownable.sol"; | |
/** | |
* @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 make a function callable only when the contract is not paused. | |
*/ | |
modifier whenNotPaused() { | |
require(!paused); | |
_; | |
} | |
/** | |
* @dev Modifier to make a function callable only when the contract is paused. | |
*/ | |
modifier whenPaused() { | |
require(paused); | |
_; | |
} | |
/** | |
* @dev called by the owner to pause, triggers stopped state | |
*/ | |
function pause() onlyOwner whenNotPaused public { | |
paused = true; | |
emit Pause(); | |
} | |
/** | |
* @dev called by the owner to unpause, returns to normal state | |
*/ | |
function unpause() onlyOwner whenPaused public { | |
paused = false; | |
emit Unpause(); | |
} | |
} |
This file contains 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.23; | |
import "./StandardToken.sol"; | |
import "./Pausable.sol"; | |
/** | |
* @title Pausable token | |
* @dev StandardToken modified with pausable transfers. | |
**/ | |
contract PausableToken is StandardToken, Pausable { | |
function transfer( | |
address _to, | |
uint256 _value | |
) | |
public | |
whenNotPaused | |
returns (bool) | |
{ | |
return super.transfer(_to, _value); | |
} | |
function transferFrom( | |
address _from, | |
address _to, | |
uint256 _value | |
) | |
public | |
whenNotPaused | |
returns (bool) | |
{ | |
return super.transferFrom(_from, _to, _value); | |
} | |
function approve( | |
address _spender, | |
uint256 _value | |
) | |
public | |
whenNotPaused | |
returns (bool) | |
{ | |
return super.approve(_spender, _value); | |
} | |
function increaseApproval( | |
address _spender, | |
uint _addedValue | |
) | |
public | |
whenNotPaused | |
returns (bool success) | |
{ | |
return super.increaseApproval(_spender, _addedValue); | |
} | |
function decreaseApproval( | |
address _spender, | |
uint _subtractedValue | |
) | |
public | |
whenNotPaused | |
returns (bool success) | |
{ | |
return super.decreaseApproval(_spender, _subtractedValue); | |
} | |
} |
This file contains 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; | |
import "./ERC721Token.sol"; | |
import "./InvestorToken.sol"; | |
import "./Ownable.sol"; | |
/** | |
* The PropertyToken contract creates ERC721 tokens for each property | |
*/ | |
contract PropertyToken is ERC721Token("SaroProperty", "SARO"), Ownable { | |
string hashIPFS; | |
/** | |
* @dev Creates an ERC20 contract | |
* @param _tokenName Name of the ERC20 token | |
* @param _tokenSymbol ID of the ERC20 token | |
* @param _tokenDecimals The total Supply of the token | |
*/ | |
function makeInvestorToken(string _tokenName, string _tokenSymbol, uint8 _tokenDecimals) public onlyOwner { | |
InvestorToken iToken = new InvestorToken(_tokenName, _tokenSymbol, _tokenDecimals); | |
_mintTokens(iToken); | |
} | |
/** | |
* @dev Mints the total supply to the owner | |
* @param _iToken Token Contract created by Property ERC-721 | |
*/ | |
function _mintTokens(InvestorToken _iToken) private onlyOwner { | |
uint256 tokenSupply = _iToken.totalSupply(); | |
_iToken.mint(msg.sender, tokenSupply); | |
} | |
/** | |
* @dev Sets hashIPFS to a new hash | |
* @param newHashIPFS IPFS Hash owner wants the value to be | |
*/ | |
function setIPFShash(string newHashIPFS) public onlyOwner { | |
hashIPFS = newHashIPFS; | |
} | |
} |
This file contains 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.23; | |
import "./Roles.sol"; | |
/** | |
* @title RBAC (Role-Based Access Control) | |
* @author Matt Condon (@Shrugs) | |
* @dev Stores and provides setters and getters for roles and addresses. | |
* @dev Supports unlimited numbers of roles and addresses. | |
* @dev See //contracts/mocks/RBACMock.sol for an example of usage. | |
* This RBAC method uses strings to key roles. It may be beneficial | |
* for you to write your own implementation of this interface using Enums or similar. | |
* It's also recommended that you define constants in the contract, like ROLE_ADMIN below, | |
* to avoid typos. | |
*/ | |
contract RBAC { | |
using Roles for Roles.Role; | |
mapping (string => Roles.Role) private roles; | |
event RoleAdded(address addr, string roleName); | |
event RoleRemoved(address addr, string roleName); | |
/** | |
* @dev reverts if addr does not have role | |
* @param addr address | |
* @param roleName the name of the role | |
* // reverts | |
*/ | |
function checkRole(address addr, string roleName) | |
view | |
public | |
{ | |
roles[roleName].check(addr); | |
} | |
/** | |
* @dev determine if addr has role | |
* @param addr address | |
* @param roleName the name of the role | |
* @return bool | |
*/ | |
function hasRole(address addr, string roleName) | |
view | |
public | |
returns (bool) | |
{ | |
return roles[roleName].has(addr); | |
} | |
/** | |
* @dev add a role to an address | |
* @param addr address | |
* @param roleName the name of the role | |
*/ | |
function addRole(address addr, string roleName) | |
internal | |
{ | |
roles[roleName].add(addr); | |
emit RoleAdded(addr, roleName); | |
} | |
/** | |
* @dev remove a role from an address | |
* @param addr address | |
* @param roleName the name of the role | |
*/ | |
function removeRole(address addr, string roleName) | |
internal | |
{ | |
roles[roleName].remove(addr); | |
emit RoleRemoved(addr, roleName); | |
} | |
/** | |
* @dev modifier to scope access to a single role (uses msg.sender as addr) | |
* @param roleName the name of the role | |
* // reverts | |
*/ | |
modifier onlyRole(string roleName) | |
{ | |
checkRole(msg.sender, roleName); | |
_; | |
} | |
/** | |
* @dev modifier to scope access to a set of roles (uses msg.sender as addr) | |
* @param roleNames the names of the roles to scope access to | |
* // reverts | |
* | |
* @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this | |
* see: https://github.com/ethereum/solidity/issues/2467 | |
*/ | |
// modifier onlyRoles(string[] roleNames) { | |
// bool hasAnyRole = false; | |
// for (uint8 i = 0; i < roleNames.length; i++) { | |
// if (hasRole(msg.sender, roleNames[i])) { | |
// hasAnyRole = true; | |
// break; | |
// } | |
// } | |
// require(hasAnyRole); | |
// _; | |
// } | |
} |
This file contains 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.23; | |
import "./MintableToken.sol"; | |
import "./RBAC.sol"; | |
/** | |
* @title RBACMintableToken | |
* @author Vittorio Minacori (@vittominacori) | |
* @dev Mintable Token, with RBAC minter permissions | |
*/ | |
contract RBACMintableToken is MintableToken, RBAC { | |
/** | |
* A constant role name for indicating minters. | |
*/ | |
string public constant ROLE_MINTER = "minter"; | |
/** | |
* @dev override the Mintable token modifier to add role based logic | |
*/ | |
modifier hasMintPermission() { | |
checkRole(msg.sender, ROLE_MINTER); | |
_; | |
} | |
/** | |
* @dev add a minter role to an address | |
* @param minter address | |
*/ | |
function addMinter(address minter) onlyOwner public { | |
addRole(minter, ROLE_MINTER); | |
} | |
/** | |
* @dev remove a minter role from an address | |
* @param minter address | |
*/ | |
function removeMinter(address minter) onlyOwner public { | |
removeRole(minter, ROLE_MINTER); | |
} | |
} |
This file contains 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.23; | |
/** | |
* @title Roles | |
* @author Francisco Giordano (@frangio) | |
* @dev Library for managing addresses assigned to a Role. | |
* See RBAC.sol for example usage. | |
*/ | |
library Roles { | |
struct Role { | |
mapping (address => bool) bearer; | |
} | |
/** | |
* @dev give an address access to this role | |
*/ | |
function add(Role storage role, address addr) | |
internal | |
{ | |
role.bearer[addr] = true; | |
} | |
/** | |
* @dev remove an address' access to this role | |
*/ | |
function remove(Role storage role, address addr) | |
internal | |
{ | |
role.bearer[addr] = false; | |
} | |
/** | |
* @dev check if an address has this role | |
* // reverts | |
*/ | |
function check(Role storage role, address addr) | |
view | |
internal | |
{ | |
require(has(role, addr)); | |
} | |
/** | |
* @dev check if an address has this role | |
* @return bool | |
*/ | |
function has(Role storage role, address addr) | |
view | |
internal | |
returns (bool) | |
{ | |
return role.bearer[addr]; | |
} | |
} |
This file contains 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.23; | |
import "./ERC20Basic.sol"; | |
import "./ERC20.sol"; | |
/** | |
* @title SafeERC20 | |
* @dev Wrappers around ERC20 operations that throw on failure. | |
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, | |
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc. | |
*/ | |
library SafeERC20 { | |
function safeTransfer(ERC20Basic token, address to, uint256 value) internal { | |
require(token.transfer(to, value)); | |
} | |
function safeTransferFrom( | |
ERC20 token, | |
address from, | |
address to, | |
uint256 value | |
) | |
internal | |
{ | |
require(token.transferFrom(from, to, value)); | |
} | |
function safeApprove(ERC20 token, address spender, uint256 value) internal { | |
require(token.approve(spender, value)); | |
} | |
} |
This file contains 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.23; | |
/** | |
* @title SafeMath | |
* @dev Math operations with safety checks that throw on error | |
*/ | |
library SafeMath { | |
/** | |
* @dev Multiplies two numbers, throws on overflow. | |
*/ | |
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
// Gas optimization: this is cheaper than asserting '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; | |
} | |
c = a * b; | |
assert(c / a == b); | |
return c; | |
} | |
/** | |
* @dev Integer division of two numbers, truncating the quotient. | |
*/ | |
function div(uint256 a, uint256 b) internal pure returns (uint256) { | |
// assert(b > 0); // Solidity automatically throws when dividing by 0 | |
// uint256 c = a / b; | |
// assert(a == b * c + a % b); // There is no case in which this doesn't hold | |
return a / b; | |
} | |
/** | |
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). | |
*/ | |
function sub(uint256 a, uint256 b) internal pure returns (uint256) { | |
assert(b <= a); | |
return a - b; | |
} | |
/** | |
* @dev Adds two numbers, throws on overflow. | |
*/ | |
function add(uint256 a, uint256 b) internal pure returns (uint256 c) { | |
c = a + b; | |
assert(c >= a); | |
return c; | |
} | |
} |
This file contains 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.23; | |
import "./BurnableToken.sol"; | |
import "./StandardToken.sol"; | |
/** | |
* @title Standard Burnable Token | |
* @dev Adds burnFrom method to ERC20 implementations | |
*/ | |
contract StandardBurnableToken is BurnableToken, StandardToken { | |
/** | |
* @dev Burns a specific amount of tokens from the target address and decrements allowance | |
* @param _from address The address which you want to send tokens from | |
* @param _value uint256 The amount of token to be burned | |
*/ | |
function burnFrom(address _from, uint256 _value) public { | |
require(_value <= allowed[_from][msg.sender]); | |
// Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted, | |
// this function needs to emit an event with the updated approval. | |
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); | |
_burn(_from, _value); | |
} | |
} |
This file contains 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.23; | |
import "./BasicToken.sol"; | |
import "./ERC20.sol"; | |
/** | |
* @title Standard ERC20 token | |
* | |
* @dev Implementation of the basic standard 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 ERC20, BasicToken { | |
mapping (address => mapping (address => uint256)) internal 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 uint256 the amount of tokens to be transferred | |
*/ | |
function transferFrom( | |
address _from, | |
address _to, | |
uint256 _value | |
) | |
public | |
returns (bool) | |
{ | |
require(_to != address(0)); | |
require(_value <= balances[_from]); | |
require(_value <= allowed[_from][msg.sender]); | |
balances[_from] = balances[_from].sub(_value); | |
balances[_to] = balances[_to].add(_value); | |
allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); | |
emit Transfer(_from, _to, _value); | |
return true; | |
} | |
/** | |
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. | |
* | |
* 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 | |
* @param _spender The address which will spend the funds. | |
* @param _value The amount of tokens to be spent. | |
*/ | |
function approve(address _spender, uint256 _value) public returns (bool) { | |
allowed[msg.sender][_spender] = _value; | |
emit Approval(msg.sender, _spender, _value); | |
return true; | |
} | |
/** | |
* @dev Function to check the amount of tokens that 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 uint256 specifying the amount of tokens still available for the spender. | |
*/ | |
function allowance( | |
address _owner, | |
address _spender | |
) | |
public | |
view | |
returns (uint256) | |
{ | |
return allowed[_owner][_spender]; | |
} | |
/** | |
* @dev Increase the amount of tokens that an owner allowed to a spender. | |
* | |
* approve should be called when allowed[_spender] == 0. To increment | |
* allowed value is better to use this function to avoid 2 calls (and wait until | |
* the first transaction is mined) | |
* From MonolithDAO Token.sol | |
* @param _spender The address which will spend the funds. | |
* @param _addedValue The amount of tokens to increase the allowance by. | |
*/ | |
function increaseApproval( | |
address _spender, | |
uint _addedValue | |
) | |
public | |
returns (bool) | |
{ | |
allowed[msg.sender][_spender] = ( | |
allowed[msg.sender][_spender].add(_addedValue)); | |
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); | |
return true; | |
} | |
/** | |
* @dev Decrease the amount of tokens that an owner allowed to a spender. | |
* | |
* approve should be called when allowed[_spender] == 0. To decrement | |
* allowed value is better to use this function to avoid 2 calls (and wait until | |
* the first transaction is mined) | |
* From MonolithDAO Token.sol | |
* @param _spender The address which will spend the funds. | |
* @param _subtractedValue The amount of tokens to decrease the allowance by. | |
*/ | |
function decreaseApproval( | |
address _spender, | |
uint _subtractedValue | |
) | |
public | |
returns (bool) | |
{ | |
uint oldValue = allowed[msg.sender][_spender]; | |
if (_subtractedValue > oldValue) { | |
allowed[msg.sender][_spender] = 0; | |
} else { | |
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue); | |
} | |
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); | |
return true; | |
} | |
} |
This file contains 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.23; | |
import "./SafeERC20.sol"; | |
/** | |
* @title TokenTimelock | |
* @dev TokenTimelock is a token holder contract that will allow a | |
* beneficiary to extract the tokens after a given release time | |
*/ | |
contract TokenTimelock { | |
using SafeERC20 for ERC20Basic; | |
// ERC20 basic token contract being held | |
ERC20Basic public token; | |
// beneficiary of tokens after they are released | |
address public beneficiary; | |
// timestamp when token release is enabled | |
uint256 public releaseTime; | |
constructor( | |
ERC20Basic _token, | |
address _beneficiary, | |
uint256 _releaseTime | |
) | |
public | |
{ | |
// solium-disable-next-line security/no-block-members | |
require(_releaseTime > block.timestamp); | |
token = _token; | |
beneficiary = _beneficiary; | |
releaseTime = _releaseTime; | |
} | |
/** | |
* @notice Transfers tokens held by timelock to beneficiary. | |
*/ | |
function release() public { | |
// solium-disable-next-line security/no-block-members | |
require(block.timestamp >= releaseTime); | |
uint256 amount = token.balanceOf(this); | |
require(amount > 0); | |
token.safeTransfer(beneficiary, amount); | |
} | |
} |
This file contains 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
/* solium-disable security/no-block-members */ | |
pragma solidity ^0.4.23; | |
import "./ERC20Basic.sol"; | |
import "./SafeERC20.sol"; | |
import "./Ownable.sol"; | |
import ".SafeMath.sol"; | |
/** | |
* @title TokenVesting | |
* @dev A token holder contract that can release its token balance gradually like a | |
* typical vesting scheme, with a cliff and vesting period. Optionally revocable by the | |
* owner. | |
*/ | |
contract TokenVesting is Ownable { | |
using SafeMath for uint256; | |
using SafeERC20 for ERC20Basic; | |
event Released(uint256 amount); | |
event Revoked(); | |
// beneficiary of tokens after they are released | |
address public beneficiary; | |
uint256 public cliff; | |
uint256 public start; | |
uint256 public duration; | |
bool public revocable; | |
mapping (address => uint256) public released; | |
mapping (address => bool) public revoked; | |
/** | |
* @dev Creates a vesting contract that vests its balance of any ERC20 token to the | |
* _beneficiary, gradually in a linear fashion until _start + _duration. By then all | |
* of the balance will have vested. | |
* @param _beneficiary address of the beneficiary to whom vested tokens are transferred | |
* @param _cliff duration in seconds of the cliff in which tokens will begin to vest | |
* @param _start the time (as Unix time) at which point vesting starts | |
* @param _duration duration in seconds of the period in which the tokens will vest | |
* @param _revocable whether the vesting is revocable or not | |
*/ | |
constructor( | |
address _beneficiary, | |
uint256 _start, | |
uint256 _cliff, | |
uint256 _duration, | |
bool _revocable | |
) | |
public | |
{ | |
require(_beneficiary != address(0)); | |
require(_cliff <= _duration); | |
beneficiary = _beneficiary; | |
revocable = _revocable; | |
duration = _duration; | |
cliff = _start.add(_cliff); | |
start = _start; | |
} | |
/** | |
* @notice Transfers vested tokens to beneficiary. | |
* @param token ERC20 token which is being vested | |
*/ | |
function release(ERC20Basic token) public { | |
uint256 unreleased = releasableAmount(token); | |
require(unreleased > 0); | |
released[token] = released[token].add(unreleased); | |
token.safeTransfer(beneficiary, unreleased); | |
emit Released(unreleased); | |
} | |
/** | |
* @notice Allows the owner to revoke the vesting. Tokens already vested | |
* remain in the contract, the rest are returned to the owner. | |
* @param token ERC20 token which is being vested | |
*/ | |
function revoke(ERC20Basic token) public onlyOwner { | |
require(revocable); | |
require(!revoked[token]); | |
uint256 balance = token.balanceOf(this); | |
uint256 unreleased = releasableAmount(token); | |
uint256 refund = balance.sub(unreleased); | |
revoked[token] = true; | |
token.safeTransfer(owner, refund); | |
emit Revoked(); | |
} | |
/** | |
* @dev Calculates the amount that has already vested but hasn't been released yet. | |
* @param token ERC20 token which is being vested | |
*/ | |
function releasableAmount(ERC20Basic token) public view returns (uint256) { | |
return vestedAmount(token).sub(released[token]); | |
} | |
/** | |
* @dev Calculates the amount that has already vested. | |
* @param token ERC20 token which is being vested | |
*/ | |
function vestedAmount(ERC20Basic token) public view returns (uint256) { | |
uint256 currentBalance = token.balanceOf(this); | |
uint256 totalBalance = currentBalance.add(released[token]); | |
if (block.timestamp < cliff) { | |
return 0; | |
} else if (block.timestamp >= start.add(duration) || revoked[token]) { | |
return totalBalance; | |
} else { | |
return totalBalance.mul(block.timestamp.sub(start)).div(duration); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment