Skip to content

Instantly share code, notes, and snippets.

@jlind0
Created March 4, 2018 12:21
Show Gist options
  • Save jlind0/bace0517c61da5ea6b682df995d48294 to your computer and use it in GitHub Desktop.
Save jlind0/bace0517c61da5ea6b682df995d48294 to your computer and use it in GitHub Desktop.
pragma solidity ^0.4.18;
import "./QuickSort.sol";
contract Collateral {
address public owner;
string public description;
string public title;
string public url;
uint public estimatedValue;
uint public collateralizedDate;
uint public liquidationPrice;
uint public liquidationDate;
event Liquidated(uint price);
CollateralizedLoanLedger ledger;
function Collateral(address _owner, string _description, string _title, string _url, uint _estimatedValue) public {
owner = _owner;
description = _description;
title = _title;
url = _url;
estimatedValue = _estimatedValue;
collateralizedDate = now;
}
function setLedger(CollateralizedLoanLedger _ledger) public {
assert(msg.sender == owner);
ledger = _ledger;
}
function liquidate(uint price) public {
assert(msg.sender == owner);
price = price;
liquidationPrice = price;
liquidationDate = now;
Liquidated(price);
ledger.distribute(price);
}
}
contract CollateralizedLoanLedger {
struct LedgerEntry {
CollateralizedDebtObligation creditor;
uint payment;
uint date;
}
address owner;
mapping(address => Collateral) public collateral;
mapping(address => CollateralizedDebtObligation) creditors;
address[] creditorMap;
address[] collateralMap;
LedgerEntry[] public ledger;
function CollateralizedLoanLedger(address _owner) public {
owner = _owner;
}
function addCollateral(Collateral _collateral) public {
assert(msg.sender == owner);
collateral[address(_collateral)] = _collateral;
_collateral.setLedger(this);
collateralMap.push(address(_collateral));
}
function distribute(uint payment) public {
assert(msg.sender == owner);
uint totalShares = 0;
for (uint i = 0; i < creditorMap.length; i++) {
totalShares += creditors[creditorMap[i]].loan();
}
for (uint j = 0; j < creditorMap.length; j++) {
CollateralizedDebtObligation cdo = creditors[creditorMap[i]];
uint dist = (cdo.loan()*payment)/totalShares;
address(cdo).transfer(dist);
ledger.push(LedgerEntry({
creditor: cdo,
payment: dist,
date: now
}));
}
}
}
contract DutchCollateralizedLoanAuction {
address public payee;
uint public startDate;
uint public endDate;
uint public maxCoins;
Collateral[] public colletaral;
Bid[] activeBids;
function DutchCollateralizedLoanAuction(address _payee, uint _auctionLength) public {
payee = _payee;
startDate = now;
endDate = startDate + _auctionLength * 1 days;
}
function totalCoinsAvailable() private returns (uint) {
uint totalCoinAvailable = maxCoins;
for (uint n = 0; n < activeBids.length; n++) {
totalCoinAvailable -= activeBids[n].activeCoins();
}
return totalCoinAvailable;
}
function getHighestAffectedBid(uint _maxCoins, uint _bid) private returns (uint) {
uint i = 0;
uint totalAllocated = 0;
do {
totalAllocated = activeBids[i].activeCoins()*activeBids[i].bid();
i++;
}
while (i < activeBids.length && totalAllocated < _maxCoins * _bid);
return i;
}
function executeBidRequest(Bid newBid, uint _maxCoins, uint _bid) private returns (uint) {
uint i = getHighestAffectedBid(_maxCoins, _bid);
uint j = 0;
uint totalAllocated = 0;
uint totalCoins = 0;
while (j < i && (activeBids[0].activeCoins()*activeBids[0].bid()) < _maxCoins * _bid - totalAllocated) {
Bid bid = activeBids[0];
totalAllocated += bid.activeCoins() * _bid;
totalCoins += bid.activeCoins();
bid.adjustActiveCoins(0);
delete activeBids[0];
j++;
}
bool isPartial = totalAllocated < _maxCoins*_bid && activeBids.length > 0;
if (isPartial) {
Bid kbid = activeBids[0];
uint k = kbid.activeCoins();
while (k <= kbid.minCoins() && k * kbid.bid() < _maxCoins * _bid - totalAllocated) {
k--;
}
totalCoins += kbid.activeCoins() - k;
totalAllocated += kbid.activeCoins() - k;
bid.adjustActiveCoins(k);
}
allocateBid(newBid, totalAllocated, isPartial, _maxCoins, _bid);
return totalAllocated;
}
function allocateBid(Bid newBid, uint totalAllocated, bool isPartial, uint _maxCoins, uint _bid) private {
if (activeBids.length > 0) {
activeBids.push(activeBids[activeBids.length - 1]);
uint i = 0;
if (isPartial) {
i = 1;
}
uint len = activeBids.length;
for (i; i < len; i++) {
activeBids[i + 1] = activeBids[i];
}
if (isPartial) {
activeBids[1] = newBid;
} else {
activeBids[0] = newBid;
}
}
else
activeBids.push(newBid);
if (totalAllocated < _maxCoins*_bid)
msg.sender.transfer(_maxCoins*_bid - totalAllocated);
}
function placeBid(uint _maxCoins, uint _minCoins, uint _bid) public payable returns (Bid) {
assert(msg.value == _maxCoins * _bid);
Bid newBid = new Bid(_maxCoins, _minCoins, _bid, this);
uint totalAllocated = executeBidRequest(newBid, _maxCoins, _bid);
if (totalAllocated > 0) {
return newBid;
} else {
assert(false);
}
}
}
contract Bid {
uint public maxCoins;
uint public minCoins;
uint public bid;
uint public activeCoins;
uint public finalizedCoins;
DutchCollateralizedLoanAuction public auction;
event ActiveCoinsChanged(uint activeCoins);
event CoinsFinalized(uint finalizedCoins);
function Bid(uint _maxCoins, uint _minCoins, uint _bid, DutchCollateralizedLoanAuction _auction) public payable {
maxCoins = _maxCoins;
minCoins = _minCoins;
bid = _bid;
auction = _auction;
}
function adjustActiveCoins(uint coins) public {
assert(msg.sender == address(auction));
finalizedCoins = coins;
ActiveCoinsChanged(coins);
}
}
contract CollateralizedDebtObligation {
address public debtor;
uint public loan;
function CollateralizedDebtObligation(address _debtor, uint _loan) public payable {
debtor = _debtor;
_loan = loan;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment