Skip to content
This repository has been archived by the owner on Apr 18, 2023. It is now read-only.

Commit

Permalink
(re)introduce din, remove ice
Browse files Browse the repository at this point in the history
  • Loading branch information
rainbreak committed Nov 21, 2017
1 parent 2c177a7 commit 6d23859
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 50 deletions.
7 changes: 4 additions & 3 deletions DEVELOPING.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,13 @@ Some important features of `cage`:
The `top` also serves as a useful frontend entrypoint to the system, as it
links to all other components.

### `drip`, `art` and `chi`: Dynamic Fee Accumulation
### `drip`, `rum`, `art` and `chi`: Dynamic Fee Accumulation

In a simpler system with no interest rates, we could denominate CDP debt,
the `tab`, directly in `sin`. However with non zero interest, `tab` is a
dynamic quantity, computed from `art`, a per CDP debt unit, and `chi`,
the price of this debt unit in `sin`.
dynamic quantity, computed from `art`, a rate-normalised per-CDP debt unit,
and `chi`, the product of accumulated rates that converts `art` into a real
debt amount.

```
tab(cdp) = cdp.art * chi
Expand Down
5 changes: 5 additions & 0 deletions libexec/sai/sai-din
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
### sai-din -- get the debt backed by CDPs
set -e
wad=$(seth call "${SAI_TUB?}" "din()")
sai wad -h "$wad"
5 changes: 0 additions & 5 deletions libexec/sai/sai-ice

This file was deleted.

36 changes: 16 additions & 20 deletions src/sai.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ contract SaiTestBase is DSTest, DSMath {
dad.permit(tub, sai, bytes4(keccak256('mint(address,uint256)')));
dad.permit(tub, sai, bytes4(keccak256('burn(address,uint256)')));

dad.permit(tub, sin, bytes4(keccak256('mint(address,uint256)')));
dad.permit(tub, sin, bytes4(keccak256('mint(uint256)')));
dad.permit(tub, sin, bytes4(keccak256('burn(uint256)')));

Expand Down Expand Up @@ -321,10 +322,8 @@ contract SaiTubTest is SaiTestBase {
tub.lock(cup, 10 ether);

assertEq(sai.balanceOf(this), 0 ether);
assertEq(sin.balanceOf(tub), 0 ether);
tub.draw(cup, 10 ether);
assertEq(sai.balanceOf(this), 10 ether);
assertEq(sin.balanceOf(tub), 10 ether);
}
function testWipe() public {
mom.setMat(ray(1 ether));
Expand All @@ -334,10 +333,8 @@ contract SaiTubTest is SaiTestBase {
tub.draw(cup, 10 ether);

assertEq(sai.balanceOf(this), 10 ether);
assertEq(sin.balanceOf(tub), 10 ether);
tub.wipe(cup, 5 ether);
assertEq(sai.balanceOf(this), 5 ether);
assertEq(sin.balanceOf(tub), 5 ether);
}
function testUnsafe() public {
tub.join(10 ether);
Expand Down Expand Up @@ -372,12 +369,12 @@ contract SaiTubTest is SaiTestBase {
mark(1 ether / 2); // 125% collateralisation
assertTrue(!tub.safe(cup));

assertEq(tub.ice(), 4 ether);
assertEq(tub.din(), 4 ether);
assertEq(tub.tab(cup), 4 ether);
assertEq(tap.fog(), 0 ether);
assertEq(tap.woe(), 0 ether);
tub.bite(cup);
assertEq(tub.ice(), 0 ether);
assertEq(tub.din(), 0 ether);
assertEq(tub.tab(cup), 0 ether);
assertEq(tap.fog(), 8 ether);
assertEq(tap.woe(), 4 ether);
Expand Down Expand Up @@ -470,8 +467,7 @@ contract CageTest is SaiTestBase {
mark(1 ether);
top.cage();

var woe = sin.balanceOf(tub);
assertEq(woe, 5 ether); // all good debt now bad debt
assertEq(tub.din(), 5 ether); // debt remains in tub
assertEq(wad(top.fix()), 1 ether); // sai redeems 1:1 with gem
assertEq(wad(tub.fit()), 1 ether); // skr redeems 1:1 with gem just before pushing gem to tub

Expand Down Expand Up @@ -1130,12 +1126,12 @@ contract CageTest is SaiTestBase {
// the remaining gem can be claimed only if the cup skr is burned
assertEq(tub.air(), 5 ether);
assertEq(tap.fog(), 0 ether);
assertEq(tub.ice(), 5 ether);
assertEq(tub.din(), 5 ether);
assertEq(tap.woe(), 0 ether);
tub.bite(cup);
assertEq(tub.air(), 0 ether);
assertEq(tap.fog(), 5 ether);
assertEq(tub.ice(), 0 ether);
assertEq(tub.din(), 0 ether);
assertEq(tap.woe(), 5 ether);

tap.vent();
Expand Down Expand Up @@ -1622,11 +1618,11 @@ contract TaxTest is SaiTestBase {
function testTaxJoy() public {
var cup = taxSetup();
assertEq(tub.tab(cup), 100 ether);
assertEq(tub.ice(), 100 ether);
assertEq(tub.din(), 100 ether);
assertEq(tap.joy(), 0 ether);
warp(1 days);
assertEq(tub.tab(cup), 105 ether);
assertEq(tub.ice(), 105 ether);
assertEq(tub.din(), 105 ether);
assertEq(tap.joy(), 5 ether);
}
function testTaxDraw() public {
Expand Down Expand Up @@ -1690,11 +1686,11 @@ contract TaxTest is SaiTestBase {
mom.setAxe(ray(1.4 ether));
mom.setTax(ray(1.000000001547126 ether));
// log_named_uint('tab', tub.tab(cup));
// log_named_uint('sin', sin.balanceOf(tub));
// log_named_uint('sin', tub.din());
for (uint i=0; i<=50; i++) {
warp(10);
// log_named_uint('tab', tub.tab(cup));
// log_named_uint('sin', sin.balanceOf(tub));
// log_named_uint('sin', tub.din());
}
uint256 debtAfterWarp = rmul(100 ether, rpow(tub.tax(), 510));
assertEq(tub.tab(cup), debtAfterWarp);
Expand Down Expand Up @@ -1745,10 +1741,10 @@ contract TaxTest is SaiTestBase {

var owe = tub.tab(cup);
assertEq(owe, 105 ether);
assertEq(tub.ice(), owe);
assertEq(tub.din(), owe);
assertEq(tap.woe(), 0);
tub.bite(cup);
assertEq(tub.ice(), 0);
assertEq(tub.din(), 0);
assertEq(tap.woe(), owe);

assertEq(tap.joy(), 5 ether);
Expand Down Expand Up @@ -2141,11 +2137,11 @@ contract FeeTest is SaiTestBase {
// Unpaid fees do not accumulate as sin
function testFeeIce() public {
var cup = feeSetup();
assertEq(tub.ice(), 100 ether);
assertEq(tub.din(), 100 ether);
assertEq(tub.tab(cup), 100 ether);
assertEq(tub.rap(cup), 0 ether);
warp(1 days);
assertEq(tub.ice(), 100 ether);
assertEq(tub.din(), 100 ether);
assertEq(tub.tab(cup), 100 ether);
assertEq(tub.rap(cup), 5 ether);
}
Expand Down Expand Up @@ -2283,15 +2279,15 @@ contract FeeTaxTest is SaiTestBase {
assertEq(tub.tab(cup), 100 ether);
assertEq(tub.rap(cup), 0 ether);

assertEq(tub.ice(), 100 ether);
assertEq(tub.din(), 100 ether);
assertEq(tap.joy(), 0 ether);

warp(1 days);

assertEq(tub.tab(cup), 105 ether);
assertEq(tub.rap(cup), 5.25 ether);

assertEq(tub.ice(), 105 ether);
assertEq(tub.din(), 105 ether);
assertEq(tap.joy(), 5 ether);
}
function testFeeTaxDraw() public {
Expand Down
6 changes: 6 additions & 0 deletions src/tap.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,13 @@ contract SaiTap is DSThing {
}
function vent() public note {
require(off);

// TODO: maybe this is vulnerable to rounding mismatch. Just
// accumulate the sai instead, or burn on cash. Then all the
// sin from post-cage liquidation will just remain in the tap
// forever.
heal();

skr.burn(fog());
}
}
8 changes: 4 additions & 4 deletions src/top.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ contract SaiTop is DSThing {
fit = rmul(wmul(price, tub.vox().par()), tub.per());
// Most gems we can get per sai is the full balance of the tub.
// If there is no sai issued, we should still be able to cage.
if (sin.totalSupply() == 0) {
if (sai.totalSupply() == 0) {
fix = rdiv(WAD, price);
} else {
fix = min(rdiv(WAD, price), rdiv(tub.pie(), sin.totalSupply()));
fix = min(rdiv(WAD, price), rdiv(tub.pie(), sai.totalSupply()));
}

tub.cage(fit, rmul(fix, sin.totalSupply()));
tub.cage(fit, rmul(fix, sai.totalSupply()));
tap.cage(fix);

tap.vent(); // burn pending sale skr
Expand All @@ -72,7 +72,7 @@ contract SaiTop is DSThing {

function flow() public note {
require(tub.off());
var empty = tub.ice() == 0 && tap.fog() == 0;
var empty = tub.din() == 0 && tap.fog() == 0;
var ended = era() > caged + cooldown;
require(empty || ended);
tub.flow();
Expand Down
32 changes: 14 additions & 18 deletions src/tub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ contract SaiTub is DSThing, SaiTubEvents {
uint256 public rho; // Time of last drip
uint256 _chi; // Accumulated Tax Rates
uint256 _rhi; // Accumulated Tax + Fee Rates
uint256 public rum; // Total normalised debt

uint256 public cupi;
mapping (bytes32 => Cup) public cups;
Expand All @@ -71,9 +72,9 @@ contract SaiTub is DSThing, SaiTubEvents {
return sub(rmul(cups[cup].irk, rhi()), tab(cup));
}

// Good debt
function ice() public view returns (uint) {
return sin.balanceOf(this);
// Total CDP Debt
function din() public returns (uint) {
return rmul(rum, chi());
}
// Backing collateral
function air() public view returns (uint) {
Expand Down Expand Up @@ -188,15 +189,17 @@ contract SaiTub is DSThing, SaiTubEvents {

if (tax != RAY) { // optimised
inc = rpow(tax, age);
var din_ = din();
_chi = rmul(_chi, inc);
lend(tap, sub(rmul(ice(), inc), ice()));
sai.mint(tap, sub(din(), din_));
}

// optimised
if (fee != RAY) inc = rmul(inc, rpow(fee, age));
if (inc != RAY) _rhi = rmul(_rhi, inc);
}


//--CDP-risk-indicator----------------------------------------------

// Abstracted collateral price (ref per skr)
Expand All @@ -211,16 +214,6 @@ contract SaiTub is DSThing, SaiTubEvents {
return pro >= min;
}

//--Anti-corruption-aliases-----------------------------------------

function lend(address dst, uint wad) internal {
sin.mint(wad);
sai.mint(dst, wad);
}
function mend(address src, uint wad) internal {
sai.burn(src, wad);
sin.burn(wad);
}

//--CDP-operations--------------------------------------------------

Expand Down Expand Up @@ -254,11 +247,12 @@ contract SaiTub is DSThing, SaiTubEvents {
require(msg.sender == cups[cup].lad);

cups[cup].art = add(cups[cup].art, rdiv(wad, chi()));
rum = add(rum, rdiv(wad, chi()));
cups[cup].irk = add(cups[cup].irk, rdiv(wad, rhi()));
lend(cups[cup].lad, wad);
sai.mint(cups[cup].lad, wad);

require(safe(cup));
require(sin.totalSupply() <= hat);
require(sai.totalSupply() <= hat);
}
function wipe(bytes32 cup, uint wad) public note {
require(!off);
Expand All @@ -267,8 +261,9 @@ contract SaiTub is DSThing, SaiTubEvents {
var owe = rmul(wad, rdiv(rap(cup), tab(cup)));

cups[cup].art = sub(cups[cup].art, rdiv(wad, chi()));
rum = sub(rum, rdiv(wad, chi()));
cups[cup].irk = sub(cups[cup].irk, rdiv(add(wad, owe), rhi()));
mend(msg.sender, wad);
sai.burn(msg.sender, wad);

var (val, ok) = pep.peek();
if (ok && val != 0) gov.move(msg.sender, pit, wdiv(owe, uint(val)));
Expand All @@ -286,7 +281,8 @@ contract SaiTub is DSThing, SaiTubEvents {

// Take on all of the debt, except unpaid fees
var rue = tab(cup);
sin.push(tap, rue);
sin.mint(tap, rue);
rum = sub(rum, cups[cup].art);
cups[cup].art = 0;
cups[cup].irk = 0;

Expand Down

0 comments on commit 6d23859

Please sign in to comment.