EthereumEthereum
0xd8...79ac
KittenETHv0

KittenETHv0

KittenETHv0

代币
市值
$1.00
 
价格
2%
此合同的源代码已经过验证!
合同元数据
编译器
0.6.12+commit.27d51765
语言
Solidity
合同源代码
文件 1 的 1:KittenETHv0.sol
// SPDX-License-Identifier: UNLICENSED
//   _    _ _   _                __ _                            
//  | |  (_) | | |              / _(_)                           
//  | | ___| |_| |_ ___ _ __   | |_ _ _ __   __ _ _ __   ___ ___ 
//  | |/ / | __| __/ _ \ '_ \  |  _| | '_ \ / _` | '_ \ / __/ _ \
//  |   <| | |_| ||  __/ | | |_| | | | | | | (_| | | | | (_|  __/
//  |_|\_\_|\__|\__\___|_| |_(_)_| |_|_| |_|\__,_|_| |_|\___\___|
//
//  KittenSwap Lending v0
//
//  https://www.KittenSwap.org/
//
pragma solidity ^0.6.12;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require (c >= a, "!!add");
        return c;
    }
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require (b <= a, "!!sub");
        uint256 c = a - b;
        return c;
    }
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require (b <= a, errorMessage);
        uint c = a - b;
        return c;
    }    
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }
        uint256 c = a * b;
        require (c / a == b, "!!mul");
        return c;
    }
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require (b > 0, "!!div");
        uint256 c = a / b;
        return c;
    }
}

contract ERC20Detailed {
    string private _name;
    string private _symbol;
    uint8 private _decimals;

    constructor (string memory name, string memory symbol, uint8 decimals) public {
        _name = name;
        _symbol = symbol;
        _decimals = decimals;
    }
    function name() public view returns (string memory) {
        return _name;
    }
    function symbol() public view returns (string memory) {
        return _symbol;
    }
    function decimals() public view returns (uint8) {
        return _decimals;
    }
}

////////////////////////////////////////////////////////////////////////////////

interface LIQUID_TOKEN {
    function totalSupply (  ) external view returns ( uint256 );
    function getTokenReserve (  ) external view returns ( uint256 );
    function getEthReserve (  ) external view returns ( uint256 );
    
    function balanceOf ( address account ) external view returns ( uint256 );
    function transfer ( address recipient, uint256 amount ) external returns ( bool );
    function transferFrom ( address sender, address recipient, uint256 amount ) external returns ( bool );    
    
    function buyToken ( uint256 minTokenAmt, uint256 expireTimestamp ) external payable;    
    function sellToken ( uint256 tokenAmt, uint256 minEthAmt, uint256 expireTimestamp ) external;
}

////////////////////////////////////////////////////////////////////////////////

