账户
0x2b...8f12
0x2b...8f12

0x2b...8f12

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.21+commit.d9974bed
语言
Solidity
合同源代码
文件 1 的 3:LockstakeEngine.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// 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.8.21;

import { LockstakeUrn } from "src/LockstakeUrn.sol";
import { Multicall } from "src/Multicall.sol";

interface VoteDelegateFactoryLike {
    function created(address) external returns (uint256);
}

interface VoteDelegateLike {
    function lock(uint256) external;
    function free(uint256) external;
}

interface VatLike {
    function ilks(bytes32) external view returns (uint256, uint256, uint256, uint256, uint256);
    function urns(bytes32, address) external view returns (uint256, uint256);
    function hope(address) external;
    function slip(bytes32, address, int256) external;
    function frob(bytes32, address, address, address, int256, int256) external;
    function grab(bytes32, address, address, address, int256, int256) external;
}

interface UsdsJoinLike {
    function vat() external view returns (VatLike);
    function usds() external view returns (GemLike);
    function join(address, uint256) external;
    function exit(address, uint256) external;
}

interface GemLike {
    function approve(address, uint256) external;
    function transfer(address, uint256) external;
    function transferFrom(address, address, uint256) external;
    function mint(address, uint256) external;
    function burn(address, uint256) external;
}

interface JugLike {
    function drip(bytes32) external returns (uint256);
}

interface MkrSkyLike {
    function rate() external view returns (uint256);
    function mkr() external view returns (GemLike);
    function sky() external view returns (GemLike);
    function skyToMkr(address, uint256) external;
    function mkrToSky(address, uint256) external;
}

contract LockstakeEngine is Multicall {
    // --- storage variables ---

    mapping(address usr   => uint256 allowed)                         public wards;
    mapping(address farm  => FarmStatus)                              public farms;
    mapping(address owner => uint256 count)                           public ownerUrnsCount;
    mapping(address owner => mapping(uint256 index => address urn))   public ownerUrns;
    mapping(address urn   => address owner)                           public urnOwners;
    mapping(address urn   => mapping(address usr => uint256 allowed)) public urnCan;
    mapping(address urn   => address voteDelegate)                    public urnVoteDelegates;
    mapping(address urn   => address farm)                            public urnFarms;
    mapping(address urn   => uint256 auctionsCount)                   public urnAuctions;
    JugLike                                                           public jug;
    uint256                                                           public fee;

    // --- constants and enums ---

    uint256 constant WAD = 10**18;
    uint256 constant RAY = 10**27;

    enum FarmStatus { UNSUPPORTED, ACTIVE, DELETED }

    // --- immutables ---

    VoteDelegateFactoryLike immutable public voteDelegateFactory;
    VatLike                 immutable public vat;
    UsdsJoinLike            immutable public usdsJoin;
    GemLike                 immutable public usds;
    bytes32                 immutable public ilk;
    GemLike                 immutable public mkr;
    GemLike                 immutable public lsmkr;
    MkrSkyLike              immutable public mkrSky;
    GemLike                 immutable public sky;
    uint256                 immutable public mkrSkyRate;
    address                 immutable public urnImplementation;

    // --- events ---   

    event Rely(address indexed usr);
    event Deny(address indexed usr);
    event File(bytes32 indexed what, address data);
    event File(bytes32 indexed what, uint256 data);
    event AddFarm(address farm);
    event DelFarm(address farm);
    event Open(address indexed owner, uint256 indexed index, address urn);
    event Hope(address indexed owner, uint256 indexed index, address indexed usr);
    event Nope(address indexed owner, uint256 indexed index, address indexed usr);
    event SelectVoteDelegate(address indexed owner, uint256 indexed index, address indexed voteDelegate);
    event SelectFarm(address indexed owner, uint256 indexed index, address indexed farm, uint16 ref);
    event Lock(address indexed owner, uint256 indexed index, uint256 wad, uint16 ref);
    event LockSky(address indexed owner, uint256 indexed index, uint256 skyWad, uint16 ref);
    event Free(address indexed owner, uint256 indexed index, address to, uint256 wad, uint256 freed);
    event FreeSky(address indexed owner, uint256 indexed index, address to, uint256 skyWad, uint256 skyFreed);
    event FreeNoFee(address indexed owner, uint256 indexed index, address to, uint256 wad);
    event Draw(address indexed owner, uint256 indexed index, address to, uint256 wad);
    event Wipe(address indexed owner, uint256 indexed index, uint256 wad);
    event GetReward(address indexed owner, uint256 indexed index, address indexed farm, address to, uint256 amt);
    event OnKick(address indexed urn, uint256 wad);
    event OnTake(address indexed urn, address indexed who, uint256 wad);
    event OnRemove(address indexed urn, uint256 sold, uint256 burn, uint256 refund);

    // --- modifiers ---

    modifier auth {
        require(wards[msg.sender] == 1, "LockstakeEngine/not-authorized");
        _;
    }

    // --- constructor ---

    constructor(address voteDelegateFactory_, address usdsJoin_, bytes32 ilk_, address mkrSky_, address lsmkr_) {
        voteDelegateFactory = VoteDelegateFactoryLike(voteDelegateFactory_);
        usdsJoin = UsdsJoinLike(usdsJoin_);
        vat = usdsJoin.vat();
        usds = usdsJoin.usds();
        ilk = ilk_;
        mkrSky = MkrSkyLike(mkrSky_);
        mkr = mkrSky.mkr();
        sky = mkrSky.sky();
        mkrSkyRate = mkrSky.rate();
        lsmkr = GemLike(lsmkr_);
        urnImplementation = address(new LockstakeUrn(address(vat), lsmkr_));
        vat.hope(usdsJoin_);
        usds.approve(usdsJoin_, type(uint256).max);
        sky.approve(address(mkrSky), type(uint256).max);
        mkr.approve(address(mkrSky), type(uint256).max);

        wards[msg.sender] = 1;
        emit Rely(msg.sender);
    }

    // --- internals ---

    function _min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x <= y ? x : y;
    }

    function _divup(uint256 x, uint256 y) internal pure returns (uint256 z) {
        // Note: _divup(0,0) will return 0 differing from natural solidity division
        unchecked {
            z = x != 0 ? ((x - 1) / y) + 1 : 0;
        }
    }

    function _urnAuth(address owner, address urn, address usr) internal view returns (bool ok) {
        ok = owner == usr || urnCan[urn][usr] == 1;
    }

    function _getUrn(address owner, uint256 index) internal view returns (address urn) {
        urn = ownerUrns[owner][index];
        require(urn != address(0), "LockstakeEngine/invalid-urn");
    }

    function _getAuthedUrn(address owner, uint256 index) internal view returns (address urn) {
        urn = _getUrn(owner, index);
        require(_urnAuth(owner, urn, msg.sender), "LockstakeEngine/urn-not-authorized");
    }

    // See the reference implementation in https://eips.ethereum.org/EIPS/eip-1167
    function _initCode() internal view returns (bytes memory code) {
        code = new bytes(0x37);
        bytes20 impl = bytes20(urnImplementation);
        assembly {
            mstore(add(code,     0x20),        0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
            mstore(add(code, add(0x20, 0x14)), impl)
            mstore(add(code, add(0x20, 0x28)), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
        }
    }

    // --- administration ---

    function rely(address usr) external auth {
        wards[usr] = 1;
        emit Rely(usr);
    }

    function deny(address usr) external auth {
        wards[usr] = 0;
        emit Deny(usr);
    }

    function file(bytes32 what, address data) external auth {
        if (what == "jug") {
            jug = JugLike(data);
        } else revert("LockstakeEngine/file-unrecognized-param");
        emit File(what, data);
    }

    function file(bytes32 what, uint256 data) external auth {
        if (what == "fee") {
            require(data < WAD, "LockstakeEngine/fee-equal-or-greater-wad");
            fee = data;
        } else revert("LockstakeEngine/file-unrecognized-param");
        emit File(what, data);
    }

    function addFarm(address farm) external auth {
        farms[farm] = FarmStatus.ACTIVE;
        emit AddFarm(farm);
    }

    function delFarm(address farm) external auth {
        farms[farm] = FarmStatus.DELETED;
        emit DelFarm(farm);
    }

    // --- getters ---

    function isUrnAuth(address owner, uint256 index, address usr) external view returns (bool ok) {
        ok = _urnAuth(owner, _getUrn(owner, index), usr);
    }

    // --- urn management functions ---

    function open(uint256 index) external returns (address urn) {
        require(index == ownerUrnsCount[msg.sender]++, "LockstakeEngine/wrong-urn-index");
        bytes memory initCode = _initCode();
        assembly { urn := create(0, add(initCode, 0x20), 0x37) }
        LockstakeUrn(urn).init(); // would revert if create had failed
        ownerUrns[msg.sender][index] = urn;
        urnOwners[urn] = msg.sender;
        emit Open(msg.sender, index, urn);
    }

    function hope(address owner, uint256 index, address usr) external {
        address urn = _getAuthedUrn(owner, index);
        urnCan[urn][usr] = 1;
        emit Hope(owner, index, usr);
    }

    function nope(address owner, uint256 index, address usr) external {
        address urn = _getAuthedUrn(owner, index);
        urnCan[urn][usr] = 0;
        emit Nope(owner, index, usr);
    }

    // --- delegation/staking functions ---

    function selectVoteDelegate(address owner, uint256 index, address voteDelegate) external {
        address urn = _getAuthedUrn(owner, index);
        require(urnAuctions[urn] == 0, "LockstakeEngine/urn-in-auction");
        require(voteDelegate == address(0) || voteDelegateFactory.created(voteDelegate) == 1, "LockstakeEngine/not-valid-vote-delegate");
        address prevVoteDelegate = urnVoteDelegates[urn];
        require(prevVoteDelegate != voteDelegate, "LockstakeEngine/same-vote-delegate");
        (uint256 ink, uint256 art) = vat.urns(ilk, urn);
        if (art > 0 && voteDelegate != address(0)) {
            (,, uint256 spot,,) = vat.ilks(ilk);
            require(ink * spot >= art * jug.drip(ilk), "LockstakeEngine/urn-unsafe");
        }
        _selectVoteDelegate(urn, ink, prevVoteDelegate, voteDelegate);
        emit SelectVoteDelegate(owner, index, voteDelegate);
    }

    function _selectVoteDelegate(address urn, uint256 wad, address prevVoteDelegate, address voteDelegate) internal {
        if (wad > 0) {
            if (prevVoteDelegate != address(0)) {
                VoteDelegateLike(prevVoteDelegate).free(wad);
            }
            if (voteDelegate != address(0)) {
                mkr.approve(voteDelegate, wad);
                VoteDelegateLike(voteDelegate).lock(wad);
            }
        }
        urnVoteDelegates[urn] = voteDelegate;
    }

    function selectFarm(address owner, uint256 index, address farm, uint16 ref) external {
        address urn = _getAuthedUrn(owner, index);
        require(urnAuctions[urn] == 0, "LockstakeEngine/urn-in-auction");
        require(farm == address(0) || farms[farm] == FarmStatus.ACTIVE, "LockstakeEngine/farm-unsupported-or-deleted");
        address prevFarm = urnFarms[urn];
        require(prevFarm != farm, "LockstakeEngine/same-farm");
        (uint256 ink,) = vat.urns(ilk, urn);
        _selectFarm(urn, ink, prevFarm, farm, ref);
        emit SelectFarm(owner, index, farm, ref);
    }

    function _selectFarm(address urn, uint256 wad, address prevFarm, address farm, uint16 ref) internal {
        if (wad > 0) {
            if (prevFarm != address(0)) {
                LockstakeUrn(urn).withdraw(prevFarm, wad);
            }
            if (farm != address(0)) {
                LockstakeUrn(urn).stake(farm, wad, ref);
            }
        }
        urnFarms[urn] = farm;
    }

    function lock(address owner, uint256 index, uint256 wad, uint16 ref) external {
        address urn = _getUrn(owner, index);
        mkr.transferFrom(msg.sender, address(this), wad);
        _lock(urn, wad, ref);
        emit Lock(owner, index, wad, ref);
    }

    function lockSky(address owner, uint256 index, uint256 skyWad, uint16 ref) external {
        address urn = _getUrn(owner, index);
        sky.transferFrom(msg.sender, address(this), skyWad);
        mkrSky.skyToMkr(address(this), skyWad);
        _lock(urn, skyWad / mkrSkyRate, ref);
        emit LockSky(owner, index, skyWad, ref);
    }

    function _lock(address urn, uint256 wad, uint16 ref) internal {
        require(wad <= uint256(type(int256).max), "LockstakeEngine/overflow");
        address voteDelegate = urnVoteDelegates[urn];
        if (voteDelegate != address(0)) {
            mkr.approve(voteDelegate, wad);
            VoteDelegateLike(voteDelegate).lock(wad);
        }
        vat.slip(ilk, urn, int256(wad));
        vat.frob(ilk, urn, urn, address(0), int256(wad), 0);
        lsmkr.mint(urn, wad);
        address urnFarm = urnFarms[urn];
        if (urnFarm != address(0)) {
            require(farms[urnFarm] == FarmStatus.ACTIVE, "LockstakeEngine/farm-deleted");
            LockstakeUrn(urn).stake(urnFarm, wad, ref);
        }
    }

    function free(address owner, uint256 index, address to, uint256 wad) external returns (uint256 freed) {
        address urn = _getAuthedUrn(owner, index);
        freed = _free(urn, wad, fee);
        mkr.transfer(to, freed);
        emit Free(owner, index, to, wad, freed);
    }

    function freeSky(address owner, uint256 index, address to, uint256 skyWad) external returns (uint256 skyFreed) {
        address urn = _getAuthedUrn(owner, index);
        uint256 wad = skyWad / mkrSkyRate;
        uint256 freed = _free(urn, wad, fee);
        skyFreed = freed * mkrSkyRate;
        mkrSky.mkrToSky(to, freed);
        emit FreeSky(owner, index, to, skyWad, skyFreed);
    }

    function freeNoFee(address owner, uint256 index, address to, uint256 wad) external auth {
        address urn = _getAuthedUrn(owner, index);
        _free(urn, wad, 0);
        mkr.transfer(to, wad);
        emit FreeNoFee(owner, index, to, wad);
    }

    function _free(address urn, uint256 wad, uint256 fee_) internal returns (uint256 freed) {
        require(wad <= uint256(type(int256).max), "LockstakeEngine/overflow");
        address urnFarm = urnFarms[urn];
        if (urnFarm != address(0)) {
            LockstakeUrn(urn).withdraw(urnFarm, wad);
        }
        lsmkr.burn(urn, wad);
        vat.frob(ilk, urn, urn, address(0), -int256(wad), 0);
        vat.slip(ilk, urn, -int256(wad));
        address voteDelegate = urnVoteDelegates[urn];
        if (voteDelegate != address(0)) {
            VoteDelegateLike(voteDelegate).free(wad);
        }
        uint256 burn = wad * fee_ / WAD;
        if (burn > 0) {
            mkr.burn(address(this), burn);
        }
        unchecked { freed = wad - burn; } // burn <= wad always
    }

    // --- loan functions ---

    function draw(address owner, uint256 index, address to, uint256 wad) external {
        address urn = _getAuthedUrn(owner, index);
        uint256 rate = jug.drip(ilk);
        uint256 dart = _divup(wad * RAY, rate);
        require(dart <= uint256(type(int256).max), "LockstakeEngine/overflow");
        vat.frob(ilk, urn, address(0), address(this), 0, int256(dart));
        usdsJoin.exit(to, wad);
        emit Draw(owner, index, to, wad);
    }

    function wipe(address owner, uint256 index, uint256 wad) external {
        address urn = _getUrn(owner, index);
        usds.transferFrom(msg.sender, address(this), wad);
        usdsJoin.join(address(this), wad);
        (, uint256 rate,,,) = vat.ilks(ilk);
        uint256 dart = wad * RAY / rate;
        require(dart <= uint256(type(int256).max), "LockstakeEngine/overflow");
        vat.frob(ilk, urn, address(0), address(this), 0, -int256(dart));
        emit Wipe(owner, index, wad);
    }

    function wipeAll(address owner, uint256 index) external returns (uint256 wad) {
        address urn = _getUrn(owner, index);
        (, uint256 art) = vat.urns(ilk, urn);
        require(art <= uint256(type(int256).max), "LockstakeEngine/overflow");
        (, uint256 rate,,,) = vat.ilks(ilk);
        wad = _divup(art * rate, RAY);
        usds.transferFrom(msg.sender, address(this), wad);
        usdsJoin.join(address(this), wad);
        vat.frob(ilk, urn, address(0), address(this), 0, -int256(art));
        emit Wipe(owner, index, wad);
    }

    // --- staking rewards function ---

    function getReward(address owner, uint256 index, address farm, address to) external returns (uint256 amt) {
        address urn = _getAuthedUrn(owner, index);
        require(farms[farm] > FarmStatus.UNSUPPORTED, "LockstakeEngine/farm-unsupported");
        amt = LockstakeUrn(urn).getReward(farm, to);
        emit GetReward(owner, index, farm, to, amt);
    }

    // --- liquidation callback functions ---

    function onKick(address urn, uint256 wad) external auth {
        // Urn confiscation happens in Dog contract where ilk vat.gem is sent to the LockstakeClipper
        (uint256 ink,) = vat.urns(ilk, urn);
        uint256 inkBeforeKick = ink + wad;
        _selectVoteDelegate(urn, inkBeforeKick, urnVoteDelegates[urn], address(0));
        _selectFarm(urn, inkBeforeKick, urnFarms[urn], address(0), 0);
        lsmkr.burn(urn, wad);
        urnAuctions[urn]++;
        emit OnKick(urn, wad);
    }

    function onTake(address urn, address who, uint256 wad) external auth {
        mkr.transfer(who, wad); // Free MKR to the auction buyer
        emit OnTake(urn, who, wad);
    }

    function onRemove(address urn, uint256 sold, uint256 left) external auth {
        uint256 burn;
        uint256 refund;
        if (left > 0) {
            uint256 fee_ = fee;
            burn = _min(sold * fee_ / (WAD - fee_), left);
            mkr.burn(address(this), burn);
            unchecked { refund = left - burn; }
            if (refund > 0) {
                // The following is ensured by the dog and clip but we still prefer to be explicit
                require(refund <= uint256(type(int256).max), "LockstakeEngine/overflow");
                vat.slip(ilk, urn, int256(refund));
                vat.grab(ilk, urn, urn, address(0), int256(refund), 0);
                lsmkr.mint(urn, refund);
            }
        }
        urnAuctions[urn]--;
        emit OnRemove(urn, sold, burn, refund);
    }
}
合同源代码
文件 2 的 3:LockstakeUrn.sol
// SPDX-FileCopyrightText: © 2023 Dai Foundation <www.daifoundation.org>
// SPDX-License-Identifier: AGPL-3.0-or-later
//
// 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.8.21;

interface VatLike {
    function hope(address) external;
}

interface GemLike {
    function balanceOf(address) external view returns (uint256);
    function approve(address, uint256) external;
    function transfer(address, uint256) external;
}

interface StakingRewardsLike {
    function rewardsToken() external view returns (GemLike);
    function stake(uint256, uint16) external;
    function withdraw(uint256) external;
    function getReward() external;
}

contract LockstakeUrn {
    // --- immutables ---

    address immutable public engine;
    GemLike immutable public lsmkr;
    VatLike immutable public vat;

    // --- modifiers ---

    modifier isEngine {
        require(msg.sender == engine, "LockstakeUrn/not-engine");
        _;
    }

    // --- constructor & init ---

    constructor(address vat_, address lsmkr_) {
        engine = msg.sender;
        vat = VatLike(vat_);
        lsmkr = GemLike(lsmkr_);
    }

    function init() external isEngine {
        vat.hope(msg.sender);
        lsmkr.approve(msg.sender, type(uint256).max);
    }

    // --- staking functions ---

    function stake(address farm, uint256 wad, uint16 ref) external isEngine {
        lsmkr.approve(farm, wad);
        StakingRewardsLike(farm).stake(wad, ref);
    }

    function withdraw(address farm, uint256 wad) external isEngine {
        StakingRewardsLike(farm).withdraw(wad);
    }

    function getReward(address farm, address to) external isEngine returns (uint256 amt) {
        StakingRewardsLike(farm).getReward();
        GemLike rewardsToken = StakingRewardsLike(farm).rewardsToken();
        amt = rewardsToken.balanceOf(address(this));
        rewardsToken.transfer(to, amt);
    }
}
合同源代码
文件 3 的 3:Multicall.sol
// SPDX-License-Identifier: GPL-2.0-or-later

// Based on https://github.com/Uniswap/v3-periphery/blob/697c2474757ea89fec12a4e6db16a574fe259610/contracts/base/Multicall.sol

pragma solidity ^0.8.21;

// Enables calling multiple methods in a single call to the contract
abstract contract Multicall  {
    function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
        results = new bytes[](data.length);
        for (uint256 i = 0; i < data.length; i++) {
            (bool success, bytes memory result) = address(this).delegatecall(data[i]);

            if (!success) {
                if (result.length == 0) revert("multicall failed");
                assembly ("memory-safe") {
                    revert(add(32, result), mload(result))
                }
            }

            results[i] = result;
        }
    }
}
设置
{
  "compilationTarget": {
    "src/LockstakeEngine.sol": "LockstakeEngine"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [
    ":dss-interfaces/=lib/token-tests/lib/dss-test/lib/dss-interfaces/src/",
    ":dss-test/=lib/token-tests/lib/dss-test/src/",
    ":forge-std/=lib/token-tests/lib/dss-test/lib/forge-std/src/",
    ":token-tests/=lib/token-tests/src/"
  ]
}
ABI
[{"inputs":[{"internalType":"address","name":"voteDelegateFactory_","type":"address"},{"internalType":"address","name":"usdsJoin_","type":"address"},{"internalType":"bytes32","name":"ilk_","type":"bytes32"},{"internalType":"address","name":"mkrSky_","type":"address"},{"internalType":"address","name":"lsmkr_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"farm","type":"address"}],"name":"AddFarm","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"farm","type":"address"}],"name":"DelFarm","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Draw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"address","name":"data","type":"address"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"data","type":"uint256"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"freed","type":"uint256"}],"name":"Free","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"FreeNoFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"skyWad","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"skyFreed","type":"uint256"}],"name":"FreeSky","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"farm","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amt","type":"uint256"}],"name":"GetReward","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Hope","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"ref","type":"uint16"}],"name":"Lock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"skyWad","type":"uint256"},{"indexed":false,"internalType":"uint16","name":"ref","type":"uint16"}],"name":"LockSky","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Nope","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"urn","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"OnKick","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"urn","type":"address"},{"indexed":false,"internalType":"uint256","name":"sold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"refund","type":"uint256"}],"name":"OnRemove","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"urn","type":"address"},{"indexed":true,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"OnTake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"urn","type":"address"}],"name":"Open","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"usr","type":"address"}],"name":"Rely","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"farm","type":"address"},{"indexed":false,"internalType":"uint16","name":"ref","type":"uint16"}],"name":"SelectFarm","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":true,"internalType":"address","name":"voteDelegate","type":"address"}],"name":"SelectVoteDelegate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"wad","type":"uint256"}],"name":"Wipe","type":"event"},{"inputs":[{"internalType":"address","name":"farm","type":"address"}],"name":"addFarm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"farm","type":"address"}],"name":"delFarm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"draw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"farm","type":"address"}],"name":"farms","outputs":[{"internalType":"enum LockstakeEngine.FarmStatus","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"uint256","name":"data","type":"uint256"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"address","name":"data","type":"address"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"free","outputs":[{"internalType":"uint256","name":"freed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"freeNoFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"skyWad","type":"uint256"}],"name":"freeSky","outputs":[{"internalType":"uint256","name":"skyFreed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"farm","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"getReward","outputs":[{"internalType":"uint256","name":"amt","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"usr","type":"address"}],"name":"hope","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ilk","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"usr","type":"address"}],"name":"isUrnAuth","outputs":[{"internalType":"bool","name":"ok","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"jug","outputs":[{"internalType":"contract JugLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"wad","type":"uint256"},{"internalType":"uint16","name":"ref","type":"uint16"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"skyWad","type":"uint256"},{"internalType":"uint16","name":"ref","type":"uint16"}],"name":"lockSky","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lsmkr","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mkr","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mkrSky","outputs":[{"internalType":"contract MkrSkyLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mkrSkyRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"usr","type":"address"}],"name":"nope","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"onKick","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"},{"internalType":"uint256","name":"sold","type":"uint256"},{"internalType":"uint256","name":"left","type":"uint256"}],"name":"onRemove","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"},{"internalType":"address","name":"who","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"onTake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"open","outputs":[{"internalType":"address","name":"urn","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"ownerUrns","outputs":[{"internalType":"address","name":"urn","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"ownerUrnsCount","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"farm","type":"address"},{"internalType":"uint16","name":"ref","type":"uint16"}],"name":"selectFarm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"voteDelegate","type":"address"}],"name":"selectVoteDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sky","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"}],"name":"urnAuctions","outputs":[{"internalType":"uint256","name":"auctionsCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"},{"internalType":"address","name":"usr","type":"address"}],"name":"urnCan","outputs":[{"internalType":"uint256","name":"allowed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"}],"name":"urnFarms","outputs":[{"internalType":"address","name":"farm","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"urnImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"}],"name":"urnOwners","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"urn","type":"address"}],"name":"urnVoteDelegates","outputs":[{"internalType":"address","name":"voteDelegate","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usds","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"usdsJoin","outputs":[{"internalType":"contract UsdsJoinLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vat","outputs":[{"internalType":"contract VatLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"voteDelegateFactory","outputs":[{"internalType":"contract VoteDelegateFactoryLike","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"allowed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"wipe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"wipeAll","outputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]