Siblearn Academy siblearn academy

DAI Proxy Examples

نمونه ای از قفل کردن وثیقه ETH، قرض گرفتن DAI، بازپرداخت DAI و باز کردن ETH با استفاده از DssProxy.


// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

address constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address constant PROXY_REGISTRY = 0x4678f0a6958e4D2Bc4F1BAF7Bc52E8F3564f3fE4;
address constant PROXY_ACTIONS = 0x82ecD135Dce65Fbc6DbdD0e4237E0AF93FFD5038;
address constant CDP_MANAGER = 0x5ef30b9986345249bc32d8928B7ee64DE9435E39;
address constant JUG = 0x19c0976f590D67707E62397C87829d896Dc0f1F1;
address constant JOIN_ETH_C = 0xF04a5cC80B1E94C69B48f5ee68a08CD2F09A7c3E;
address constant JOIN_DAI = 0x9759A6Ac90977b93B58547b4A71c78317f391A28;

bytes32 constant ETH_C =
    0x4554482d43000000000000000000000000000000000000000000000000000000;

contract DaiProxy {
    IERC20 private constant dai = IERC20(DAI);
    address public immutable proxy;
    uint256 public immutable cdpId;

    constructor() {
        proxy = IDssProxyRegistry(PROXY_REGISTRY).build();
        bytes32 res = IDssProxy(proxy).execute(
            PROXY_ACTIONS,
            abi.encodeCall(IDssProxyActions.open, (CDP_MANAGER, ETH_C, proxy))
        );
        cdpId = uint256(res);
    }

    receive() external payable {}

    function lockEth() external payable {
        IDssProxy(proxy).execute{value: msg.value}(
            PROXY_ACTIONS,
            abi.encodeCall(
                IDssProxyActions.lockETH, (CDP_MANAGER, JOIN_ETH_C, cdpId)
            )
        );
    }

    function borrow(uint256 daiAmount) external {
        IDssProxy(proxy).execute(
            PROXY_ACTIONS,
            abi.encodeCall(
                IDssProxyActions.draw,
                (CDP_MANAGER, JUG, JOIN_DAI, cdpId, daiAmount)
            )
        );
    }

    function repay(uint256 daiAmount) external {
        dai.approve(proxy, daiAmount);
        IDssProxy(proxy).execute(
            PROXY_ACTIONS,
            abi.encodeCall(
                IDssProxyActions.wipe, (CDP_MANAGER, JOIN_DAI, cdpId, daiAmount)
            )
        );
    }

    function repayAll() external {
        dai.approve(proxy, type(uint256).max);
        IDssProxy(proxy).execute(
            PROXY_ACTIONS,
            abi.encodeCall(
                IDssProxyActions.wipeAll, (CDP_MANAGER, JOIN_DAI, cdpId)
            )
        );
    }

    function unlockEth(uint256 ethAmount) external {
        IDssProxy(proxy).execute(
            PROXY_ACTIONS,
            abi.encodeCall(
                IDssProxyActions.freeETH,
                (CDP_MANAGER, JOIN_ETH_C, cdpId, ethAmount)
            )
        );
    }
}

interface IDssProxyRegistry {
    function build() external returns (address proxy);
}

interface IDssProxy {
    function execute(address target, bytes memory data)
        external
        payable
        returns (bytes32 res);
}

interface IDssProxyActions {
    function open(address cdpManager, bytes32 ilk, address usr)
        external
        returns (uint256 cdpId);
    function lockETH(address cdpManager, address ethJoin, uint256 cdpId)
        external
        payable;
    function draw(
        address cdpManager,
        address jug,
        address daiJoin,
        uint256 cdpId,
        uint256 daiAmount
    ) external;
    function wipe(
        address cdpManager,
        address daiJoin,
        uint256 cdpId,
        uint256 daiAmount
    ) external;
    function wipeAll(address cdpManager, address daiJoin, uint256 cdpId)
        external;
    function freeETH(
        address cdpManager,
        address ethJoin,
        uint256 cdpId,
        uint256 collateralAmount
    ) external;
}

interface IERC20 {
    function totalSupply() external view returns (uint256);
    function balanceOf(address account) external view returns (uint256);
    function allowance(address owner, address spender)
        external
        view
        returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transfer(address dst, uint256 amount) external returns (bool);
    function transferFrom(address src, address dst, uint256 amount)
        external
        returns (bool);
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import {Test, console2} from "forge-std/Test.sol";
import "../../../src/defi/dai-proxy/DaiProxy.sol";

address constant VAT = 0x35D1b3F3D7966A1DFe207aa4514C12a259A0492B;

uint256 constant WAD = 1e18;
uint256 constant RAY = 1e27;
uint256 constant RAD = 1e45;

uint256 constant ETH_AMOUNT = 100 * 1e18;
uint256 constant DAI_AMOUNT = 10000 * 1e18;

contract DaiProxyTest is Test {
    IERC20 private constant dai = IERC20(DAI);
    ICdpManager private constant cdpManager = ICdpManager(CDP_MANAGER);
    IVat private constant vat = IVat(VAT);
    DaiProxy private proxy;

    function setUp() public {
        proxy = new DaiProxy();

        // Check min borrow
        IVat.Ilk memory ilk = vat.ilks(ETH_C);
        assertGe(DAI_AMOUNT * RAY, ilk.dust, "DAI borrow amount < dust");

        // Interest rate accumulator
        console2.log("ilk.rate", ilk.rate);
    }

    function print(address urnAddr) private {
        IVat.Urn memory urn = vat.urns(ETH_C, urnAddr);
        console2.log("--------------------");
        console2.log("vault collateral [wad]", urn.ink);
        console2.log("vault debt       [wad]", urn.art);
        console2.log("DAI in proxy     [wad]", dai.balanceOf(address(proxy)));
        console2.log("ETH in proxy     [wad]", address(proxy).balance);
    }

    function test_proxy() public {
        uint256 cdpId = proxy.cdpId();
        address urnAddr = cdpManager.urns(cdpId);

        console2.log("Before lock ETH");
        print(urnAddr);

        proxy.lockEth{value: ETH_AMOUNT}();
        console2.log("");
        console2.log("After lock ETH");
        print(urnAddr);

        proxy.borrow(DAI_AMOUNT);
        console2.log("");
        console2.log("After borrow DAI");
        print(urnAddr);

        proxy.repay(DAI_AMOUNT / 2);
        console2.log("");
        console2.log("After partial repay DAI");
        print(urnAddr);

        proxy.repayAll();
        console2.log("");
        console2.log("After repay all DAI");
        print(urnAddr);

        proxy.unlockEth(ETH_AMOUNT);
        console2.log("");
        console2.log("After unlock ETH");
        print(urnAddr);
    }
}

interface IVat {
    // Collateral type
    struct Ilk {
        uint256 Art; // Total normalized debt      [wad]
        uint256 rate; // Accumulated rates         [ray]
        uint256 spot; // Price with safety margin  [ray]
        uint256 line; // Debt ceiling              [rad]
        uint256 dust; // Urn debt floor            [rad]
    }

    // Vault
    struct Urn {
        uint256 ink; // Locked collateral  [wad]
        uint256 art; // Normalised debt    [wad]
    }

    function ilks(bytes32 ilk) external view returns (Ilk memory);
    function urns(bytes32 ilk, address user)
        external
        view
        returns (Urn memory);
}

interface ICdpManager {
    function urns(uint256 cdpId) external view returns (address urn);
}

روی محیط توسعه ی Remix امتحان بکنید

  • DaiProxy.sol
  • DaiProxyTest.sol
  • بازگشت به لیست