contract KittenETHv0 is ERC20Detailed
{
    using SafeMath for uint;
    
    address public constant LIQUID_ADDR = 0xC618D56b6D606E59c6B87Af724AB5a91eb40D1cb;
    uint public MIGRATION_TIMESTAMP = 0;               // for migration
    uint public MIGRATION_LIQUIDATION_WAIT = 14 days;  // gov can liquidate forgotten loans some days after migration starts
    uint public FLASH_LOAN_BP = 10;                    // in terms of basis points
    
    ////////////////////////////////////////////////////////////////////////////////
    
    LIQUID_TOKEN private constant LIQUID = LIQUID_TOKEN(LIQUID_ADDR);
    address public govAddr;
        
    constructor () public ERC20Detailed("KittenETHv0", "KittenETHv0", 18) {
        govAddr = msg.sender;
    }
    
    modifier govOnly() {
    	require (msg.sender == govAddr, "!gov");
    	_;
    }
    
    function govTransferAddr(address newAddr) external govOnly {
    	require (newAddr != address(0), "!addr");
    	govAddr = newAddr;
    }
    
    function govSetMIGRATION_TIMESTAMP(uint $MIGRATION_TIMESTAMP) external govOnly {
        require ($MIGRATION_TIMESTAMP > block.timestamp);
    	MIGRATION_TIMESTAMP = $MIGRATION_TIMESTAMP;
    }
    
    function govSetFLASH_LOAN_BP(uint $FLASH_LOAN_BP) external govOnly {
        require (FLASH_LOAN_BP <= 60);
    	FLASH_LOAN_BP = $FLASH_LOAN_BP;
    }    
    
    ////////////////////////////////////////////////////////////////////////////////
    
    function _msgSender() internal view returns (address payable) {
        return msg.sender;
    }
    
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
    
    mapping (address => uint) private _balances;
    mapping (address => mapping (address => uint)) private _allowances;

    uint private _totalSupply;
    function totalSupply() public view returns (uint) {
        return _totalSupply;
    }
    function balanceOf(address account) public view returns (uint) {
        return _balances[account];
    }
    function transfer(address recipient, uint amount) public returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }
    function transferFrom(address sender, address recipient, uint amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
        return true;
    }
    function _transfer(address sender, address recipient, uint amount) internal {
        require (sender != address(0), "ERC20: transfer from the zero address");
        require (recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
        
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }
    
    //------------------------------------------------------------------------------
    
    function allowance(address owner, address spender) public view returns (uint) {
        return _allowances[owner][spender];
    }
    function approve(address spender, uint amount) public returns (bool) {
        _approve(_msgSender(), spender, amount);
        return true;
    }
    function _approve(address owner, address spender, uint amount) internal {
        require (owner != address(0), "ERC20: approve from the zero address");
        require (spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }
    
    //------------------------------------------------------------------------------
    
    function _mint(address account, uint amount) internal {
        require (account != address(0), "ERC20: mint to the zero address");

        _balances[account] = _balances[account].add(amount);
        _totalSupply = _totalSupply.add(amount);

        emit Transfer(address(0), account, amount);
    }
    function _burn(address account, uint amount) internal {
        require (account != address(0), "ERC20: burn from the zero address");
        
        _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
        _totalSupply = _totalSupply.sub(amount);

        emit Transfer(account, address(0), amount);
    }
    
    ////////////////////////////////////////////////////////////////////////////////

    uint constant PRICE_SCALE = 10 ** 10;
    function getLiqEthFloorPriceScaled() internal view returns (uint)
    {
        uint AMM_PRODUCT = (LIQUID.getTokenReserve()).mul(LIQUID.getEthReserve());
        uint TOTAL_SUPPLY = LIQUID.totalSupply();

        return PRICE_SCALE.mul(AMM_PRODUCT).div(TOTAL_SUPPLY).div(TOTAL_SUPPLY);
    }
    
    ////////////////////////////////////////////////////////////////////////////////

    event LOCK_ETH(address indexed user, uint ethAmt, uint kethAmt);
    event UNLOCK_ETH(address indexed user, uint ethAmt, uint kethAmt);
    
    function getContractValueInEth() public view returns (uint)
    {
        uint ethValue = (address(this).balance);
        
        uint liqValue = (LIQUID.balanceOf(address(this))).mul(getLiqEthFloorPriceScaled()) / (PRICE_SCALE);
        
        return ethValue.add(liqValue);
    }

    function lockEth() external payable // lock ETH for lending, and mint KittenEth
    {
        //-------- receive ETH from user --------
        address user = msg.sender;
        uint ethInAmt = msg.value;
        require (ethInAmt > 0, '!ethInAmt');
        
        //-------- compute KittenETH mint amt --------
        uint kethMintAmt = 0;
        if (_totalSupply == 0) { 
            kethMintAmt = ethInAmt; // initial price: 1 kETH = 1 ETH
        }
        else {                
            kethMintAmt = ethInAmt.mul(_totalSupply).div(getContractValueInEth().sub(ethInAmt));
        }
        
        //-------- mint KittenETH to user --------
        _mint(user, kethMintAmt);
        emit LOCK_ETH(user, ethInAmt, kethMintAmt);
    }
    
    function unlockEth(uint kethBurnAmt) external // unlock ETH, and burn KittenEth
    {
        require (kethBurnAmt > 0, '!kethBurnAmt');
        address payable user = msg.sender;

        //-------- compute ETH out amt --------
        uint ethOutAmt = kethBurnAmt.mul(getContractValueInEth()).div(_totalSupply);
        require (address(this).balance >= ethOutAmt, '!ethInContract');

        //-------- burn KittenETH from user --------
        _burn(user, kethBurnAmt);
        
        //-------- send ETH to user --------
        user.transfer(ethOutAmt);
        emit UNLOCK_ETH(user, ethOutAmt, kethBurnAmt);
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    mapping (address => uint) public liqLocked;
    
    event LOCK_LIQ(address indexed user, uint liqAmt, uint ethAmt);
    event UNLOCK_LIQ(address indexed user, uint liqAmt, uint ethAmt);    
    
    function lockLiq(uint liqInAmt) external // lock LIQUID to borrow ETH
    {
        require (liqInAmt > 0, '!liqInAmt');
        require (block.timestamp < MIGRATION_TIMESTAMP, '!migration'); // can't lock after migration starts
        address payable user = msg.sender;

        //-------- compute ETH out amt --------
        uint ethOutAmt = liqInAmt.mul(getLiqEthFloorPriceScaled()) / (PRICE_SCALE);
        require (address(this).balance >= ethOutAmt, '!ethInContract');

        //--------  send LIQUID to contract --------
        LIQUID.transferFrom(user, address(this), liqInAmt); 
        liqLocked[user] = liqLocked[user].add(liqInAmt);
        
        //-------- send ETH to user --------
        user.transfer(ethOutAmt);
        emit LOCK_LIQ(user, liqInAmt, ethOutAmt);
    }
    
    function unlockLiq() external payable // payback ETH to unlock LIQUID
    {
        //-------- receive ETH from user --------
        uint ethInAmt = msg.value;
        require (ethInAmt > 0, '!ethInAmt');
        uint ethReturnAmt = 0;
        address payable user = msg.sender;

        //-------- compute LIQUID out amt --------
        uint LiqEthFloorPriceScaled = getLiqEthFloorPriceScaled();

        uint liqOutAmt = ethInAmt.mul(PRICE_SCALE).div(LiqEthFloorPriceScaled);
        if (liqOutAmt > liqLocked[user])
        {
            liqOutAmt = liqLocked[user];
            ethReturnAmt = ethInAmt.sub(
                    liqOutAmt.mul(LiqEthFloorPriceScaled) / (PRICE_SCALE)
                );
        }
        
        //--------  send LIQUID to user --------
        liqLocked[user] = liqLocked[user].sub(liqOutAmt);
        LIQUID.transfer(user, liqOutAmt);
        
        //-------- return extra ETH to user --------
        if (ethReturnAmt > 10 ** 8) { // ignore dust
            user.transfer(ethReturnAmt);
        }
        emit UNLOCK_LIQ(user, liqOutAmt, ethInAmt.sub(ethReturnAmt));
    }
    
    ////////////////////////////////////////////////////////////////////////////////
    
    receive() external payable { // receive ETH (from selling LIQUID)
        require(msg.sender == LIQUID_ADDR, '!sender');
    }

    function flashUnlockLiqAndSell(address payable user, uint liqUnlockAmt, uint liqSellAmt, uint liqSellMinEthAmt, uint liqSellExpireTimestamp) external payable
    {
        require (
            (user == msg.sender) 
            || // gov can liquidate forgotten loans some days after migration starts
            ((block.timestamp.sub(MIGRATION_LIQUIDATION_WAIT) > MIGRATION_TIMESTAMP) && (govAddr == msg.sender))
        , '!user');
        
        if (liqUnlockAmt > liqLocked[user])
            liqUnlockAmt = liqLocked[user];
        if (liqSellAmt > liqUnlockAmt)
            liqSellAmt = liqUnlockAmt;

        //-------- receive ETH from user --------
        uint ethInAmt = msg.value;
        
        //-------- compute ETH required for unlocking LIQUID --------
        uint ethBorrowAmt = 0;
        uint ethOutAmt = 0;
        
        uint ethRequiredForUnlock = liqUnlockAmt.mul(getLiqEthFloorPriceScaled()) / (PRICE_SCALE);
        if (ethRequiredForUnlock > ethInAmt) {
            ethBorrowAmt = (ethRequiredForUnlock - ethInAmt).mul(10000 + FLASH_LOAN_BP) / 10000; // add FLASH_LOAN_BP fee
        } else {
            ethOutAmt = ethInAmt - ethRequiredForUnlock;
        }

        //-------- sell LIQUID --------
        uint liqLoss = 0;
        uint ethGain = 0;
        if (liqSellAmt > 0)
        {
            uint liqBefore = LIQUID.balanceOf(address(this));
            uint ethBefore = address(this).balance;
            
            LIQUID.sellToken(liqSellAmt, liqSellMinEthAmt, liqSellExpireTimestamp); // sell LIQUID
    
            liqLoss = liqBefore.sub(LIQUID.balanceOf(address(this)), '!liqLoss'); // now contract has less LIQUID
            ethGain = (address(this).balance).sub(ethBefore, '!ethGain'); // now contract has more ETH            
        }
        
        //-------- payback flash-loan (if occured) --------
        if (ethBorrowAmt > 0) { // ethOutAmt = 0
            ethOutAmt = ethGain.sub(ethBorrowAmt, '!ethBorrowAmt'); // will throw if not enough
        } else { // ethBorrowAmt = 0
            ethOutAmt = ethOutAmt.add(ethGain);
        }

        //-------- unlock LIQUID --------
        liqLocked[user] = liqLocked[user].sub(liqUnlockAmt, '!liqUnlockAmt');
        
        //-------- send LIQUID to user --------
        if (liqUnlockAmt > liqLoss) {
            LIQUID.transfer(user, liqUnlockAmt - liqLoss);
        }
        //-------- send ETH to user --------
        if (ethOutAmt > 10 ** 8) { // ignore dust
            user.transfer(ethOutAmt);
        }
        
        emit UNLOCK_LIQ(user, liqUnlockAmt, ethRequiredForUnlock);
    }
    
    function flashBuyLiqAndLock(uint ethBorrowAmt, uint liqLockAmt, uint liqBuyMinAmt, uint liqBuyExpireTimestamp) external payable
    {
        require (block.timestamp < MIGRATION_TIMESTAMP, '!migration'); // can't lock after migration starts        
        address payable user = msg.sender;
        
        //-------- receive ETH from user --------
        uint ethInAmt = msg.value;
        
        //-------- buy LIQUID --------
        uint liqGain = 0;
        uint ethLoss = 0;
        {
            uint liqBefore = LIQUID.balanceOf(address(this));
            uint ethBefore = address(this).balance;
            
            //-------- borrow flash-loan --------
            uint ethTotalInAmt = ethInAmt.add(ethBorrowAmt);
            
            require (ethBefore >= ethTotalInAmt, '!ethInContract');
            LIQUID.buyToken {value: ethTotalInAmt} (liqBuyMinAmt, liqBuyExpireTimestamp); // buy LIQUID
    
            liqGain = (LIQUID.balanceOf(address(this))).sub(liqBefore, '!liqGain'); // now contract has more LIQUID
            ethLoss = ethBefore.sub(address(this).balance, '!ethLoss'); // now contract has less ETH            
        }
        
        //-------- compute ETH gain from locking LIQUID --------
        if (liqLockAmt > liqGain) {
            liqLockAmt = liqGain;
        }
        uint ethLockOutAmt = liqLockAmt.mul(getLiqEthFloorPriceScaled()) / (PRICE_SCALE);
        
        //-------- payback flash-loan --------
        uint ethOutAmt = ethInAmt.add(ethLockOutAmt).sub(ethLoss, '!ethLockOutAmt'); // will throw if not enough
        ethOutAmt = ethOutAmt.sub(ethBorrowAmt.mul(FLASH_LOAN_BP) / 10000, '!ethBorrowAmt');

        //-------- lock LIQUID --------
        liqLocked[user] = liqLocked[user].add(liqLockAmt);
        
        //-------- send LIQUID to user --------
        if (liqGain > liqLockAmt) {
            LIQUID.transfer(user, liqGain - liqLockAmt);
        }
        //-------- send ETH to user --------
        if (ethOutAmt > 10 ** 8) { // ignore dust
            require (address(this).balance >= ethOutAmt, '!ethOutAmt');
            user.transfer(ethOutAmt);
        }
        
        emit LOCK_LIQ(user, liqLockAmt, ethLockOutAmt);
    }
}
设置
{
  "compilationTarget": {
    "KittenETHv0.sol": "KittenETHv0"
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 999
  },
  "remappings": []
}
ABI
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"kethAmt","type":"uint256"}],"name":"LOCK_ETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"liqAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAmt","type":"uint256"}],"name":"LOCK_LIQ","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"kethAmt","type":"uint256"}],"name":"UNLOCK_ETH","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"liqAmt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAmt","type":"uint256"}],"name":"UNLOCK_LIQ","type":"event"},{"inputs":[],"name":"FLASH_LOAN_BP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LIQUID_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIGRATION_LIQUIDATION_WAIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIGRATION_TIMESTAMP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethBorrowAmt","type":"uint256"},{"internalType":"uint256","name":"liqLockAmt","type":"uint256"},{"internalType":"uint256","name":"liqBuyMinAmt","type":"uint256"},{"internalType":"uint256","name":"liqBuyExpireTimestamp","type":"uint256"}],"name":"flashBuyLiqAndLock","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address payable","name":"user","type":"address"},{"internalType":"uint256","name":"liqUnlockAmt","type":"uint256"},{"internalType":"uint256","name":"liqSellAmt","type":"uint256"},{"internalType":"uint256","name":"liqSellMinEthAmt","type":"uint256"},{"internalType":"uint256","name":"liqSellExpireTimestamp","type":"uint256"}],"name":"flashUnlockLiqAndSell","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getContractValueInEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"govAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"$FLASH_LOAN_BP","type":"uint256"}],"name":"govSetFLASH_LOAN_BP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"$MIGRATION_TIMESTAMP","type":"uint256"}],"name":"govSetMIGRATION_TIMESTAMP","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAddr","type":"address"}],"name":"govTransferAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"liqLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liqInAmt","type":"uint256"}],"name":"lockLiq","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"kethBurnAmt","type":"uint256"}],"name":"unlockEth","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockLiq","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]