Skip to content

Instantly share code, notes, and snippets.

@Mikodes
Created February 18, 2020 10:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Mikodes/aacf6b0260ed94a36af175f64d0a44d1 to your computer and use it in GitHub Desktop.
Save Mikodes/aacf6b0260ed94a36af175f64d0a44d1 to your computer and use it in GitHub Desktop.
/**
*Submitted for verification at Etherscan.io on 2019-05-31
*/
/**
* Copyright 2017-2019, bZeroX, LLC. All Rights Reserved.
* Licensed under the Apache License, Version 2.0.
*/
pragma solidity 0.5.8;
/**
* @title ERC20Basic
* @dev Simpler version of ERC20 interface
* 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);
}
/**
* @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
);
}
contract WETHInterface is ERC20 {
function deposit() external payable;
function withdraw(uint256 wad) external;
}
/**
* @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 Integer division of two numbers, rounding up and truncating the quotient
*/
function divCeil(uint256 _a, uint256 _b) internal pure returns (uint256) {
if (_a == 0) {
return 0;
}
return ((_a - 1) / _b) + 1;
}
/**
* @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;
}
}
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) 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;
}
}
/**
* @title Helps contracts guard against reentrancy attacks.
* @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io>
* @dev If you mark a function `nonReentrant`, you should also
* mark it `external`.
*/
contract ReentrancyGuard {
/// @dev Constant for unlocked guard state - non-zero to prevent extra gas costs.
/// See: https://github.com/OpenZeppelin/openzeppelin-solidity/issues/1056
uint256 internal constant REENTRANCY_GUARD_FREE = 1;
/// @dev Constant for locked guard state
uint256 internal constant REENTRANCY_GUARD_LOCKED = 2;
/**
* @dev We use a single lock for the whole contract.
*/
uint256 internal reentrancyLock = REENTRANCY_GUARD_FREE;
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* If you mark a function `nonReentrant`, you should also
* mark it `external`. Calling one `nonReentrant` function from
* another is not supported. Instead, you can implement a
* `private` function doing the actual work, and an `external`
* wrapper marked as `nonReentrant`.
*/
modifier nonReentrant() {
require(reentrancyLock == REENTRANCY_GUARD_FREE, "nonReentrant");
reentrancyLock = REENTRANCY_GUARD_LOCKED;
_;
reentrancyLock = REENTRANCY_GUARD_FREE;
}
}
contract LoanTokenization is ReentrancyGuard, Ownable {
uint256 internal constant MAX_UINT = 2**256 - 1;
string public name;
string public symbol;
uint8 public decimals;
address public bZxContract;
address public bZxVault;
address public bZxOracle;
address public wethContract;
address public loanTokenAddress;
// price of token at last user checkpoint
mapping (address => uint256) internal checkpointPrices_;
}
contract LoanTokenStorage is LoanTokenization {
struct ListIndex {
uint256 index;
bool isSet;
}
struct LoanData {
bytes32 loanOrderHash;
uint256 leverageAmount;
uint256 initialMarginAmount;
uint256 maintenanceMarginAmount;
uint256 maxDurationUnixTimestampSec;
uint256 index;
}
struct TokenReserves {
address lender;
uint256 amount;
}
event Borrow(
address indexed borrower,
uint256 borrowAmount,
uint256 interestRate,
address collateralTokenAddress,
address tradeTokenToFillAddress,
bool withdrawOnOpen
);
event Claim(
address indexed claimant,
uint256 tokenAmount,
uint256 assetAmount,
uint256 remainingTokenAmount,
uint256 price
);
bool internal isInitialized_ = false;
address public tokenizedRegistry;
uint256 public baseRate = 1000000000000000000; // 1.0%
uint256 public rateMultiplier = 39000000000000000000; // 39%
// "fee percentage retained by the oracle" = SafeMath.sub(10**20, spreadMultiplier);
uint256 public spreadMultiplier;
mapping (uint256 => bytes32) public loanOrderHashes; // mapping of levergeAmount to loanOrderHash
mapping (bytes32 => LoanData) public loanOrderData; // mapping of loanOrderHash to LoanOrder
uint256[] public leverageList;
TokenReserves[] public burntTokenReserveList; // array of TokenReserves
mapping (address => ListIndex) public burntTokenReserveListIndex; // mapping of lender address to ListIndex objects
uint256 public burntTokenReserved; // total outstanding burnt token amount
address internal nextOwedLender_;
uint256 public totalAssetBorrow = 0; // current amount of loan token amount tied up in loans
uint256 internal checkpointSupply_;
uint256 internal lastSettleTime_;
uint256 public initialPrice;
}
contract AdvancedTokenStorage is LoanTokenStorage {
using SafeMath for uint256;
event Transfer(
address indexed from,
address indexed to,
uint256 value
);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Mint(
address indexed minter,
uint256 tokenAmount,
uint256 assetAmount,
uint256 price
);
event Burn(
address indexed burner,
uint256 tokenAmount,
uint256 assetAmount,
uint256 price
);
mapping(address => uint256) internal balances;
mapping (address => mapping (address => uint256)) internal allowed;
uint256 internal totalSupply_;
function totalSupply()
public
view
returns (uint256)
{
return totalSupply_;
}
function balanceOf(
address _owner)
public
view
returns (uint256)
{
return balances[_owner];
}
function allowance(
address _owner,
address _spender)
public
view
returns (uint256)
{
return allowed[_owner][_spender];
}
}
contract LoanToken is AdvancedTokenStorage {
address internal target_;
constructor(
address _newTarget)
public
{
_setTarget(_newTarget);
}
function()
external
payable
{
address target = target_;
bytes memory data = msg.data;
assembly {
let result := delegatecall(gas, target, add(data, 0x20), mload(data), 0, 0)
let size := returndatasize
let ptr := mload(0x40)
returndatacopy(ptr, 0, size)
switch result
case 0 { revert(ptr, size) }
default { return(ptr, size) }
}
}
function setTarget(
address _newTarget)
public
onlyOwner
{
_setTarget(_newTarget);
}
function _setTarget(
address _newTarget)
internal
{
require(_isContract(_newTarget), "target not a contract");
target_ = _newTarget;
}
function _isContract(
address addr)
internal
view
returns (bool)
{
uint256 size;
assembly { size := extcodesize(addr) }
return size > 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment