ETH Price: $1,972.81 (-5.28%)

Contract Diff Checker

Contract Name:
DssAutoLine

Contract Source Code:

File 1 of 1 : DssAutoLine

// SPDX-License-Identifier: AGPL-3.0-or-later

/// DssAutoLine.sol

// Copyright (C) 2018-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.11;

interface VatLike {
    function ilks(bytes32) external view returns (uint256, uint256, uint256, uint256, uint256);
    function Line() external view returns (uint256);
    function file(bytes32, uint256) external;
    function file(bytes32, bytes32, uint256) external;
}

contract DssAutoLine {
    /*** Data ***/
    struct Ilk {
        uint256   line;  // Max ceiling possible                                               [rad]
        uint256    gap;  // Max Value between current debt and line to be set                  [rad]
        uint48     ttl;  // Min time to pass before a new increase                             [seconds]
        uint48    last;  // Last block the ceiling was updated                                 [blocks]
        uint48 lastInc;  // Last time the ceiling was increased compared to its previous value [seconds]
    }

    mapping (bytes32 => Ilk)     public ilks;
    mapping (address => uint256) public wards;

    VatLike immutable public vat;

    /*** Events ***/
    event Rely(address indexed usr);
    event Deny(address indexed usr);
    event Setup(bytes32 indexed ilk, uint256 line, uint256 gap, uint256 ttl);
    event Remove(bytes32 indexed ilk);
    event Exec(bytes32 indexed ilk, uint256 line, uint256 lineNew);

    /*** Init ***/
    constructor(address vat_) public {
        vat = VatLike(vat_);
        wards[msg.sender] = 1;
        emit Rely(msg.sender);
    }

    /*** Math ***/
    function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
        require((z = x + y) >= x);
    }
    function sub(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 min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        return x <= y ? x : y;
    }

    /*** Administration ***/

    /**
        @dev Add or update an ilk
        @param ilk    Collateral type (ex. ETH-A)
        @param line   Collateral maximum debt ceiling that can be configured [RAD]
        @param gap    Amount of collateral to step [RAD]
        @param ttl    Minimum time between increase [seconds]
    */
    function setIlk(bytes32 ilk, uint256 line, uint256 gap, uint256 ttl) external auth {
        require(ttl  < uint48(-1), "DssAutoLine/invalid-ttl");
        require(line > 0,          "DssAutoLine/invalid-line");
        ilks[ilk] = Ilk(line, gap, uint48(ttl), 0, 0);
        emit Setup(ilk, line, gap, ttl);
    }

    /**
        @dev Remove an ilk
        @param ilk    Collateral type (ex. ETH-A)
    */
    function remIlk(bytes32 ilk) external auth {
        delete ilks[ilk];
        emit Remove(ilk);
    }

    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, "DssAutoLine/not-authorized");
        _;
    }

    /*** Auto-Line Update ***/
    // @param  _ilk  The bytes32 ilk tag to adjust (ex. "ETH-A")
    // @return       The ilk line value as uint256
    function exec(bytes32 _ilk) external returns (uint256) {
        (uint256 Art, uint256 rate,, uint256 line,) = vat.ilks(_ilk);
        uint256 ilkLine = ilks[_ilk].line;

        // Return if the ilk is not enabled
        if (ilkLine == 0) return line;

        // 1 SLOAD
        uint48 ilkTtl     = ilks[_ilk].ttl;
        uint48 ilkLast    = ilks[_ilk].last;
        uint48 ilkLastInc = ilks[_ilk].lastInc;
        //

        // Return if there was already an update in the same block
        if (ilkLast == block.number) return line;

        // Calculate collateral debt
        uint256 debt = mul(Art, rate);

        uint256 ilkGap  = ilks[_ilk].gap;

        // Calculate new line based on the minimum between the maximum line and actual collateral debt + gap
        uint256 lineNew = min(add(debt, ilkGap), ilkLine);

        // Short-circuit if there wasn't an update or if the time since last increment has not passed
        if (lineNew == line || lineNew > line && block.timestamp < add(ilkLastInc, ilkTtl)) return line;

        // Set collateral debt ceiling
        vat.file(_ilk, "line", lineNew);
        // Set general debt ceiling
        vat.file("Line", add(sub(vat.Line(), line), lineNew));

        // Update lastInc if it is an increment in the debt ceiling
        // and update last whatever the update is
        if (lineNew > line) {
            // 1 SSTORE
            ilks[_ilk].lastInc = uint48(block.timestamp);
            ilks[_ilk].last    = uint48(block.number);
            //
        } else {
            ilks[_ilk].last    = uint48(block.number);
        }

        emit Exec(_ilk, line, lineNew);

        return lineNew;
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):