Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
4 contributors

Users who have contributed to this file

@gbalabasquer @michaelelliot @iamchrissmith @zdumitru
257 lines (225 sloc) 7.66 KB
pragma solidity 0.5.12;
import { LibNote } from "dss/lib.sol";
contract VatLike {
function urns(bytes32, address) public view returns (uint, uint);
function hope(address) public;
function flux(bytes32, address, address, uint) public;
function move(address, address, uint) public;
function frob(bytes32, address, address, address, int, int) public;
function fork(bytes32, address, address, int, int) public;
}
contract UrnHandler {
constructor(address vat) public {
VatLike(vat).hope(msg.sender);
}
}
contract DssCdpManager is LibNote {
address public vat;
uint public cdpi; // Auto incremental
mapping (uint => address) public urns; // CDPId => UrnHandler
mapping (uint => List) public list; // CDPId => Prev & Next CDPIds (double linked list)
mapping (uint => address) public owns; // CDPId => Owner
mapping (uint => bytes32) public ilks; // CDPId => Ilk
mapping (address => uint) public first; // Owner => First CDPId
mapping (address => uint) public last; // Owner => Last CDPId
mapping (address => uint) public count; // Owner => Amount of CDPs
mapping (
address => mapping (
uint => mapping (
address => uint
)
)
) public cdpCan; // Owner => CDPId => Allowed Addr => True/False
mapping (
address => mapping (
address => uint
)
) public urnCan; // Urn => Allowed Addr => True/False
struct List {
uint prev;
uint next;
}
event NewCdp(address indexed usr, address indexed own, uint indexed cdp);
modifier cdpAllowed(
uint cdp
) {
require(msg.sender == owns[cdp] || cdpCan[owns[cdp]][cdp][msg.sender] == 1, "cdp-not-allowed");
_;
}
modifier urnAllowed(
address urn
) {
require(msg.sender == urn || urnCan[urn][msg.sender] == 1, "urn-not-allowed");
_;
}
constructor(address vat_) public {
vat = vat_;
}
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x);
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x);
}
function toInt(uint x) internal pure returns (int y) {
y = int(x);
require(y >= 0);
}
// Allow/disallow a usr address to manage the cdp.
function cdpAllow(
uint cdp,
address usr,
uint ok
) public cdpAllowed(cdp) {
cdpCan[owns[cdp]][cdp][usr] = ok;
}
// Allow/disallow a usr address to quit to the the sender urn.
function urnAllow(
address usr,
uint ok
) public {
urnCan[msg.sender][usr] = ok;
}
// Open a new cdp for a given usr address.
function open(
bytes32 ilk,
address usr
) public note returns (uint) {
require(usr != address(0), "usr-address-0");
cdpi = add(cdpi, 1);
urns[cdpi] = address(new UrnHandler(vat));
owns[cdpi] = usr;
ilks[cdpi] = ilk;
// Add new CDP to double linked list and pointers
if (first[usr] == 0) {
first[usr] = cdpi;
}
if (last[usr] != 0) {
list[cdpi].prev = last[usr];
list[last[usr]].next = cdpi;
}
last[usr] = cdpi;
count[usr] = add(count[usr], 1);
emit NewCdp(msg.sender, usr, cdpi);
return cdpi;
}
// Give the cdp ownership to a dst address.
function give(
uint cdp,
address dst
) public note cdpAllowed(cdp) {
require(dst != address(0), "dst-address-0");
require(dst != owns[cdp], "dst-already-owner");
// Remove transferred CDP from double linked list of origin user and pointers
if (list[cdp].prev != 0) {
list[list[cdp].prev].next = list[cdp].next; // Set the next pointer of the prev cdp (if exists) to the next of the transferred one
}
if (list[cdp].next != 0) { // If wasn't the last one
list[list[cdp].next].prev = list[cdp].prev; // Set the prev pointer of the next cdp to the prev of the transferred one
} else { // If was the last one
last[owns[cdp]] = list[cdp].prev; // Update last pointer of the owner
}
if (first[owns[cdp]] == cdp) { // If was the first one
first[owns[cdp]] = list[cdp].next; // Update first pointer of the owner
}
count[owns[cdp]] = sub(count[owns[cdp]], 1);
// Transfer ownership
owns[cdp] = dst;
// Add transferred CDP to double linked list of destiny user and pointers
list[cdp].prev = last[dst];
list[cdp].next = 0;
if (last[dst] != 0) {
list[last[dst]].next = cdp;
}
if (first[dst] == 0) {
first[dst] = cdp;
}
last[dst] = cdp;
count[dst] = add(count[dst], 1);
}
// Frob the cdp keeping the generated DAI or collateral freed in the cdp urn address.
function frob(
uint cdp,
int dink,
int dart
) public note cdpAllowed(cdp) {
address urn = urns[cdp];
VatLike(vat).frob(
ilks[cdp],
urn,
urn,
urn,
dink,
dart
);
}
// Transfer wad amount of cdp collateral from the cdp address to a dst address.
function flux(
uint cdp,
address dst,
uint wad
) public note cdpAllowed(cdp) {
VatLike(vat).flux(ilks[cdp], urns[cdp], dst, wad);
}
// Transfer wad amount of any type of collateral (ilk) from the cdp address to a dst address.
// This function has the purpose to take away collateral from the system that doesn't correspond to the cdp but was sent there wrongly.
function flux(
bytes32 ilk,
uint cdp,
address dst,
uint wad
) public note cdpAllowed(cdp) {
VatLike(vat).flux(ilk, urns[cdp], dst, wad);
}
// Transfer wad amount of DAI from the cdp address to a dst address.
function move(
uint cdp,
address dst,
uint rad
) public note cdpAllowed(cdp) {
VatLike(vat).move(urns[cdp], dst, rad);
}
// Quit the system, migrating the cdp (ink, art) to a different dst urn
function quit(
uint cdp,
address dst
) public note cdpAllowed(cdp) urnAllowed(dst) {
(uint ink, uint art) = VatLike(vat).urns(ilks[cdp], urns[cdp]);
VatLike(vat).fork(
ilks[cdp],
urns[cdp],
dst,
toInt(ink),
toInt(art)
);
}
// Import a position from src urn to the urn owned by cdp
function enter(
address src,
uint cdp
) public note urnAllowed(src) cdpAllowed(cdp) {
(uint ink, uint art) = VatLike(vat).urns(ilks[cdp], src);
VatLike(vat).fork(
ilks[cdp],
src,
urns[cdp],
toInt(ink),
toInt(art)
);
}
// Move a position from cdpSrc urn to the cdpDst urn
function shift(
uint cdpSrc,
uint cdpDst
) public note cdpAllowed(cdpSrc) cdpAllowed(cdpDst) {
require(ilks[cdpSrc] == ilks[cdpDst], "non-matching-cdps");
(uint ink, uint art) = VatLike(vat).urns(ilks[cdpSrc], urns[cdpSrc]);
VatLike(vat).fork(
ilks[cdpSrc],
urns[cdpSrc],
urns[cdpDst],
toInt(ink),
toInt(art)
);
}
}
You can’t perform that action at this time.