/*向债仓锁定数字资产*/
        public static bool Lock(byte[] addr, BigInteger value)
        {
            if (addr.Length != 20) return false;

            if (value == 0) return false;

            byte[] key = addr.Concat(ConvertN(0));
            byte[] cdp = Storage.Get(Storage.CurrentContext, key);
            if (cdp.Length == 0) return false;

            byte[] to = Storage.Get(Storage.CurrentContext, STORAGE_ACCOUNT);
            if (to.Length == 0) return false;

            object[] arg = new object[3];
            arg[0] = addr;
            arg[1] = to;
            arg[2] = value;

            if (!(bool)SDTContract("transfer", arg)) return false;
            
            var txid = ((Transaction)ExecutionEngine.ScriptContainer).Hash;

            //object[] obj = new object[1];
            //obj[0] = txid;

            //TransferInfo transferInfo = (TransferInfo)SDTContract("getTXInfo", obj);


            /*校验交易信息*/
            //if (transferInfo.from != addr || transferInfo.to != to || value != transferInfo.value) return false;

            byte[] used = Storage.Get(Storage.CurrentContext, txid);
            /*判断txid是否已被使用*/
            if (used.Length != 0) return false;

            CDPTransferInfo cdpInfo = (CDPTransferInfo)Helper.Deserialize(cdp);

            cdpInfo.locked = cdpInfo.locked + value; 
            BigInteger currLock = cdpInfo.locked;

            Storage.Put(Storage.CurrentContext, key, Helper.Serialize(cdpInfo));

            //记录交易详细数据
            CDPTransferDetail detail = new CDPTransferDetail();
            detail.from = addr;
            detail.cdpTxid = cdpInfo.txid;
            detail.type = (int)ConfigTranType.TRANSACTION_TYPE_LOCK;
            detail.operated = value;
            detail.hasLocked = currLock;
            detail.hasDrawed = cdpInfo.hasDrawed;
            detail.txid = txid;
            Storage.Put(Storage.CurrentContext, txid, Helper.Serialize(detail));

            /*记录txid 已被使用*/
            Storage.Put(Storage.CurrentContext, txid, addr);
            return true;
        }
        private static Boolean shut(byte[] addr)
        {
            //CDP是否存在
            var key = addr.Concat(ConvertN(0));

            byte[] cdp = Storage.Get(Storage.CurrentContext, key);
            if (cdp.Length == 0)
                return false;
            CDPTransferInfo cdpInfo = (CDPTransferInfo)Helper.Deserialize(cdp);

            byte[] owner = cdpInfo.owner;
            BigInteger locked = cdpInfo.locked;
            BigInteger hasDrawed = cdpInfo.hasDrawed;

            //当前余额必须要大于负债
            BigInteger balance = balanceOf(addr);
            if (hasDrawed > balance) return false;

            var txid = ((Transaction)ExecutionEngine.ScriptContainer).Hash;

            //从合约地址转账
            byte[] from = Storage.Get(Storage.CurrentContext, STORAGE_ACCOUNT);
            object[] arg = new object[3];
            arg[0] = from;
            arg[1] = owner;
            arg[2] = locked;

            if (!(bool)SDTContract("transfer_contract", arg)) return false;

            if (hasDrawed > 0)
            {
                //先要销毁SD
                transfer(addr, null, hasDrawed);
                //减去总量
                operateTotalSupply(0 - hasDrawed);
            }
            //关闭CDP
            Storage.Delete(Storage.CurrentContext, key);

            //记录交易详细数据
            CDPTransferDetail detail = new CDPTransferDetail();
            detail.from = addr;
            detail.cdpTxid = cdpInfo.txid;
            detail.txid = txid;
            detail.type = (int)ConfigTranType.TRANSACTION_TYPE_SHUT;
            detail.operated = hasDrawed;
            detail.hasLocked = locked;
            detail.hasDrawed = hasDrawed;
            Storage.Put(Storage.CurrentContext, txid, Helper.Serialize(detail));
            return true;
        }
        public static bool draw(byte[] addr, BigInteger drawSdusdValue)
        {
            if (addr.Length != 20) return false;

            if (drawSdusdValue <= 0) return false;

            byte[] key = addr.Concat(ConvertN(0));
            byte[] cdp = Storage.Get(Storage.CurrentContext, key);
            if (cdp.Length == 0) return false;
            //获取CDP
            CDPTransferInfo cdpInfo = (CDPTransferInfo)Helper.Deserialize(cdp);
            BigInteger locked = cdpInfo.locked;
            BigInteger hasDrawed = cdpInfo.hasDrawed;
             
            BigInteger sdt_price = getConfig(CONFIG_SDT_PRICE); 
            BigInteger sdt_rate = getConfig(CONFIG_SDT_RATE); ;

            BigInteger sdusd_limit = sdt_price * locked * 100 / sdt_rate;

            if (sdusd_limit < hasDrawed + drawSdusdValue) return false;

            if (!increase(addr, drawSdusdValue)) return false; ;

            cdpInfo.hasDrawed = hasDrawed + drawSdusdValue;
            Storage.Put(Storage.CurrentContext, key, Helper.Serialize(cdpInfo));
            
            //记录交易详细数据
            var txid = ((Transaction)ExecutionEngine.ScriptContainer).Hash;
            CDPTransferDetail detail = new CDPTransferDetail();
            detail.from = addr;
            detail.cdpTxid = cdpInfo.txid;
            detail.txid = txid;
            detail.type = (int)ConfigTranType.TRANSACTION_TYPE_DRAW;
            detail.operated = drawSdusdValue;
            detail.hasLocked = locked;
            detail.hasDrawed = hasDrawed;

            Storage.Put(Storage.CurrentContext, txid, Helper.Serialize(detail));
             
            return true;
        }