public static object setAssetSetting(byte[] assetHash, BigInteger enable, BigInteger valueMin, BigInteger valueUnit, BigInteger handlingFeeRate, string transferMethod) { //只有管理员地址可以操作此方法 if (!checkSpuerAdmin()) { throw new InvalidOperationException("error"); } if (valueMin < 0 || valueUnit < 0 || handlingFeeRate < 0) { throw new InvalidOperationException("error"); } if (enable != 0 && enable != 1) { throw new InvalidOperationException("error"); } assetSetting assetSetting = new assetSetting(); assetSetting.enable = enable; assetSetting.valueMin = valueMin; assetSetting.valueUnit = valueUnit; assetSetting.handlingFeeRate = handlingFeeRate; assetSetting.appTransferMethod = transferMethod; StorageMap assetSettingMap = Storage.CurrentContext.CreateMap("assetSettingMap"); assetSettingMap.Put(assetHash, assetSetting.Serialize()); //通知资产设置事件 onSetAssetSetting(assetHash, assetSetting); return(true); }
private static bool NEP5transfer(byte[] from, byte[] to, byte[] assetHash, BigInteger amount) { StorageMap balanceMap = Storage.CurrentContext.CreateMap("balanceMap"); assetSetting assetSetting = getAssetSetting(assetHash); //多判断总比少判断好 if (amount <= 0) { throw new InvalidOperationException("error"); } if (from.Length != 20 || to.Length != 20) { throw new InvalidOperationException("error"); } //构造入参 object[] transInput = new object[3]; transInput[0] = from; transInput[1] = to; transInput[2] = amount; //动态调用执行转账 deleDyncall dyncall = (deleDyncall)assetHash.ToDelegate(); bool result = (bool)dyncall(assetSetting.appTransferMethod, transInput); return(result); }
public static assetSetting getAssetSetting(byte[] assetHash) { StorageMap assetSettingMap = Storage.CurrentContext.CreateMap("assetSettingMap"); byte[] data = assetSettingMap.Get(assetHash); assetSetting assetSetting = new assetSetting(); assetSetting.enable = 0; if (data.Length > 0) { assetSetting = data.Deserialize() as assetSetting; } return(assetSetting); }
public static bool GetMoneyBack(byte[] who, byte[] assetHash, BigInteger amount) { StorageMap balanceMap = Storage.CurrentContext.CreateMap("balanceMap"); assetSetting assetSetting = getAssetSetting(assetHash); if (!Runtime.CheckWitness(who) && !checkSpuerAdmin()) { throw new InvalidOperationException("error"); } //多判断总比少判断好 if (amount <= 0) { throw new InvalidOperationException("error"); } if (who.Length != 20) { throw new InvalidOperationException("error"); } var balance = balanceMap.Get(who.Concat(assetHash)).AsBigInteger(); if (balance < amount) { throw new InvalidOperationException("error"); } //NEP5转出 bool result = NEP5transfer(ExecutionEngine.ExecutingScriptHash, who, assetHash, amount); if (result) { if (balance == amount) { balanceMap.Delete(who.Concat(assetHash)); } else { balance -= amount; balanceMap.Put(who.Concat(assetHash), balance); } onGetMoneyBack(who, assetHash, amount); return(true); } throw new InvalidOperationException("error"); }
/// <summary> /// 拍卖某个域名 /// </summary> /// <param name="domainArray"></param> /// <param name="startPrice"></param> /// <param name="endPrice"></param> /// <param name="ratio"></param> /// <returns></returns> public static bool Auction(string[] domainArray, byte[] assetHash, BigInteger startPrice, BigInteger endPrice, BigInteger salePrice, BigInteger mortgagePayments) { //不允许的资产不能定价 assetSetting assetSetting = getAssetSetting(assetHash); if (assetSetting.enable != 1) { throw new InvalidOperationException("error"); } //价格必须大于0 if (startPrice <= 0 || endPrice <= 0 || endPrice > startPrice) { throw new InvalidOperationException("error"); } //合约限制最小价格为0.1,并且小数点后面不能超过一位(按照精度2换算),NNC为10 if (startPrice < assetSetting.valueMin || startPrice % assetSetting.valueUnit > 0 || endPrice < assetSetting.valueMin || endPrice % assetSetting.valueUnit > 0) { throw new InvalidOperationException("error"); } //限制每次降价的精度 if ((salePrice < assetSetting.valueMin || salePrice % assetSetting.valueUnit > 0) && salePrice != 0) { throw new InvalidOperationException("error"); } //验证押金 BigInteger minMortgagePayments = getSysSetting("minMortgagePayments").AsBigInteger(); if (mortgagePayments < minMortgagePayments) { throw new InvalidOperationException("error"); } byte[] fullHash = NameHashArray(domainArray); //先获取这个域名的信息 OwnerInfo ownerInfo = GetOwnerInfo(fullHash); var auctioner = ownerInfo.owner; //域名没有初始化不能上架 if (ownerInfo.owner.Length == 0) { throw new InvalidOperationException("error"); } //域名已经到期了不能上架 if (!verifyExpires(ownerInfo.TTL)) { throw new InvalidOperationException("error"); } //验证权限 if (!Runtime.CheckWitness(auctioner)) { throw new InvalidOperationException("error"); } //将域名抵押给本合约(域名所有权:卖家=>DEX合约) //本合约的scripthash byte[] scriptHash = ExecutionEngine.ExecutingScriptHash; deleDyncall centerCall = (deleDyncall)getSysSetting("domainCenterHash").ToDelegate(); var result = (byte[])centerCall("owner_SetOwner", new object[3] { auctioner, fullHash, scriptHash }); if (result.AsBigInteger() != 1) { throw new InvalidOperationException("error"); } //扣除押金 var mortgageAssetHash = getSysSetting("mortgageAssetHash"); StorageMap balanceMap = Storage.CurrentContext.CreateMap("balanceMap"); var balanceOfBuyer = balanceMap.Get(auctioner.Concat(mortgageAssetHash)).AsBigInteger(); balanceOfBuyer = balanceOfBuyer - mortgagePayments; if (balanceOfBuyer > 0) { balanceMap.Put(auctioner.Concat(mortgageAssetHash), balanceOfBuyer); } else if (balanceOfBuyer == 0) { balanceMap.Delete(auctioner.Concat(mortgageAssetHash)); } else { throw new Exception("no money"); } onDexTransfer(auctioner, new byte[] { }, mortgageAssetHash, mortgagePayments); //获取开始拍卖的时间戳 var timeStamp = Blockchain.GetHeader(Blockchain.GetHeight()).Timestamp; //获取交易id var auctionid = (ExecutionEngine.ScriptContainer as Transaction).Hash; //记录拍卖的信息 AuctionInfo auctionInfo = new AuctionInfo() { auctionid = auctionid, fullDomain = getFullStrForArray(domainArray), fullHash = fullHash, auctioner = auctioner, startPrice = startPrice, endPrice = endPrice, salePrice = salePrice, startTimeStamp = timeStamp, assetHash = assetHash, mortgagePayments = mortgagePayments, }; StorageMap auctionInfoMap = Storage.CurrentContext.CreateMap("auctionInfoMap"); //如果已经存在这个id报错 if (auctionInfoMap.Get(auctionid).Length != 0) { throw new Exception("error"); } auctionInfoMap.Put(auctionid, auctionInfo.Serialize()); //记录当前这个域名正在拍卖的场次是什么 StorageMap auctionInfoCurrentMap = Storage.CurrentContext.CreateMap("auctionInfoCurrentMap"); auctionInfoCurrentMap.Put(fullHash, auctionid); onAuction(auctionInfo); return(true); }
/// <summary> /// 出售 /// </summary> /// <param name="buyer">求购者</param> /// <param name="fullHash"></param> /// <param name="assetHash"></param> /// <returns></returns> public static bool Sell(byte[] offerid) { //获取求购信息 OfferToBuyInfo offerToBuyInfo = GetOfferToBuyInfo(offerid); if (offerToBuyInfo.fullHash.Length == 0)//没求购过别浪费时间了 { throw new InvalidOperationException("error"); } var fullHash = offerToBuyInfo.fullHash; var buyer = offerToBuyInfo.buyer; var assetHash = offerToBuyInfo.assetHash; //先获取这个域名的信息 OwnerInfo ownerInfo = GetOwnerInfo(fullHash); if (ownerInfo.owner.Length == 0 || !verifyExpires(ownerInfo.TTL))//验证域名是否有效 { throw new InvalidOperationException("error"); } //验证权限 var seller = ownerInfo.owner; if (!Runtime.CheckWitness(seller)) { throw new InvalidOperationException("error"); } //进行域名的转让操作(域名所有权:卖家=>买家) deleDyncall centerCall = (deleDyncall)getSysSetting("domainCenterHash").ToDelegate(); var result = (byte[])centerCall("owner_SetOwner", new object[3] { seller, fullHash, buyer }); if (result.AsBigInteger() != 1) //如果域名所有权转移失败,返回失败 { throw new InvalidOperationException("error"); } //把钱转给卖家 assetSetting assetSetting = getAssetSetting(assetHash); BigInteger handlingFee = offerToBuyInfo.price * assetSetting.handlingFeeRate / fixedNumber; //handlingFeeRate是事先乘10000存储的 StorageMap balanceMap = Storage.CurrentContext.CreateMap("balanceMap"); var balanceOfSeller = balanceMap.Get(seller.Concat(assetHash)).AsBigInteger(); //卖家 balanceOfSeller = balanceOfSeller + offerToBuyInfo.price - handlingFee; //给卖方增加钱(扣除手续费) balanceMap.Put(seller.Concat(assetHash), balanceOfSeller); onDexTransfer(new byte[] { }, seller, assetHash, offerToBuyInfo.price - handlingFee); //转移手续费 //发送手续费到分红池 if (handlingFee > 0) { if (!NEP5transfer(ExecutionEngine.ExecutingScriptHash, getSysSetting("dividingPoolAddr"), assetHash, handlingFee)) { throw new Exception("NEP5transfer is wrong"); } } //把押金还给买家 var mortgageAssetHash = getSysSetting("mortgageAssetHash"); var nncBalanceOfOffer = balanceMap.Get(buyer.Concat(mortgageAssetHash)).AsBigInteger(); nncBalanceOfOffer += offerToBuyInfo.mortgagePayments; balanceMap.Put(buyer.Concat(mortgageAssetHash), nncBalanceOfOffer); onDexTransfer(new byte[] { }, buyer, mortgageAssetHash, offerToBuyInfo.mortgagePayments); //删除此条求购信息 DeleteOfferToBuyInfo(offerid); //通知 onSell(seller, offerToBuyInfo); return(true); }
/// <summary> /// 求购 /// </summary> /// <param name="fullhash"></param> /// <param name="price"></param> /// <returns></returns> public static bool OfferToBuy(byte[] buyer, string[] domainArray, byte[] assetHash, BigInteger price, BigInteger MortgagePayments) { if (!Runtime.CheckWitness(buyer)) { throw new InvalidOperationException("error"); } if (price <= 0) { throw new InvalidOperationException("error"); } //不允许的资产不能定价 assetSetting assetSetting = getAssetSetting(assetHash); if (assetSetting.enable != 1) { throw new InvalidOperationException("error"); } //价格必须大于0 if (price <= 0) { throw new InvalidOperationException("error"); } //支付的抵押金数额必须大于 BigInteger minMortgagePayments = getSysSetting("minMortgagePayments").AsBigInteger(); if (MortgagePayments < minMortgagePayments) { throw new InvalidOperationException("error"); } //合约限制最小价格为0.1,并且小数点后面不能超过一位(按照精度2换算),NNC为10 if (price < assetSetting.valueMin || price % assetSetting.valueUnit > 0) { throw new InvalidOperationException("error"); } //获取域名的fullhash byte[] fullHash = NameHashArray(domainArray); //获取这个交易的txid byte[] offerid = (ExecutionEngine.ScriptContainer as Transaction).Hash; //获取求购信息 OfferToBuyInfo offerToBuyInfo = GetOfferToBuyInfo(offerid); if (offerToBuyInfo.fullHash.Length != 0)//已经有了这个资产的求购信息 同资产只能有一个求购 { throw new InvalidOperationException("error"); } //先获取这个域名的信息 OwnerInfo ownerInfo = GetOwnerInfo(fullHash); //域名没有初始化或者已经到期了不能求购 ???????先写着 再想想有没有必要限制 if (ownerInfo.owner.Length == 0 || !verifyExpires(ownerInfo.TTL)) { throw new InvalidOperationException("error"); } //不能求购属于自己的合约 if (buyer == ownerInfo.owner) { throw new InvalidOperationException("error"); } //看看有没有这么多钱 StorageMap balanceMap = Storage.CurrentContext.CreateMap("balanceMap"); var balanceOfBuyer = balanceMap.Get(buyer.Concat(assetHash)).AsBigInteger(); balanceOfBuyer = balanceOfBuyer - price; //扣钱 if (balanceOfBuyer > 0) { balanceMap.Put(buyer.Concat(assetHash), balanceOfBuyer); } else if (balanceOfBuyer == 0) { balanceMap.Delete(buyer.Concat(assetHash)); } else { throw new InvalidOperationException("error"); } onDexTransfer(buyer, new byte[] { }, assetHash, price); //扣除抵押金 var mortgageAssetHash = getSysSetting("mortgageAssetHash"); var nncBalanceOfBuyer = balanceMap.Get(buyer.Concat(mortgageAssetHash)).AsBigInteger(); //var nncBalanceOfContract = balanceMap.Get(ExecutionEngine.ExecutingScriptHash.Concat(nncHash)).AsBigInteger(); nncBalanceOfBuyer = nncBalanceOfBuyer - MortgagePayments; if (nncBalanceOfBuyer > 0) { balanceMap.Put(buyer.Concat(mortgageAssetHash), nncBalanceOfBuyer); } else if (nncBalanceOfBuyer == 0) { balanceMap.Delete(buyer.Concat(mortgageAssetHash)); } else { throw new InvalidOperationException("error"); } onDexTransfer(buyer, new byte[] { }, mortgageAssetHash, MortgagePayments); //更新这个域名的求购信息 offerToBuyInfo = new OfferToBuyInfo { offerid = offerid, fullHash = fullHash, buyer = buyer, assetHash = assetHash, price = price, fullDomain = getFullStrForArray(domainArray), mortgagePayments = MortgagePayments }; PutOfferToBuyInfo(offerid, offerToBuyInfo); onOfferToBuy(offerToBuyInfo); return(true); }
/// <summary> /// 竞拍 /// </summary> /// <param name="fullHash"></param> /// <param name="price">价格,价格合约内计算,但是要求传入是以防前端计算错误误导用户</param> /// <returns></returns> public static bool Bet(byte[] buyer, byte[] auctionid, byte[] assetHash, BigInteger price) { if (!Runtime.CheckWitness(buyer)) { throw new InvalidOperationException("error"); } //获取域名的拍卖情况 AuctionInfo auctionInfo = GetAuctionInfo(auctionid); //自己不能竞拍自己上架的域名 if (buyer == auctionInfo.auctioner) { throw new InvalidOperationException("error"); } if (auctionInfo.fullDomain == "") { throw new InvalidOperationException("error"); } //验证资产种类 if (auctionInfo.assetHash != assetHash) { throw new InvalidOperationException("error"); } //获取当前的时间戳 var currentTimeStamp = Blockchain.GetHeader(Blockchain.GetHeight()).Timestamp; //距离开始拍卖已经过了多久 var timeStamp = currentTimeStamp - auctionInfo.startTimeStamp; //获取降价的间隔 var interval = getSysSetting("interval").AsBigInteger(); //X小时一轮 开拍为0阶段 X小时后为1阶段 X*2小时后为2阶段 X*60*60 var phase = timeStamp / interval; //计算当前的价格 var currentPrice = auctionInfo.startPrice - auctionInfo.salePrice * phase; if (currentPrice < auctionInfo.endPrice) { currentPrice = auctionInfo.endPrice; } //对比下用户从前端获取到的价格 if (price != currentPrice) { throw new InvalidOperationException("error"); } //检查用户钱够不够 StorageMap balanceMap = Storage.CurrentContext.CreateMap("balanceMap"); var balanceOfBuyer = balanceMap.Get(buyer.Concat(assetHash)).AsBigInteger();//买家 if (balanceOfBuyer < price) { throw new InvalidOperationException("error"); } //合约将域名转让给买家 byte[] scriptHash = ExecutionEngine.ExecutingScriptHash; deleDyncall centerCall = (deleDyncall)getSysSetting("domainCenterHash").ToDelegate(); var result = (byte[])centerCall("owner_SetOwner", new object[3] { scriptHash, auctionInfo.fullHash, buyer }); if (result.AsBigInteger() != 1) { throw new InvalidOperationException("error"); } //购买者扣钱 balanceOfBuyer = balanceOfBuyer - price; if (balanceOfBuyer == 0) { balanceMap.Delete(buyer.Concat(assetHash)); } else { balanceMap.Put(buyer.Concat(assetHash), balanceOfBuyer); } onDexTransfer(buyer, new byte[] { }, assetHash, price); //转钱给拍卖者 //计算手续费 assetSetting assetSetting = getAssetSetting(assetHash); BigInteger handlingFee = price * assetSetting.handlingFeeRate / fixedNumber;//handlingFeeRate是事先乘10000存储的 //给卖方增加钱(扣除手续费) var auctioner = auctionInfo.auctioner; var balanceOfAuctioner = balanceMap.Get(auctioner.Concat(assetHash)).AsBigInteger(); balanceMap.Put(auctioner.Concat(assetHash), balanceOfAuctioner + price - handlingFee); onDexTransfer(new byte[] { }, auctioner, assetHash, price - handlingFee); //归还卖方的抵押金 var mortgageAssetHash = getSysSetting("mortgageAssetHash"); var nncBalanceOfAuctioner = balanceMap.Get(auctioner.Concat(mortgageAssetHash)).AsBigInteger(); balanceMap.Put(auctioner.Concat(mortgageAssetHash), nncBalanceOfAuctioner + auctionInfo.mortgagePayments); onDexTransfer(new byte[] { }, auctioner, mortgageAssetHash, auctionInfo.mortgagePayments); if (handlingFee > 0) { if (!NEP5transfer(ExecutionEngine.ExecutingScriptHash, getSysSetting("dividingPoolAddr"), assetHash, handlingFee)) { throw new Exception("NEP5transfer is wrong"); } } //删除拍卖信息 StorageMap auctionInfoMap = Storage.CurrentContext.CreateMap("auctionInfoMap"); auctionInfoMap.Delete(auctionid); onBet(auctionInfo, buyer, price); return(true); }