mirror of
				https://github.com/Instadapp/dsa-connectors.git
				synced 2024-07-29 22:37:00 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			428 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Solidity
		
	
	
	
	
	
//SPDX-License-Identifier: MIT
 | 
						|
pragma solidity ^0.7.0;
 | 
						|
 | 
						|
/**
 | 
						|
 * @title Reflexer.
 | 
						|
 * @dev Collateralized Borrowing.
 | 
						|
 */
 | 
						|
 | 
						|
import { TokenInterface } from "../../common/interfaces.sol";
 | 
						|
import { Helpers } from "./helpers.sol";
 | 
						|
import { Events } from "./events.sol";
 | 
						|
import { SafeEngineLike, TokenJoinInterface } from "./interface.sol";
 | 
						|
 | 
						|
abstract contract GebResolver is Helpers, Events {
 | 
						|
    /**
 | 
						|
     * @dev Open Safe
 | 
						|
     * @notice Open a Reflexer Safe.
 | 
						|
     * @param colType Type of Collateral.(eg: 'ETH-A')
 | 
						|
    */
 | 
						|
    function open(string calldata colType) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        bytes32 collateralType = stringToBytes32(colType);
 | 
						|
        require(getCollateralJoinAddress(collateralType) != address(0), "wrong-col-type");
 | 
						|
        uint256 safe = managerContract.openSAFE(collateralType, address(this));
 | 
						|
 | 
						|
        _eventName = "LogOpen(uint256,bytes32)";
 | 
						|
        _eventParam = abi.encode(safe, collateralType);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Close Safe
 | 
						|
     * @notice Close a Reflexer Safe.
 | 
						|
     * @param safe Safe ID to close.
 | 
						|
    */
 | 
						|
    function close(uint256 safe) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(_safe);
 | 
						|
        (uint collateral, uint debt) = SafeEngineLike(managerContract.safeEngine()).safes(collateralType, handler);
 | 
						|
 | 
						|
        require(collateral == 0 && debt == 0, "safe-has-assets");
 | 
						|
        require(managerContract.ownsSAFE(_safe) == address(this), "not-owner");
 | 
						|
 | 
						|
        managerContract.transferSAFEOwnership(_safe, giveAddr);
 | 
						|
 | 
						|
        _eventName = "LogClose(uint256,bytes32)";
 | 
						|
        _eventParam = abi.encode(_safe, collateralType);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Deposit ETH/ERC20_Token Collateral.
 | 
						|
     * @notice Deposit collateral to a Reflexer safe
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param amt token amount to deposit.
 | 
						|
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function deposit(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 amt,
 | 
						|
        uint256 getId,
 | 
						|
        uint256 setId
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _amt = getUint(getId, amt);
 | 
						|
        uint _safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(_safe);
 | 
						|
 | 
						|
        address colAddr = getCollateralJoinAddress(collateralType);
 | 
						|
        TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
 | 
						|
        TokenInterface tokenContract = tokenJoinContract.collateral();
 | 
						|
 | 
						|
        if (isEth(address(tokenContract))) {
 | 
						|
            _amt = _amt == uint(-1) ? address(this).balance : _amt;
 | 
						|
            tokenContract.deposit{value: _amt}();
 | 
						|
        } else {
 | 
						|
            _amt = _amt == uint(-1) ?  tokenContract.balanceOf(address(this)) : _amt;
 | 
						|
        }
 | 
						|
 | 
						|
        approve(tokenContract, address(colAddr), _amt);
 | 
						|
        tokenJoinContract.join(address(this), _amt);
 | 
						|
 | 
						|
        SafeEngineLike(managerContract.safeEngine()).modifySAFECollateralization(
 | 
						|
            collateralType,
 | 
						|
            handler,
 | 
						|
            address(this),
 | 
						|
            address(this),
 | 
						|
            toInt(convertTo18(tokenJoinContract.decimals(), _amt)),
 | 
						|
            0
 | 
						|
        );
 | 
						|
 | 
						|
        setUint(setId, _amt);
 | 
						|
 | 
						|
        _eventName = "LogDeposit(uint256,bytes32,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Withdraw ETH/ERC20_Token Collateral.
 | 
						|
     * @notice Withdraw collateral from a Reflexer Safe
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param amt token amount to withdraw.
 | 
						|
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function withdraw(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 amt,
 | 
						|
        uint256 getId,
 | 
						|
        uint256 setId
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _amt = getUint(getId, amt);
 | 
						|
        uint _safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(_safe);
 | 
						|
 | 
						|
        address colAddr = getCollateralJoinAddress(collateralType);
 | 
						|
        TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
 | 
						|
 | 
						|
        uint _amt18;
 | 
						|
        if (_amt == uint(-1)) {
 | 
						|
            (_amt18,) = SafeEngineLike(managerContract.safeEngine()).safes(collateralType, handler);
 | 
						|
            _amt = convert18ToDec(tokenJoinContract.decimals(), _amt18);
 | 
						|
        } else {
 | 
						|
            _amt18 = convertTo18(tokenJoinContract.decimals(), _amt);
 | 
						|
        }
 | 
						|
 | 
						|
        managerContract.modifySAFECollateralization(
 | 
						|
            _safe,
 | 
						|
            -toInt(_amt18),
 | 
						|
            0
 | 
						|
        );
 | 
						|
 | 
						|
        managerContract.transferCollateral(
 | 
						|
            _safe,
 | 
						|
            address(this),
 | 
						|
            _amt18
 | 
						|
        );
 | 
						|
 | 
						|
        TokenInterface tokenContract = tokenJoinContract.collateral();
 | 
						|
 | 
						|
        if (isEth(address(tokenContract))) {
 | 
						|
            tokenJoinContract.exit(address(this), _amt);
 | 
						|
            tokenContract.withdraw(_amt);
 | 
						|
        } else {
 | 
						|
            tokenJoinContract.exit(address(this), _amt);
 | 
						|
        }
 | 
						|
 | 
						|
        setUint(setId, _amt);
 | 
						|
 | 
						|
        _eventName = "LogWithdraw(uint256,bytes32,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Borrow Coin.
 | 
						|
     * @notice Borrow Coin using a Reflexer safe
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param amt token amount to borrow.
 | 
						|
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function borrow(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 amt,
 | 
						|
        uint256 getId,
 | 
						|
        uint256 setId
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _amt = getUint(getId, amt);
 | 
						|
        uint _safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(_safe);
 | 
						|
 | 
						|
        SafeEngineLike safeEngineContract = SafeEngineLike(managerContract.safeEngine());
 | 
						|
 | 
						|
        managerContract.modifySAFECollateralization(
 | 
						|
            _safe,
 | 
						|
            0,
 | 
						|
            _getBorrowAmt(
 | 
						|
                address(safeEngineContract),
 | 
						|
                handler,
 | 
						|
                collateralType,
 | 
						|
                _amt
 | 
						|
            )
 | 
						|
        );
 | 
						|
 | 
						|
        managerContract.transferInternalCoins(
 | 
						|
            _safe,
 | 
						|
            address(this),
 | 
						|
            toRad(_amt)
 | 
						|
        );
 | 
						|
 | 
						|
        if (safeEngineContract.safeRights(address(this), address(coinJoinContract)) == 0) {
 | 
						|
            safeEngineContract.approveSAFEModification(address(coinJoinContract));
 | 
						|
        }
 | 
						|
 | 
						|
        coinJoinContract.exit(address(this), _amt);
 | 
						|
 | 
						|
        setUint(setId, _amt);
 | 
						|
 | 
						|
        _eventName = "LogBorrow(uint256,bytes32,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Payback borrowed Coin.
 | 
						|
     * @notice Payback Coin debt owed by a Reflexer safe
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param amt token amount to payback.
 | 
						|
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function payback(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 amt,
 | 
						|
        uint256 getId,
 | 
						|
        uint256 setId
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _amt = getUint(getId, amt);
 | 
						|
        uint _safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(_safe);
 | 
						|
 | 
						|
        address safeEngine = managerContract.safeEngine();
 | 
						|
 | 
						|
        uint _maxDebt = _getSafeDebt(safeEngine, collateralType, handler);
 | 
						|
 | 
						|
        _amt = _amt == uint(-1) ? _maxDebt : _amt;
 | 
						|
 | 
						|
        require(_maxDebt >= _amt, "paying-excess-debt");
 | 
						|
 | 
						|
        approve(coinJoinContract.systemCoin(), address(coinJoinContract), _amt);
 | 
						|
        coinJoinContract.join(handler, _amt);
 | 
						|
 | 
						|
        managerContract.modifySAFECollateralization(
 | 
						|
            _safe,
 | 
						|
            0,
 | 
						|
            _getWipeAmt(
 | 
						|
                safeEngine,
 | 
						|
                SafeEngineLike(safeEngine).coinBalance(handler),
 | 
						|
                handler,
 | 
						|
                collateralType
 | 
						|
            )
 | 
						|
        );
 | 
						|
 | 
						|
        setUint(setId, _amt);
 | 
						|
 | 
						|
        _eventName = "LogPayback(uint256,bytes32,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Withdraw leftover ETH/ERC20_Token after Liquidation.
 | 
						|
     * @notice Withdraw leftover collateral after Liquidation.
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param amt token amount to Withdraw.
 | 
						|
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function withdrawLiquidated(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 amt,
 | 
						|
        uint256 getId,
 | 
						|
        uint256 setId
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _amt = getUint(getId, amt);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(safe);
 | 
						|
 | 
						|
        address colAddr = getCollateralJoinAddress(collateralType);
 | 
						|
        TokenJoinInterface tokenJoinContract = TokenJoinInterface(colAddr);
 | 
						|
 | 
						|
        uint _amt18;
 | 
						|
        if (_amt == uint(-1)) {
 | 
						|
            _amt18 = SafeEngineLike(managerContract.safeEngine()).tokenCollateral(collateralType, handler);
 | 
						|
            _amt = convert18ToDec(tokenJoinContract.decimals(), _amt18);
 | 
						|
        } else {
 | 
						|
            _amt18 = convertTo18(tokenJoinContract.decimals(), _amt);
 | 
						|
        }
 | 
						|
 | 
						|
        managerContract.transferCollateral(
 | 
						|
            safe,
 | 
						|
            address(this),
 | 
						|
            _amt18
 | 
						|
        );
 | 
						|
 | 
						|
        TokenInterface tokenContract = tokenJoinContract.collateral();
 | 
						|
        tokenJoinContract.exit(address(this), _amt);
 | 
						|
        if (isEth(address(tokenContract))) {
 | 
						|
            tokenContract.withdraw(_amt);
 | 
						|
        }
 | 
						|
 | 
						|
        setUint(setId, _amt);
 | 
						|
 | 
						|
        _eventName = "LogWithdrawLiquidated(uint256,bytes32,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(safe, collateralType, _amt, getId, setId);
 | 
						|
    }
 | 
						|
 | 
						|
    struct GebData {
 | 
						|
        uint _safe;
 | 
						|
        address colAddr;
 | 
						|
        TokenJoinInterface tokenJoinContract;
 | 
						|
        SafeEngineLike safeEngineContract;
 | 
						|
        TokenInterface tokenContract;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Deposit ETH/ERC20_Token Collateral and Borrow Coin.
 | 
						|
     * @notice Deposit collateral and borrow Coin.
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param depositAmt token deposit amount to Withdraw.
 | 
						|
     * @param borrowAmt token borrow amount to Withdraw.
 | 
						|
     * @param getIdDeposit Get deposit token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param getIdBorrow Get borrow token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setIdDeposit Set deposit token amount at this ID in `InstaMemory` Contract.
 | 
						|
     * @param setIdBorrow Set borrow token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function depositAndBorrow(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 depositAmt,
 | 
						|
        uint256 borrowAmt,
 | 
						|
        uint256 getIdDeposit,
 | 
						|
        uint256 getIdBorrow,
 | 
						|
        uint256 setIdDeposit,
 | 
						|
        uint256 setIdBorrow
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        GebData memory gebData;
 | 
						|
        uint _amtDeposit = getUint(getIdDeposit, depositAmt);
 | 
						|
        uint _amtBorrow = getUint(getIdBorrow, borrowAmt);
 | 
						|
 | 
						|
        gebData._safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(gebData._safe);
 | 
						|
 | 
						|
        gebData.colAddr = getCollateralJoinAddress(collateralType);
 | 
						|
        gebData.tokenJoinContract = TokenJoinInterface(gebData.colAddr);
 | 
						|
        gebData.safeEngineContract = SafeEngineLike(managerContract.safeEngine());
 | 
						|
        gebData.tokenContract = gebData.tokenJoinContract.collateral();
 | 
						|
 | 
						|
        if (isEth(address(gebData.tokenContract))) {
 | 
						|
            _amtDeposit = _amtDeposit == uint(-1) ? address(this).balance : _amtDeposit;
 | 
						|
            gebData.tokenContract.deposit{value: _amtDeposit}();
 | 
						|
        } else {
 | 
						|
            _amtDeposit = _amtDeposit == uint(-1) ?  gebData.tokenContract.balanceOf(address(this)) : _amtDeposit;
 | 
						|
        }
 | 
						|
 | 
						|
        approve(gebData.tokenContract, address(gebData.colAddr), _amtDeposit);
 | 
						|
        gebData.tokenJoinContract.join(handler, _amtDeposit);
 | 
						|
 | 
						|
        managerContract.modifySAFECollateralization(
 | 
						|
            gebData._safe,
 | 
						|
            toInt(convertTo18(gebData.tokenJoinContract.decimals(), _amtDeposit)),
 | 
						|
            _getBorrowAmt(
 | 
						|
                address(gebData.safeEngineContract),
 | 
						|
                handler,
 | 
						|
                collateralType,
 | 
						|
                _amtBorrow
 | 
						|
            )
 | 
						|
        );
 | 
						|
 | 
						|
        managerContract.transferInternalCoins(
 | 
						|
            gebData._safe,
 | 
						|
            address(this),
 | 
						|
            toRad(_amtBorrow)
 | 
						|
        );
 | 
						|
 | 
						|
        if (gebData.safeEngineContract.safeRights(address(this), address(coinJoinContract)) == 0) {
 | 
						|
            gebData.safeEngineContract.approveSAFEModification(address(coinJoinContract));
 | 
						|
        }
 | 
						|
 | 
						|
        coinJoinContract.exit(address(this), _amtBorrow);
 | 
						|
 | 
						|
        setUint(setIdDeposit, _amtDeposit);
 | 
						|
        setUint(setIdBorrow, _amtBorrow);
 | 
						|
 | 
						|
        _eventName = "LogDepositAndBorrow(uint256,bytes32,uint256,uint256,uint256,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(
 | 
						|
            gebData._safe,
 | 
						|
            collateralType,
 | 
						|
            _amtDeposit,
 | 
						|
            _amtBorrow,
 | 
						|
            getIdDeposit,
 | 
						|
            getIdBorrow,
 | 
						|
            setIdDeposit,
 | 
						|
            setIdBorrow
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @dev Exit Coin from handler.
 | 
						|
     * @notice Exit Coin from handler.
 | 
						|
     * @param safe Safe ID.
 | 
						|
     * @param amt token amount to exit.
 | 
						|
     * @param getId Get token amount at this ID from `InstaMemory` Contract.
 | 
						|
     * @param setId Set token amount at this ID in `InstaMemory` Contract.
 | 
						|
    */
 | 
						|
    function exit(
 | 
						|
        uint256 safe,
 | 
						|
        uint256 amt,
 | 
						|
        uint256 getId,
 | 
						|
        uint256 setId
 | 
						|
    ) external payable returns (string memory _eventName, bytes memory _eventParam) {
 | 
						|
        uint _amt = getUint(getId, amt);
 | 
						|
        uint _safe = getSafe(safe);
 | 
						|
        (bytes32 collateralType, address handler) = getSafeData(_safe);
 | 
						|
 | 
						|
        SafeEngineLike safeEngineContract = SafeEngineLike(managerContract.safeEngine());
 | 
						|
        if(_amt == uint(-1)) {
 | 
						|
            _amt = safeEngineContract.coinBalance(handler);
 | 
						|
            _amt = _amt / 10 ** 27;
 | 
						|
        }
 | 
						|
 | 
						|
        managerContract.transferInternalCoins(
 | 
						|
            _safe,
 | 
						|
            address(this),
 | 
						|
            toRad(_amt)
 | 
						|
        );
 | 
						|
 | 
						|
        if (safeEngineContract.safeRights(address(this), address(coinJoinContract)) == 0) {
 | 
						|
            safeEngineContract.approveSAFEModification(address(coinJoinContract));
 | 
						|
        }
 | 
						|
 | 
						|
        coinJoinContract.exit(address(this), _amt);
 | 
						|
 | 
						|
        setUint(setId, _amt);
 | 
						|
 | 
						|
        _eventName = "LogExit(uint256,bytes32,uint256,uint256,uint256)";
 | 
						|
        _eventParam = abi.encode(_safe, collateralType, _amt, getId, setId);
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
contract ConnectV2Reflexer is GebResolver {
 | 
						|
    string public constant name = "Reflexer-v1";
 | 
						|
}
 |