Skip to content

Commit

Permalink
Liq 2.0 (#228)
Browse files Browse the repository at this point in the history
* Initial commit

* dapp init DutchOven

* dapp install ds-test

* paste in code from gist

* make it build

* tweak README

* add license blurb

* First draft for flash loan + removing loaf if lot is 0 + minor changes (#1)

* cmooney-20200725: various bug fixes

* done TODO checks and fixed trailing whitespace

* ONE to RAY, removed slices, bakes public

* chore: add TODO for max/min/pay variables

* SC-4072: limit amount of Dai out for liquidation (#5)

* SC-4072: limit amount of Dai out for liquidation

* remove changes for another PR

* added BLN

* fix comment

* change MILLION to MIl

* fixed up the formula

* fixed bug in MIL va. MLN

* forgot rdiv()

* missing closing )

* add comments on types

* typo, needed param to be data

* fix: update dog to fix stack to deep, compiles

* feat: update dog to use LIQ-1.2 logic

* fix: update comments, remove dunk, change bone to digs

* fix: gas optimize dink > 0 require

* fix: update comments, add spot to brace block, add cost var

* fix: change cost to due

* fix: formatting

Co-authored-by: Lucas Manuel <[email protected]>

* fix dust check

* feat: Add Auction Reset Functionality (SC-4635) (#7)

* feat: add auction reset functionality

* fix: add storage vars, fix compilation issues

* feat: add require to warm, change to external

* fix: update comments

* fix: use safe sub, add dead auction check in warm and take

* Price decrease function interface and sample implementations (#8)

* define price decrease function interface and some trial implementations

* commit sample price decrease functions

* dapp install https://github.com/makerdao/dss.git

* feat: add testing for linear/exp price dec functions

* feat: add unit tests to stairstep, linear price decrease functions

* fix: add comments about precision

* fix: update exp test tolerance to 1e-22

* feat: tests working consistently with precision tolerance

* fix: fix wrong comments

* dapp uninstall dss

* fix: update variables, comments

Co-authored-by: Lucas Manuel <[email protected]>

* rely on oven in Dog.file (#11)

* rename files (#13)

* Add on-chain tracking of live auctions (#3)

* Add on-chain tracking of live auctions

* rename last to move for clarity

* Add splice and count funtions for array management

* Fix index shifting

* Change _stopBaking to _remove

* Clean up and fixes

* remove list(uint256,uint256)(uint256[]) and replace with getId(uint256)(uint256)

* Replace .length-- with .pop() for forward compatibility

* Remove comment

* fix: update memes, comments

Co-authored-by: Lucas <[email protected]>

* feat: Add Unit Testing (SC-4636) (#9)

* feat: start bake test

* dapp install ds-value

* feat: add take tests for over/under/at tab

* feat: add take test for multiple bids, tests pass

* fix: delete notes file

* fix: remove empty lib/dss

* dapp install dss

* feat: add more testing, setup

* feat: all tests pass except exp decrease

* fix: fix exp decrease step and cut values

* fix: remove rpow, change max/pay to pay/val, update dirt require

* Fix import file and rename uint to uin256

* fix: update room require

* fix: update val to price

* fix: remove vat.flux(), grab straight to oven

* fix: remove rely/deny/hope/nope from oven file in dog

* fix: update imports

* fix: update dog.digs() comment

* fix: update vat helpers, hevm.warping, address(this)

* fix: use defined CHEAT_CODE

* feat: add pos to testing

* fix: remove unused MLN, BLN vars in test

* uint to uint256

* Compile with solc 0.5 and 0.6

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* re-meme and minor cleanup (#15)

* dapp uninstall ds-test

* dapp uninstall ds-value

* dapp uninstall dss

* Remove stuff that will not be transferred

* Minor changes to make clipper tests to work

* Preliminary Circuit Breaker

Added logic to `stop` and `start` the clipper. All major functions are frozen when `stopped == true`.

* use current price, not bidder maximum

* hole per ilk (#141)

* Bit simpler tests

* Implement hole per collateral

* Fixing minor things

* fix: update hole comment

Co-authored-by: Lucas <[email protected]>

* Clipper cleanup (#146)

* improve take arg comments

* remove comment about returning collateral incrementally

* rename warm to redo

* rename resetting event

* add Take event

* fix: format Take event, comments

Co-authored-by: Lucas <[email protected]>

* feat: Add Auction Reset Tests (SC-6413) (#148)

* feat: add auction reset testing, tests pass

* fix: move repeated setup code to function

* feat: add try_redo() to clip tests

* fix: update to camelcase, fix comment

* Add license identifier to clip.sol

* change to levels

* Revert "Merge branch 'SC-4636' into liq-2.0"

This reverts commit 1906a89, reversing
changes made to 12d3254.

* Add license identifier to dog.sol

* Add tests

* No breaker for yank

* remove yank breaker tests

* Add tests

* No breaker for yank

* remove yank breaker tests

* fixing rebase issues

* remove `which`

* fix: read dust from vat (#151)

* feat: add chop getter API

* feat: Add Dusty `bite` Check (SC-6351) (#154)

* feat: add dusty bite check

* fix: use rate in dust revert calc

* feat: add rate to dusty check test

* fix: remove math import

* fix: update comments

* fix: get rid of jug

* feat: Add LibNote events to dog.sol, clip.sol (SC-4645) (#156)

* feat: add LibNote to dog, clip

* feat: index ids, add top to Kick and Redo, add max/price/owe to Take

* fix: remove note from functions with custom events in dog and clip

* minor gas optimizations in Clipper (#152)

* minor gas optimizations in Clipper

* fix: add dust call back, resolve conflicts

Co-authored-by: Lucas <[email protected]>

* feat: Use custom events (#157)

* feat: add custom events across functions in dog and clip

* fix: update public to external for rely/deny in clip

* feat: update File events to differentiate types

* fix: add rely events to constructors, index id in Bark

* fix: change tab to due in Bark event

* feat: Add Keeper Liquidation Incentive (SC-6597) (#153)

* feat: add keeper liquidation incentive and testing, tests pass

* fix: use ali to bark()

* feat: add tip and chip as per ilk params for incentives

* fix: fix test failures from rebase

* fix: update wmul

* feat: update tests to assert bob balance

* fix: update comments

* feat: add custom events for rely/deny in abaci.sol (#163)

* change price API to accept seconds elapsed since auction start (#162)

* change price API to accept seconds elapsed since auction start

* reinstate 0.5.12 compatibility

* fix: add Rely event to abaci constructors

* fix: update liq incentive to use due (#164)

* feat: Upgrade dog, clip to 0.6.7, Update CI (SC-7268) (#165)

* feat: upgrade dog, clip to 0.6.7, update CI

* fix: format immutable vars, use interface in abaci.sol

* fix: update chip comment (#166)

* feat: End Integration and `yank()` (SC-6352 + SC-6353) (#161)

* draft, dog is in end w/ cat, and auction cancellation

* committing from laptop so i can pull to desktop

* committing latest changes to share

* fix: fix interace and formatting

* feat: add tests for yank and end integration

feix: formatting

* fix: use _remove in yank, remove vat.hope() in halt()

* fix: update halt to skip

* fix: update tests to use real rate, remove unnecessary testing

* fix: use vat.fold in snip test for rate

* feat: add clipper assertions from yank call

* fix: update scope of tab and lot

Co-authored-by: wilbarnes <[email protected]>

* separate price decrease function tests into their own file (#168)

* feat: Add `needsRedo` Function (SC-7445) (#169)

* feat: add view function for auction reset

* feat: test for both tail and cusp

* feat: add ripe function

* fix: update ripe to done

* fix: remove sale.tab check from done function

* fix: update return bool

* feat: minor gas optimization for dink calculation (#167)

* fix: Input and state validation (#170)

* add input validation to Clipper.kick w/tests

* regularize checks for non-running auctions

* more tests

* Slither findings (#172)

* make public funcs external in Dog

* simplify cut param of StairstepExponentialDecrease

* fix revert message in StairstepExponentialDecrease

* gas optimization and test for Clipper.yank (#175)

* Compile with solc 0.6.11

* Make LinearDecrease.tau public

* fix: whitespace and BIL (#178)

* LIQ-2.0 20210114 updates (#181)

* some small changes and TODO notes

* verbose testing

* Add id to yank

* rm max TODO

Co-authored-by: Brian McMichael <[email protected]>

* Add extra function to pay rewards to external address (#180)

* Add remaining art to dart to prevent unliquidatable vaults (#179)

* Add remaining art to dart to prevent unliquidatable vaults

* rm extra require

* Reuse mart

* Simplify dust check

* Modify unit test in order to work with the dust behaviour change

* rename test for clarity

* Add test TODO

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Liq 2.0 gas improvements (#184)

* Optimize gas usage in some functions

* Optimize take function and change done to status (which returns also the price)

* Fix require message

* Fix in needsRedo

* now => block.timestamp

* Add comment

* Use id as in other functions

* Fix shadow variable warning

* Add missing SPDX License Identifier for some files

* Liq 2.0: add tests for external calls (#185)

* tests for external calls

* add test for reentrancy

* test redo reentrancy

* more realistic flashsale test

* avoid third-party names

* Prevent take impersonation. (#189)

Co-authored-by: Emilio Silva Schlenker <[email protected]>

* Instead of ending auction if tab < dust, recalculate amounts (#190)

* Instead of ending auction if tab < dust, recalculate amounts

* Instead of ending auction if tab < dust, recalculate amounts

* Some changes

* Avoid if block if tab == owe

Co-authored-by: Emilio Silva Schlenker <[email protected]>
Co-authored-by: Brian McMichael <[email protected]>

* fix: move incentive to kick() in redo() (SC-8390) (#188)

* fix: move incentive to kick() in redo() (SC-8390)

* removed comment

* prevent vat.suck() and move SLOAD

* pedantic security

* adding TODO comments

* LIQ-2.0: dusty test cases around dog.bark() (#186)

* create test file for dog

* dog set up

* add isDusty() function and a few tests

- test_bark_basic()
- testFail_bark_not_unsafe()
- test_bark_unliquidatable_vault()
- test_bark_dust_over_ilk_hole()
- test_bark_dust_over_Hole()
- test_bark_exactly_dust_over_Hole()

* update code to recent changes

* add some tests

- test_bark_over_ilk_hole
- test_bark_over_Hole
- test_bark_dust_under_ilk_hole
- test_bark_dust_under_Hole

* remove duplicate lines

* Redo some tests

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Add lock modifier to redo just as extra safety measure (#192)

* Change needsRedo function to getStatus which also includes the price (#193)

* Change needsRedo function to getStatus which also includes the price

* Fix comment

* Clean up warnings (#195)

* Make dog immutable and spotter manageable + check dog is not used as who in flash loan call

* Not paying incentive in redo if the auction is dusty

* Make chip and tip public + more tests (#196)

* Test for not partial purchase when tab == dust

* Make chip and tip public + adding a test to check redo incentives logic

* Addressing comments

* Fix spacing

* Avoid extra SLOAD when using chip and tip (#2)

* In case Hole < Dirt or milk.hole < milk.dirt also show revert message

* Save SLOAD in kick

* Save SLOAD in kick

* move top

* Clearer parameter name

* Yank param uint256

* Tweak breaker docs

* Custom events + int/uint with 256 + now -> block.timestamp

* Custom events + int/uint with 256 + now -> block.timestamp

* Add indexed to usr in Skip and Snip

* Move math constant to the top

* Rename all File events to just plain File name

* getPrice function

This function:

* avoids replicated code
* avoids stack-too-deep brackets

* Fix comment take param

* Add snip to End code documentation

* Add snip to End code documentation

* Text changes

* Liq 2.0 formulas

* Add formulas for `take`

* add brief `top` formula for kick and redo

* formulas for `bark`

* made formulas for bark clearer

* general equation for bark

* added the case when `dart` creates a dusty vault

* corrected typos

* adding formulas for abaci linear and exponential decrease for price

* Updating explanation of cut

* New formulas for bark and take (#199)

* New formulas for bark

* New formulas for take

* Fix bark formula

* Format some text

* Minor fixes

Co-authored-by: Emilio Silva Schlenker <[email protected]>
Co-authored-by: tannr <[email protected]>

* Optimize deletion: don't shift if element is last

* Optimize deletion: don't shift if element is last

* Add test of element removal

* Add more assertions and a test of out-of-range failure

* document test

* unused var

* dig entire tab when full lot is purchased

* Address PwC finding 6.6

* revamp dog partial liquidation logic

* add tests for not creating dusty auctions

* Update src/test/dog.t.sol

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Update src/test/dog.t.sol

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* fix try_bark

* improve clarity of dusty vault & dusty room test

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Add lock modifier to every auth function + make SetBreaker part of th…

* Add lock modifier to every auth function + make SetBreaker part of the file function

* Update src/clip.sol

Co-authored-by: Kurt Barry <[email protected]>

Co-authored-by: Kurt Barry <[email protected]>

* Make dog can be changed on the clipper

* Save extra SLOAD calling kicks

* Addp kpr to Kick and Redo events

* Addp kpr to Kick and Redo events

* Log amount is being paid to kpr

* Rename kprAmt to coin

* Use one storage slot for chip and tip

* Use one storage slot for chip and tip

* Fix for Kurt and Brian

* Remove LibNote in order to be able to compile with solc 0.6 optimized

* Remove LibNote in order to be able to compile with solc 0.6 optimized

* Add runs to the Makefile

* Require top > 0 for kicking and resetting (#205)

* Don't set unstable default values in stairstep constructor (#204)

* Update to 0.6.12 (#206)

* changing wards uint to uint256

* Remove list(), use active() (#207)

* validation for chop (#209)

* Fix state mutability warning in one test contract (#210)

* Add list(), remove getId() (#212)

* add continuous exponential decrease (#211)

* add continuous exponential decrease

* Update src/test/abaci.t.sol

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* harmonize comments

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Gas Optimization: Cache the dust value and allow public modification. (#214)

* More efficient lock in case tx reverts or if in future there are not … (#213)

* More efficient lock in case tx reverts or if in future there are not refunds

* Fix spacing

Co-authored-by: Brian McMichael <[email protected]>

* validate Clipper ilk when filing in Dog (#216)

* Revert "More efficient lock in case tx reverts or if in future there are not … (#213)" (#217)

This reverts commit 628d6f9.

* Return lot size with getStatus (#215)

* Return lot size with getStatus

* Add tab to getStatus

* Add a breaker level that prevents kick and redo but not take (#220)

* add a breaker level to disable kick and redo but not take

* test re-enabling taking

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* fix tests

* fix tests post-rebase

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Dog and Clipper comment updates (#221)

* update Dog comment

* typos and phrasing

* improve kick param comments

* change kpr comments for kick and redo

* rename getPrice() to getFeedPrice() and price to feedPrice (#224)

* rename getPrice to getFeedPrice

Note that this is inconsistent with daiwanese practices

* rename the return value of getFeedPrice()

* gas tests and don't use optimizations (#226)

* gas tests and don't use optimizations

* update shell.nix to not compile w/optimizations

* properly account for chop in dust checks in the Clipper (#222)

* properly account for chop in dust checks in the Clipper

* cached chost, uniform checks, tests

* update take comment

* Cache chost

* Remove unused variable

* Change _ position

* don't set upchost in constructor

* cache ilk, fix comment

* actually don't cache, ilk is immutable

* remove underscore

* remove extra comma

Co-authored-by: Gonzalo Balabasquer <[email protected]>

* Rename abaci file event (#229)

* remove extra newline

Co-authored-by: Kurt Barry <[email protected]>
Co-authored-by: Christopher Mooney <[email protected]>
Co-authored-by: Lucas Manuel <[email protected]>
Co-authored-by: Kurt Barry <[email protected]>
Co-authored-by: Brian L. McMichael <[email protected]>
Co-authored-by: andy8052 <[email protected]>
Co-authored-by: wilbarnes <[email protected]>
Co-authored-by: Emilio Silva Schlenker <[email protected]>
Co-authored-by: tannr <[email protected]>
  • Loading branch information
10 people authored Apr 2, 2021
1 parent e2cdd97 commit c8d4c80
Show file tree
Hide file tree
Showing 22 changed files with 3,625 additions and 262 deletions.
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
build :; dapp --use solc:0.5.12 build
clean :; dapp clean
test :; dapp --use solc:0.5.12 test -v ${TEST_FLAGS}
.PHONY: build clean test test-gas

build :; DAPP_BUILD_OPTIMIZE=0 DAPP_BUILD_OPTIMIZE_RUNS=0 dapp --use solc:0.6.12 build
clean :; dapp clean
test :; DAPP_BUILD_OPTIMIZE=0 DAPP_BUILD_OPTIMIZE_RUNS=0 dapp --use solc:0.6.12 test -v ${TEST_FLAGS}
test-gas : build
LANG=C.UTF-8 hevm dapp-test --rpc="${ETH_RPC_URL}" --json-file=out/dapp.sol.json --dapp-root=. --verbose 2 --match "test_gas"
5 changes: 3 additions & 2 deletions shell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
}: with dappPkgs;

mkShell {
DAPP_SOLC = solc-static-versions.solc_0_5_12 + "/bin/solc-0.5.12";
# SOLC_FLAGS = "--optimize --optimize-runs=200";
DAPP_SOLC = solc-static-versions.solc_0_6_12 + "/bin/solc-0.6.12";
# No optimizations
SOLC_FLAGS = "";
buildInputs = [
dapp
];
Expand Down
260 changes: 260 additions & 0 deletions src/abaci.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
// SPDX-License-Identifier: AGPL-3.0-or-later

// Copyright (C) 2020 Maker Ecosystem Growth Holdings, INC.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.

pragma solidity >=0.6.12;

interface Abacus {
// 1st arg: initial price [ray]
// 2nd arg: seconds since auction start [seconds]
// returns: current auction price [ray]
function price(uint256, uint256) external view returns (uint256);
}

contract LinearDecrease is Abacus {

// --- Auth ---
mapping (address => uint256) public wards;
function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); }
function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); }
modifier auth {
require(wards[msg.sender] == 1, "LinearDecrease/not-authorized");
_;
}

// --- Data ---
uint256 public tau; // Seconds after auction start when the price reaches zero [seconds]

// --- Events ---
event Rely(address indexed usr);
event Deny(address indexed usr);

event File(bytes32 indexed what, uint256 data);

// --- Init ---
constructor() public {
wards[msg.sender] = 1;
emit Rely(msg.sender);
}

// --- Administration ---
function file(bytes32 what, uint256 data) external auth {
if (what == "tau") tau = data;
else revert("LinearDecrease/file-unrecognized-param");
emit File(what, data);
}

// --- Math ---
uint256 constant RAY = 10 ** 27;
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x);
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x);
}
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x * y;
require(y == 0 || z / y == x);
z = z / RAY;
}

// Price calculation when price is decreased linearly in proportion to time:
// tau: The number of seconds after the start of the auction where the price will hit 0
// top: Initial price
// dur: current seconds since the start of the auction
//
// Returns y = top * ((tau - dur) / tau)
//
// Note the internal call to mul multiples by RAY, thereby ensuring that the rmul calculation
// which utilizes top and tau (RAY values) is also a RAY value.
function price(uint256 top, uint256 dur) override external view returns (uint256) {
if (dur >= tau) return 0;
return rmul(top, mul(tau - dur, RAY) / tau);
}
}

contract StairstepExponentialDecrease is Abacus {

// --- Auth ---
mapping (address => uint256) public wards;
function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); }
function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); }
modifier auth {
require(wards[msg.sender] == 1, "StairstepExponentialDecrease/not-authorized");
_;
}

// --- Data ---
uint256 public step; // Length of time between price drops [seconds]
uint256 public cut; // Per-step multiplicative factor [ray]

// --- Events ---
event Rely(address indexed usr);
event Deny(address indexed usr);

event File(bytes32 indexed what, uint256 data);

// --- Init ---
// @notice: `cut` and `step` values must be correctly set for
// this contract to return a valid price
constructor() public {
wards[msg.sender] = 1;
emit Rely(msg.sender);
}

// --- Administration ---
function file(bytes32 what, uint256 data) external auth {
if (what == "cut") require((cut = data) <= RAY, "StairstepExponentialDecrease/cut-gt-RAY");
else if (what == "step") step = data;
else revert("StairstepExponentialDecrease/file-unrecognized-param");
emit File(what, data);
}

// --- Math ---
uint256 constant RAY = 10 ** 27;
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x * y;
require(y == 0 || z / y == x);
z = z / RAY;
}
// optimized version from dss PR #78
function rpow(uint256 x, uint256 n, uint256 b) internal pure returns (uint256 z) {
assembly {
switch n case 0 { z := b }
default {
switch x case 0 { z := 0 }
default {
switch mod(n, 2) case 0 { z := b } default { z := x }
let half := div(b, 2) // for rounding.
for { n := div(n, 2) } n { n := div(n,2) } {
let xx := mul(x, x)
if shr(128, x) { revert(0,0) }
let xxRound := add(xx, half)
if lt(xxRound, xx) { revert(0,0) }
x := div(xxRound, b)
if mod(n,2) {
let zx := mul(z, x)
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
let zxRound := add(zx, half)
if lt(zxRound, zx) { revert(0,0) }
z := div(zxRound, b)
}
}
}
}
}
}

// top: initial price
// dur: seconds since the auction has started
// step: seconds between a price drop
// cut: cut encodes the percentage to decrease per step.
// For efficiency, the values is set as (1 - (% value / 100)) * RAY
// So, for a 1% decrease per step, cut would be (1 - 0.01) * RAY
//
// returns: top * (cut ^ dur)
//
//
function price(uint256 top, uint256 dur) override external view returns (uint256) {
return rmul(top, rpow(cut, dur / step, RAY));
}
}

// While an equivalent function can be obtained by setting step = 1 in StairstepExponentialDecrease,
// this continous (i.e. per-second) exponential decrease has be implemented as it is more gas-efficient
// than using the stairstep version with step = 1 (primarily due to 1 fewer SLOAD per price calculation).
contract ExponentialDecrease is Abacus {

// --- Auth ---
mapping (address => uint256) public wards;
function rely(address usr) external auth { wards[usr] = 1; emit Rely(usr); }
function deny(address usr) external auth { wards[usr] = 0; emit Deny(usr); }
modifier auth {
require(wards[msg.sender] == 1, "ExponentialDecrease/not-authorized");
_;
}

// --- Data ---
uint256 public cut; // Per-second multiplicative factor [ray]

// --- Events ---
event Rely(address indexed usr);
event Deny(address indexed usr);

event File(bytes32 indexed what, uint256 data);

// --- Init ---
// @notice: `cut` value must be correctly set for
// this contract to return a valid price
constructor() public {
wards[msg.sender] = 1;
emit Rely(msg.sender);
}

// --- Administration ---
function file(bytes32 what, uint256 data) external auth {
if (what == "cut") require((cut = data) <= RAY, "ExponentialDecrease/cut-gt-RAY");
else revert("ExponentialDecrease/file-unrecognized-param");
emit File(what, data);
}

// --- Math ---
uint256 constant RAY = 10 ** 27;
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x * y;
require(y == 0 || z / y == x);
z = z / RAY;
}
// optimized version from dss PR #78
function rpow(uint256 x, uint256 n, uint256 b) internal pure returns (uint256 z) {
assembly {
switch n case 0 { z := b }
default {
switch x case 0 { z := 0 }
default {
switch mod(n, 2) case 0 { z := b } default { z := x }
let half := div(b, 2) // for rounding.
for { n := div(n, 2) } n { n := div(n,2) } {
let xx := mul(x, x)
if shr(128, x) { revert(0,0) }
let xxRound := add(xx, half)
if lt(xxRound, xx) { revert(0,0) }
x := div(xxRound, b)
if mod(n,2) {
let zx := mul(z, x)
if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
let zxRound := add(zx, half)
if lt(zxRound, zx) { revert(0,0) }
z := div(zxRound, b)
}
}
}
}
}
}

// top: initial price
// dur: seconds since the auction has started
// cut: cut encodes the percentage to decrease per second.
// For efficiency, the values is set as (1 - (% value / 100)) * RAY
// So, for a 1% decrease per second, cut would be (1 - 0.01) * RAY
//
// returns: top * (cut ^ dur)
//
function price(uint256 top, uint256 dur) override external view returns (uint256) {
return rmul(top, rpow(cut, dur, RAY));
}
}
22 changes: 12 additions & 10 deletions src/cat.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@

pragma solidity >=0.5.12;

import "./lib.sol";
// FIXME: This contract was altered compared to the production version.
// It doesn't use LibNote anymore.
// New deployments of this contract will need to include custom events (TO DO).

interface Kicker {
function kick(address urn, address gal, uint256 tab, uint256 lot, uint256 bid)
Expand Down Expand Up @@ -47,11 +49,11 @@ interface VowLike {
function fess(uint256) external;
}

contract Cat is LibNote {
contract Cat {
// --- Auth ---
mapping (address => uint256) public wards;
function rely(address usr) external note auth { wards[usr] = 1; }
function deny(address usr) external note auth { wards[usr] = 0; }
function rely(address usr) external auth { wards[usr] = 1; }
function deny(address usr) external auth { wards[usr] = 0; }
modifier auth {
require(wards[msg.sender] == 1, "Cat/not-authorized");
_;
Expand Down Expand Up @@ -107,20 +109,20 @@ contract Cat is LibNote {
}

// --- Administration ---
function file(bytes32 what, address data) external note auth {
function file(bytes32 what, address data) external auth {
if (what == "vow") vow = VowLike(data);
else revert("Cat/file-unrecognized-param");
}
function file(bytes32 what, uint256 data) external note auth {
function file(bytes32 what, uint256 data) external auth {
if (what == "box") box = data;
else revert("Cat/file-unrecognized-param");
}
function file(bytes32 ilk, bytes32 what, uint256 data) external note auth {
function file(bytes32 ilk, bytes32 what, uint256 data) external auth {
if (what == "chop") ilks[ilk].chop = data;
else if (what == "dunk") ilks[ilk].dunk = data;
else revert("Cat/file-unrecognized-param");
}
function file(bytes32 ilk, bytes32 what, address flip) external note auth {
function file(bytes32 ilk, bytes32 what, address flip) external auth {
if (what == "flip") {
vat.nope(ilks[ilk].flip);
ilks[ilk].flip = flip;
Expand Down Expand Up @@ -177,11 +179,11 @@ contract Cat is LibNote {
emit Bite(ilk, urn, dink, dart, mul(dart, rate), milk.flip, id);
}

function claw(uint256 rad) external note auth {
function claw(uint256 rad) external auth {
litter = sub(litter, rad);
}

function cage() external note auth {
function cage() external auth {
live = 0;
}
}
Loading

0 comments on commit c8d4c80

Please sign in to comment.