// File: zos-lib/contracts/Initializable.sol pragma solidity >=0.4.24 <0.6.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. uint256 cs; assembly { cs := extcodesize(address) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; } // File: zos-lib/contracts/application/ImplementationProvider.sol pragma solidity ^0.5.0; /** * @title ImplementationProvider * @dev Abstract contract for providing implementation addresses for other contracts by name. */ contract ImplementationProvider { /** * @dev Abstract function to return the implementation address of a contract. * @param contractName Name of the contract. * @return Implementation address of the contract. */ function getImplementation(string memory contractName) public view returns (address); } // File: zos-lib/contracts/ownership/Ownable.sol pragma solidity ^0.5.0; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". * * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/ownership/Ownable.sol * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the * build/artifacts folder) as well as the vanilla Ownable implementation from an openzeppelin version. */ contract ZOSLibOwnable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor () internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns (bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipTransferred(_owner, address(0)); _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; } } // File: zos-lib/contracts/application/Package.sol pragma solidity ^0.5.0; /** * @title Package * @dev A package is composed by a set of versions, identified via semantic versioning, * where each version has a contract address that refers to a reusable implementation, * plus an optional content URI with metadata. Note that the semver identifier is restricted * to major, minor, and patch, as prerelease tags are not supported. */ contract Package is ZOSLibOwnable { /** * @dev Emitted when a version is added to the package. * @param semanticVersion Name of the added version. * @param contractAddress Contract associated with the version. * @param contentURI Optional content URI with metadata of the version. */ event VersionAdded(uint64[3] semanticVersion, address contractAddress, bytes contentURI); struct Version { uint64[3] semanticVersion; address contractAddress; bytes contentURI; } mapping (bytes32 => Version) internal versions; mapping (uint64 => bytes32) internal majorToLatestVersion; uint64 internal latestMajor; /** * @dev Returns a version given its semver identifier. * @param semanticVersion Semver identifier of the version. * @return Contract address and content URI for the version, or zero if not exists. */ function getVersion(uint64[3] memory semanticVersion) public view returns (address contractAddress, bytes memory contentURI) { Version storage version = versions[semanticVersionHash(semanticVersion)]; return (version.contractAddress, version.contentURI); } /** * @dev Returns a contract for a version given its semver identifier. * This method is equivalent to `getVersion`, but returns only the contract address. * @param semanticVersion Semver identifier of the version. * @return Contract address for the version, or zero if not exists. */ function getContract(uint64[3] memory semanticVersion) public view returns (address contractAddress) { Version storage version = versions[semanticVersionHash(semanticVersion)]; return version.contractAddress; } /** * @dev Adds a new version to the package. Only the Owner can add new versions. * Reverts if the specified semver identifier already exists. * Emits a `VersionAdded` event if successful. * @param semanticVersion Semver identifier of the version. * @param contractAddress Contract address for the version, must be non-zero. * @param contentURI Optional content URI for the version. */ function addVersion(uint64[3] memory semanticVersion, address contractAddress, bytes memory contentURI) public onlyOwner { require(contractAddress != address(0), "Contract address is required"); require(!hasVersion(semanticVersion), "Given version is already registered in package"); require(!semanticVersionIsZero(semanticVersion), "Version must be non zero"); // Register version bytes32 versionId = semanticVersionHash(semanticVersion); versions[versionId] = Version(semanticVersion, contractAddress, contentURI); // Update latest major uint64 major = semanticVersion[0]; if (major > latestMajor) { latestMajor = semanticVersion[0]; } // Update latest version for this major uint64 minor = semanticVersion[1]; uint64 patch = semanticVersion[2]; uint64[3] storage latestVersionForMajor = versions[majorToLatestVersion[major]].semanticVersion; if (semanticVersionIsZero(latestVersionForMajor) // No latest was set for this major || (minor > latestVersionForMajor[1]) // Or current minor is greater || (minor == latestVersionForMajor[1] && patch > latestVersionForMajor[2]) // Or current patch is greater ) { majorToLatestVersion[major] = versionId; } emit VersionAdded(semanticVersion, contractAddress, contentURI); } /** * @dev Checks whether a version is present in the package. * @param semanticVersion Semver identifier of the version. * @return true if the version is registered in this package, false otherwise. */ function hasVersion(uint64[3] memory semanticVersion) public view returns (bool) { Version storage version = versions[semanticVersionHash(semanticVersion)]; return address(version.contractAddress) != address(0); } /** * @dev Returns the version with the highest semver identifier registered in the package. * For instance, if `1.2.0`, `1.3.0`, and `2.0.0` are present, will always return `2.0.0`, regardless * of the order in which they were registered. Returns zero if no versions are registered. * @return Semver identifier, contract address, and content URI for the version, or zero if not exists. */ function getLatest() public view returns (uint64[3] memory semanticVersion, address contractAddress, bytes memory contentURI) { return getLatestByMajor(latestMajor); } /** * @dev Returns the version with the highest semver identifier for the given major. * For instance, if `1.2.0`, `1.3.0`, and `2.0.0` are present, will return `1.3.0` for major `1`, * regardless of the order in which they were registered. Returns zero if no versions are registered * for the specified major. * @param major Major identifier to query * @return Semver identifier, contract address, and content URI for the version, or zero if not exists. */ function getLatestByMajor(uint64 major) public view returns (uint64[3] memory semanticVersion, address contractAddress, bytes memory contentURI) { Version storage version = versions[majorToLatestVersion[major]]; return (version.semanticVersion, version.contractAddress, version.contentURI); } function semanticVersionHash(uint64[3] memory version) internal pure returns (bytes32) { return keccak256(abi.encodePacked(version[0], version[1], version[2])); } function semanticVersionIsZero(uint64[3] memory version) internal pure returns (bool) { return version[0] == 0 && version[1] == 0 && version[2] == 0; } } // File: zos-lib/contracts/upgradeability/Proxy.sol pragma solidity ^0.5.0; /** * @title Proxy * @dev Implements delegation of calls to other contracts, with proper * forwarding of return values and bubbling of failures. * It defines a fallback function that delegates all calls to the address * returned by the abstract _implementation() internal function. */ contract Proxy { /** * @dev Fallback function. * Implemented entirely in `_fallback`. */ function () payable external { _fallback(); } /** * @return The Address of the implementation. */ function _implementation() internal view returns (address); /** * @dev Delegates execution to an implementation contract. * This is a low level function that doesn't return to its internal call site. * It will return to the external caller whatever the implementation returns. * @param implementation Address to delegate. */ function _delegate(address implementation) internal { assembly { // Copy msg.data. We take full control of memory in this inline assembly // block because it will not return to Solidity code. We overwrite the // Solidity scratch pad at memory position 0. calldatacopy(0, 0, calldatasize) // Call the implementation. // out and outsize are 0 because we don't know the size yet. let result := delegatecall(gas, implementation, 0, calldatasize, 0, 0) // Copy the returned data. returndatacopy(0, 0, returndatasize) switch result // delegatecall returns 0 on error. case 0 { revert(0, returndatasize) } default { return(0, returndatasize) } } } /** * @dev Function that is run as the first thing in the fallback function. * Can be redefined in derived contracts to add functionality. * Redefinitions must call super._willFallback(). */ function _willFallback() internal { } /** * @dev fallback implementation. * Extracted to enable manual triggering. */ function _fallback() internal { _willFallback(); _delegate(_implementation()); } } // File: zos-lib/contracts/utils/Address.sol pragma solidity ^0.5.0; /** * Utility library of inline functions on addresses * * Source https://raw.githubusercontent.com/OpenZeppelin/openzeppelin-solidity/v2.1.3/contracts/utils/Address.sol * This contract is copied here and renamed from the original to avoid clashes in the compiled artifacts * when the user imports a zos-lib contract (that transitively causes this contract to be compiled and added to the * build/artifacts folder) as well as the vanilla Address implementation from an openzeppelin version. */ library ZOSLibAddress { /** * 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 account address of the account to check * @return whether the target address is a contract */ function isContract(address account) 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. // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } // File: zos-lib/contracts/upgradeability/BaseUpgradeabilityProxy.sol pragma solidity ^0.5.0; /** * @title BaseUpgradeabilityProxy * @dev This contract implements a proxy that allows to change the * implementation address to which it will delegate. * Such a change is called an implementation upgrade. */ contract BaseUpgradeabilityProxy is Proxy { /** * @dev Emitted when the implementation is upgraded. * @param implementation Address of the new implementation. */ event Upgraded(address indexed implementation); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "org.zeppelinos.proxy.implementation", and is * validated in the constructor. */ bytes32 internal constant IMPLEMENTATION_SLOT = 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3; /** * @dev Returns the current implementation. * @return Address of the current implementation */ function _implementation() internal view returns (address impl) { bytes32 slot = IMPLEMENTATION_SLOT; assembly { impl := sload(slot) } } /** * @dev Upgrades the proxy to a new implementation. * @param newImplementation Address of the new implementation. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Sets the implementation address of the proxy. * @param newImplementation Address of the new implementation. */ function _setImplementation(address newImplementation) internal { require(ZOSLibAddress.isContract(newImplementation), "Cannot set a proxy implementation to a non-contract address"); bytes32 slot = IMPLEMENTATION_SLOT; assembly { sstore(slot, newImplementation) } } } // File: zos-lib/contracts/upgradeability/UpgradeabilityProxy.sol pragma solidity ^0.5.0; /** * @title UpgradeabilityProxy * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing * implementation and init data. */ contract UpgradeabilityProxy is BaseUpgradeabilityProxy { /** * @dev Contract constructor. * @param _logic Address of the initial implementation. * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. */ constructor(address _logic, bytes memory _data) public payable { assert(IMPLEMENTATION_SLOT == keccak256("org.zeppelinos.proxy.implementation")); _setImplementation(_logic); if(_data.length > 0) { (bool success,) = _logic.delegatecall(_data); require(success); } } } // File: zos-lib/contracts/upgradeability/BaseAdminUpgradeabilityProxy.sol pragma solidity ^0.5.0; /** * @title BaseAdminUpgradeabilityProxy * @dev This contract combines an upgradeability proxy with an authorization * mechanism for administrative tasks. * All external functions in this contract must be guarded by the * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity * feature proposal that would enable this to be done automatically. */ contract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy { /** * @dev Emitted when the administration has been transferred. * @param previousAdmin Address of the previous admin. * @param newAdmin Address of the new admin. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "org.zeppelinos.proxy.admin", and is * validated in the constructor. */ bytes32 internal constant ADMIN_SLOT = 0x10d6a54a4754c8869d6886b5f5d7fbfa5b4522237ea5c60d11bc4e7a1ff9390b; /** * @dev Modifier to check whether the `msg.sender` is the admin. * If it is, it will run the function. Otherwise, it will delegate the call * to the implementation. */ modifier ifAdmin() { if (msg.sender == _admin()) { _; } else { _fallback(); } } /** * @return The address of the proxy admin. */ function admin() external ifAdmin returns (address) { return _admin(); } /** * @return The address of the implementation. */ function implementation() external ifAdmin returns (address) { return _implementation(); } /** * @dev Changes the admin of the proxy. * Only the current admin can call this function. * @param newAdmin Address to transfer proxy administration to. */ function changeAdmin(address newAdmin) external ifAdmin { require(newAdmin != address(0), "Cannot change the admin of a proxy to the zero address"); emit AdminChanged(_admin(), newAdmin); _setAdmin(newAdmin); } /** * @dev Upgrade the backing implementation of the proxy. * Only the admin can call this function. * @param newImplementation Address of the new implementation. */ function upgradeTo(address newImplementation) external ifAdmin { _upgradeTo(newImplementation); } /** * @dev Upgrade the backing implementation of the proxy and call a function * on the new implementation. * This is useful to initialize the proxied contract. * @param newImplementation Address of the new implementation. * @param data Data to send as msg.data in the low level call. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. */ function upgradeToAndCall(address newImplementation, bytes calldata data) payable external ifAdmin { _upgradeTo(newImplementation); (bool success,) = newImplementation.delegatecall(data); require(success); } /** * @return The admin slot. */ function _admin() internal view returns (address adm) { bytes32 slot = ADMIN_SLOT; assembly { adm := sload(slot) } } /** * @dev Sets the address of the proxy admin. * @param newAdmin Address of the new proxy admin. */ function _setAdmin(address newAdmin) internal { bytes32 slot = ADMIN_SLOT; assembly { sstore(slot, newAdmin) } } /** * @dev Only fall back when the sender is not the admin. */ function _willFallback() internal { require(msg.sender != _admin(), "Cannot call fallback function from the proxy admin"); super._willFallback(); } } // File: zos-lib/contracts/upgradeability/AdminUpgradeabilityProxy.sol pragma solidity ^0.5.0; /** * @title AdminUpgradeabilityProxy * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for * initializing the implementation, admin, and init data. */ contract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy { /** * Contract constructor. * @param _logic address of the initial implementation. * @param _admin Address of the proxy administrator. * @param _data Data to send as msg.data to the implementation to initialize the proxied contract. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. */ constructor(address _logic, address _admin, bytes memory _data) UpgradeabilityProxy(_logic, _data) public payable { assert(ADMIN_SLOT == keccak256("org.zeppelinos.proxy.admin")); _setAdmin(_admin); } } // File: zos-lib/contracts/application/App.sol pragma solidity ^0.5.0; /** * @title App * @dev Contract for upgradeable applications. * It handles the creation of proxies. */ contract App is ZOSLibOwnable { /** * @dev Emitted when a new proxy is created. * @param proxy Address of the created proxy. */ event ProxyCreated(address proxy); /** * @dev Emitted when a package dependency is changed in the application. * @param providerName Name of the package that changed. * @param package Address of the package associated to the name. * @param version Version of the package in use. */ event PackageChanged(string providerName, address package, uint64[3] version); /** * @dev Tracks a package in a particular version, used for retrieving implementations */ struct ProviderInfo { Package package; uint64[3] version; } /** * @dev Maps from dependency name to a tuple of package and version */ mapping(string => ProviderInfo) internal providers; /** * @dev Constructor function. */ constructor() public { } /** * @dev Returns the provider for a given package name, or zero if not set. * @param packageName Name of the package to be retrieved. * @return The provider. */ function getProvider(string memory packageName) public view returns (ImplementationProvider provider) { ProviderInfo storage info = providers[packageName]; if (address(info.package) == address(0)) return ImplementationProvider(0); return ImplementationProvider(info.package.getContract(info.version)); } /** * @dev Returns information on a package given its name. * @param packageName Name of the package to be queried. * @return A tuple with the package address and pinned version given a package name, or zero if not set */ function getPackage(string memory packageName) public view returns (Package, uint64[3] memory) { ProviderInfo storage info = providers[packageName]; return (info.package, info.version); } /** * @dev Sets a package in a specific version as a dependency for this application. * Requires the version to be present in the package. * @param packageName Name of the package to set or overwrite. * @param package Address of the package to register. * @param version Version of the package to use in this application. */ function setPackage(string memory packageName, Package package, uint64[3] memory version) public onlyOwner { require(package.hasVersion(version), "The requested version must be registered in the given package"); providers[packageName] = ProviderInfo(package, version); emit PackageChanged(packageName, address(package), version); } /** * @dev Unsets a package given its name. * Reverts if the package is not set in the application. * @param packageName Name of the package to remove. */ function unsetPackage(string memory packageName) public onlyOwner { require(address(providers[packageName].package) != address(0), "Package to unset not found"); delete providers[packageName]; emit PackageChanged(packageName, address(0), [uint64(0), uint64(0), uint64(0)]); } /** * @dev Returns the implementation address for a given contract name, provided by the `ImplementationProvider`. * @param packageName Name of the package where the contract is contained. * @param contractName Name of the contract. * @return Address where the contract is implemented. */ function getImplementation(string memory packageName, string memory contractName) public view returns (address) { ImplementationProvider provider = getProvider(packageName); if (address(provider) == address(0)) return address(0); return provider.getImplementation(contractName); } /** * @dev Creates a new proxy for the given contract and forwards a function call to it. * This is useful to initialize the proxied contract. * @param packageName Name of the package where the contract is contained. * @param contractName Name of the contract. * @param admin Address of the proxy administrator. * @param data Data to send as msg.data to the corresponding implementation to initialize the proxied contract. * It should include the signature and the parameters of the function to be called, as described in * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped. * @return Address of the new proxy. */ function create(string memory packageName, string memory contractName, address admin, bytes memory data) payable public returns (AdminUpgradeabilityProxy) { address implementation = getImplementation(packageName, contractName); AdminUpgradeabilityProxy proxy = (new AdminUpgradeabilityProxy).value(msg.value)(implementation, admin, data); emit ProxyCreated(address(proxy)); return proxy; } } // File: openzeppelin-eth/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.2; /** * @title ERC20 interface * @dev see https://eips.ethereum.org/EIPS/eip-20 */ interface IERC20 { 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); function totalSupply() external view returns (uint256); function balanceOf(address who) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } // File: openzeppelin-eth/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.2; /** * @title ERC20Detailed 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 ERC20Detailed is Initializable, IERC20 { string private _name; string private _symbol; uint8 private _decimals; function initialize(string memory name, string memory symbol, uint8 decimals) public initializer { _name = name; _symbol = symbol; _decimals = decimals; } /** * @return the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @return the symbol of the token. */ function symbol() public view returns (string memory) { return _symbol; } /** * @return the number of decimals of the token. */ function decimals() public view returns (uint8) { return _decimals; } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/math/SafeMath.sol pragma solidity ^0.5.2; /** * @title SafeMath * @dev Unsigned math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two unsigned integers, reverts on 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); return c; } /** * @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two unsigned integers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } // File: openzeppelin-eth/contracts/token/ERC20/ERC20.sol pragma solidity ^0.5.2; /** * @title Standard ERC20 token * * @dev Implementation of the basic standard token. * https://eips.ethereum.org/EIPS/eip-20 * Originally based on code by FirstBlood: * https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol * * This implementation emits additional Approval events, allowing applications to reconstruct the allowance status for * all accounts just by listening to said events. Note that this isn't required by the specification, and other * compliant implementations may not do it. */ contract ERC20 is Initializable, IERC20 { using SafeMath for uint256; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowed; uint256 private _totalSupply; /** * @dev Total number of tokens in existence */ function totalSupply() public view returns (uint256) { return _totalSupply; } /** * @dev Gets the balance of the specified address. * @param owner The address to query the balance of. * @return A uint256 representing the amount owned by the passed address. */ function balanceOf(address owner) public view returns (uint256) { return _balances[owner]; } /** * @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 Transfer token to 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) { _transfer(msg.sender, 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) { _approve(msg.sender, spender, value); return true; } /** * @dev Transfer tokens from one address to another. * Note that while this function emits an Approval event, this is not required as per the specification, * and other compliant implementations may not emit the event. * @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) { _transfer(from, to, value); _approve(from, msg.sender, _allowed[from][msg.sender].sub(value)); return true; } /** * @dev Increase the amount of tokens that an owner allowed to a spender. * approve should be called when _allowed[msg.sender][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 * Emits an Approval event. * @param spender The address which will spend the funds. * @param addedValue The amount of tokens to increase the allowance by. */ function increaseAllowance(address spender, uint256 addedValue) public returns (bool) { _approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue)); return true; } /** * @dev Decrease the amount of tokens that an owner allowed to a spender. * approve should be called when _allowed[msg.sender][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 * Emits an Approval event. * @param spender The address which will spend the funds. * @param subtractedValue The amount of tokens to decrease the allowance by. */ function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) { _approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue)); return true; } /** * @dev Transfer token for a specified addresses * @param from The address to transfer from. * @param to The address to transfer to. * @param value The amount to be transferred. */ function _transfer(address from, address to, uint256 value) internal { require(to != address(0)); _balances[from] = _balances[from].sub(value); _balances[to] = _balances[to].add(value); emit Transfer(from, to, value); } /** * @dev Internal function that mints an amount of the token and assigns it to * an account. This encapsulates the modification of balances such that the * proper events are emitted. * @param account The account that will receive the created tokens. * @param value The amount that will be created. */ function _mint(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.add(value); _balances[account] = _balances[account].add(value); emit Transfer(address(0), account, value); } /** * @dev Internal function that burns an amount of the token of a given * account. * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burn(address account, uint256 value) internal { require(account != address(0)); _totalSupply = _totalSupply.sub(value); _balances[account] = _balances[account].sub(value); emit Transfer(account, address(0), value); } /** * @dev Approve an address to spend another addresses' tokens. * @param owner The address that owns the tokens. * @param spender The address that will spend the tokens. * @param value The number of tokens that can be spent. */ function _approve(address owner, address spender, uint256 value) internal { require(spender != address(0)); require(owner != address(0)); _allowed[owner][spender] = value; emit Approval(owner, spender, value); } /** * @dev Internal function that burns an amount of the token of a given * account, deducting from the sender's allowance for said account. Uses the * internal burn function. * Emits an Approval event (reflecting the reduced allowance). * @param account The account whose tokens will be burnt. * @param value The amount that will be burnt. */ function _burnFrom(address account, uint256 value) internal { _burn(account, value); _approve(account, msg.sender, _allowed[account][msg.sender].sub(value)); } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/access/Roles.sol pragma solidity ^0.5.2; /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev give an account access to this role */ function add(Role storage role, address account) internal { require(account != address(0)); require(!has(role, account)); role.bearer[account] = true; } /** * @dev remove an account's access to this role */ function remove(Role storage role, address account) internal { require(account != address(0)); require(has(role, account)); role.bearer[account] = false; } /** * @dev check if an account has this role * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0)); return role.bearer[account]; } } // File: openzeppelin-eth/contracts/access/roles/MinterRole.sol pragma solidity ^0.5.2; contract MinterRole is Initializable { using Roles for Roles.Role; event MinterAdded(address indexed account); event MinterRemoved(address indexed account); Roles.Role private _minters; function initialize(address sender) public initializer { if (!isMinter(sender)) { _addMinter(sender); } } modifier onlyMinter() { require(isMinter(msg.sender)); _; } function isMinter(address account) public view returns (bool) { return _minters.has(account); } function addMinter(address account) public onlyMinter { _addMinter(account); } function renounceMinter() public { _removeMinter(msg.sender); } function _addMinter(address account) internal { _minters.add(account); emit MinterAdded(account); } function _removeMinter(address account) internal { _minters.remove(account); emit MinterRemoved(account); } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/token/ERC20/ERC20Mintable.sol pragma solidity ^0.5.2; /** * @title ERC20Mintable * @dev ERC20 minting logic */ contract ERC20Mintable is Initializable, ERC20, MinterRole { function initialize(address sender) public initializer { MinterRole.initialize(sender); } /** * @dev Function to mint tokens * @param to The address that will receive the minted tokens. * @param value The amount of tokens to mint. * @return A boolean that indicates if the operation was successful. */ function mint(address to, uint256 value) public onlyMinter returns (bool) { _mint(to, value); return true; } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/access/roles/PauserRole.sol pragma solidity ^0.5.2; contract PauserRole is Initializable { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; function initialize(address sender) public initializer { if (!isPauser(sender)) { _addPauser(sender); } } modifier onlyPauser() { require(isPauser(msg.sender)); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(msg.sender); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/lifecycle/Pausable.sol pragma solidity ^0.5.2; /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is Initializable, PauserRole { event Paused(address account); event Unpaused(address account); bool private _paused; function initialize(address sender) public initializer { PauserRole.initialize(sender); _paused = false; } /** * @return true if the contract is paused, false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @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() public onlyPauser whenNotPaused { _paused = true; emit Paused(msg.sender); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(msg.sender); } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/token/ERC20/ERC20Pausable.sol pragma solidity ^0.5.2; /** * @title Pausable token * @dev ERC20 modified with pausable transfers. */ contract ERC20Pausable is Initializable, ERC20, Pausable { function initialize(address sender) public initializer { Pausable.initialize(sender); } 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 increaseAllowance(address spender, uint addedValue) public whenNotPaused returns (bool success) { return super.increaseAllowance(spender, addedValue); } function decreaseAllowance(address spender, uint subtractedValue) public whenNotPaused returns (bool success) { return super.decreaseAllowance(spender, subtractedValue); } uint256[50] private ______gap; } // File: openzeppelin-eth/contracts/token/ERC20/StandaloneERC20.sol pragma solidity ^0.5.0; /** * @title Standard ERC20 token, with minting and pause functionality. * */ contract StandaloneERC20 is Initializable, ERC20Detailed, ERC20Mintable, ERC20Pausable { function initialize( string memory name, string memory symbol, uint8 decimals, uint256 initialSupply, address initialHolder, address[] memory minters, address[] memory pausers ) public initializer { ERC20Detailed.initialize(name, symbol, decimals); // Mint the initial supply _mint(initialHolder, initialSupply); // Initialize the minter and pauser roles, and renounce them ERC20Mintable.initialize(address(this)); _removeMinter(address(this)); ERC20Pausable.initialize(address(this)); _removePauser(address(this)); // Add the requested minters and pausers (this can be done after renouncing since // these are the internal calls) for (uint256 i = 0; i < minters.length; ++i) { _addMinter(minters[i]); } for (uint256 i = 0; i < pausers.length; ++i) { _addPauser(pausers[i]); } } function initialize( string memory name, string memory symbol, uint8 decimals, address[] memory minters, address[] memory pausers ) public initializer { ERC20Detailed.initialize(name, symbol, decimals); // Initialize the minter and pauser roles, and renounce them ERC20Mintable.initialize(address(this)); _removeMinter(address(this)); ERC20Pausable.initialize(address(this)); _removePauser(address(this)); // Add the requested minters and pausers (this can be done after renouncing since // these are the internal calls) for (uint256 i = 0; i < minters.length; ++i) { _addMinter(minters[i]); } for (uint256 i = 0; i < pausers.length; ++i) { _addPauser(pausers[i]); } } } // File: openzeppelin-eth/contracts/utils/Address.sol pragma solidity ^0.5.2; /** * Utility library of inline functions on addresses */ library Address { /** * 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 account address of the account to check * @return whether the target address is a contract */ function isContract(address account) 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. // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } // File: openzeppelin-eth/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.2; /** * @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 ERC20;` 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)); } 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' require((value == 0) || (token.allowance(address(this), spender) == 0)); 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); 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 equal true). * @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. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. require(address(token).isContract()); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool))); } } } // File: contracts/crowdloan/Crowdloan.sol pragma solidity 0.5.11; contract Crowdloan is Initializable { using SafeMath for uint256; using SafeERC20 for IERC20; // Loan terms uint256 public crowdfundStart; uint256 public crowdfundEnd; // Last time contributions are accepted uint256 public crowdfundDuration; address public borrower; IERC20 public token; uint256 public principalRequested; string public loanMetadataUrl; // Contributor tracking mapping(address => uint256) public amountContributed; uint256 public totalContributed; uint256 public principalWithdrawn; // Repayment tracking uint256 public amountRepaid; mapping(address => uint256) public repaymentWithdrawn; uint256 public totalRepaymentWithdrawn; // Events event Fund(address sender, uint256 amount); event WithdrawPrincipal(address borrower, uint256 amount); event WithdrawRepayment(address lender, uint256 amount); event Repay(uint256 amount); event StartCrowdfund(uint256 crowdfundStart); function initialize( address _borrower, IERC20 _token, uint256 _principalRequested, uint256 _duration, string calldata _loanMetadataUrl ) external initializer { borrower = _borrower; crowdfundDuration = _duration; token = _token; principalRequested = _principalRequested; loanMetadataUrl = _loanMetadataUrl; } /// @dev During the crowdfund, anyone can fund and get repayment rights in proportion to their contribution function fund(uint256 amount) external { _onlyAfterCrowdfundStart(); _onlyBeforeCrowdfundEnd(); require(amount > 0, "Fund amount cannot be zero"); totalContributed = totalContributed.add(amount); require( totalContributed <= principalRequested, "Your contribution would exceed the total amount requested." ); amountContributed[msg.sender] = amountContributed[msg.sender].add(amount); token.safeTransferFrom(msg.sender, address(this), amount); emit Fund(msg.sender, amount); } /// @dev Borrower can withdraw currently aquired principal in any proportion, and any time during the crowdfund for flexibility. /// This DOES NOT affect the total principal that can be raised or the loan terms, it merely provides cash flow. function withdrawPrincipal(uint256 amount) external { _onlyBorrower(); // FIX DONATIONS! uint256 tokenBalance = token.balanceOf(address(this)); require(amount <= tokenBalance, "Insufficent tokens to withdraw"); if (amountRepaid > 0) { require( tokenBalance.sub(amount) >= amountRepaid.sub(totalRepaymentWithdrawn), "Withdrawal will lead to repayment inbalance" ); } token.safeTransfer(msg.sender, amount); emit WithdrawPrincipal(msg.sender, amount); } /// @dev Anyone can make repayments on behalf of the borrower function repay(uint256 amount) external { _onlyAfterCrowdfundEnd(); require(amount > 0, "Repayment amount cannot be zero"); amountRepaid = amountRepaid.add(amount); token.safeTransferFrom(msg.sender, address(this), amount); emit Repay(amount); } /// @dev Lenders can withdraw their proportional stake from repayments after the crowdfund ends function withdrawRepayment() external { _onlyAfterCrowdfundEnd(); uint256 totalOwed = amountRepaid.mul(amountContributed[msg.sender]).div(totalContributed); uint256 amount = totalOwed.sub(repaymentWithdrawn[msg.sender]); require(amount > 0, "Withdrawal amount cannot be zero"); repaymentWithdrawn[msg.sender] = totalOwed; totalRepaymentWithdrawn = totalRepaymentWithdrawn.add(amount); token.safeTransfer(msg.sender, amount); emit WithdrawRepayment(msg.sender, amount); } /// @dev Borrower can start the crowdfund once function startCrowdfund() external { _onlyBorrower(); _onlyBeforeCrowdfundStart(); crowdfundStart = now; crowdfundEnd = now + crowdfundDuration; emit StartCrowdfund(now); } function _onlyBorrower() internal view { require(msg.sender == borrower, "Only the borrower can call function."); } function _onlyBeforeCrowdfundStart() internal view { require(crowdfundStart == 0, "Only before crowdfund start"); } function _onlyAfterCrowdfundStart() internal view { require(crowdfundStart != 0, "Only after crowdfund start"); } function _onlyBeforeCrowdfundEnd() internal view { require(now <= crowdfundEnd, "Only before crowdfund end"); } function _onlyAfterCrowdfundEnd() internal view { require(crowdfundStart != 0 && now > crowdfundEnd, "Only after crowdfund end."); } } // File: contracts/factory/CrowdloanFactory.sol pragma solidity 0.5.11; contract CrowdloanFactory is Initializable { string constant ENABLE_CREDIT_PACKAGE = "enable-credit"; string constant TERMS_CONTRACT = "TermsContract"; string constant CROWDLOAN = "Crowdloan"; string constant REPAYMENT_ROUTER = "RepaymentManager"; App public app; event LoanCreated( address indexed borrower, uint256 indexed principalRequested, address crowdloan, string loanMetadataUrl, address contractAdmin ); function initialize(address _appContractAddress) public initializer { app = App(_appContractAddress); } function _createCrowdloan(bytes memory _data, address admin) internal returns (address proxy) { return address(app.create(ENABLE_CREDIT_PACKAGE, CROWDLOAN, admin, _data)); } function deploy( IERC20 principalToken, uint256 principalRequested, uint256 crowdfundLength, string calldata loanMetadataUrl, address contractAdmin ) external { address crowdloan = _createCrowdloan("", contractAdmin); Crowdloan(crowdloan).initialize( msg.sender, principalToken, principalRequested, crowdfundLength, loanMetadataUrl ); emit LoanCreated(msg.sender, principalRequested, crowdloan, loanMetadataUrl, contractAdmin); } }