public NativeExecutionContext(SmartContract contract) { this.Contract = contract; }
public void ApplyInflation(Address from) { Runtime.Expect(_inflationReady, "inflation not ready"); Runtime.Expect(Runtime.IsRootChain(), "only on root chain"); var currentSupply = Runtime.GetTokenSupply(DomainSettings.StakingTokenSymbol); var minExpectedSupply = UnitConversion.ToBigInteger(100000000, DomainSettings.StakingTokenDecimals); if (currentSupply < minExpectedSupply) { currentSupply = minExpectedSupply; } // NOTE this gives an approximate inflation of 3% per year (0.75% per season) var inflationAmount = currentSupply / 133; BigInteger mintedAmount = 0; Runtime.Expect(inflationAmount > 0, "invalid inflation amount"); var masterOrg = Runtime.GetOrganization(DomainSettings.MastersOrganizationName); var masters = masterOrg.GetMembers(); var rewardList = new List <Address>(); foreach (var addr in masters) { var masterDate = Runtime.CallNativeContext(NativeContractKind.Stake, nameof(StakeContract.GetMasterDate), addr).AsTimestamp(); if (masterDate <= _lastInflationDate) { rewardList.Add(addr); } } if (rewardList.Count > 0) { var rewardAmount = inflationAmount / 10; var rewardStake = rewardAmount / rewardList.Count; rewardAmount = rewardList.Count * rewardStake; // eliminate leftovers var rewardFuel = _rewardAccum / rewardList.Count; BigInteger stakeAmount; if (Runtime.ProtocolVersion > 5) { stakeAmount = UnitConversion.ToBigInteger(2, DomainSettings.StakingTokenDecimals); } else { stakeAmount = UnitConversion.ToBigInteger(1, DomainSettings.StakingTokenDecimals); } Runtime.MintTokens(DomainSettings.StakingTokenSymbol, this.Address, this.Address, rewardAmount); var crownAddress = TokenUtils.GetContractAddress(DomainSettings.RewardTokenSymbol); Runtime.MintTokens(DomainSettings.StakingTokenSymbol, this.Address, crownAddress, stakeAmount); Runtime.CallNativeContext(NativeContractKind.Stake, nameof(StakeContract.Stake), crownAddress, stakeAmount); foreach (var addr in rewardList) { var reward = new StakeReward(addr, Runtime.Time); var rom = Serialization.Serialize(reward); var tokenID = Runtime.MintToken(DomainSettings.RewardTokenSymbol, this.Address, this.Address, rom, new byte[0], 0); Runtime.InfuseToken(DomainSettings.RewardTokenSymbol, this.Address, tokenID, DomainSettings.FuelTokenSymbol, rewardFuel); Runtime.InfuseToken(DomainSettings.RewardTokenSymbol, this.Address, tokenID, DomainSettings.StakingTokenSymbol, rewardStake); Runtime.TransferToken(DomainSettings.RewardTokenSymbol, this.Address, addr, tokenID); } _rewardAccum -= rewardList.Count * rewardFuel; Runtime.Expect(_rewardAccum >= 0, "invalid reward leftover"); inflationAmount -= rewardAmount; inflationAmount -= stakeAmount; } var refillAmount = inflationAmount / 50; var cosmicAddress = SmartContract.GetAddressForNative(NativeContractKind.Swap); Runtime.MintTokens(DomainSettings.StakingTokenSymbol, this.Address, cosmicAddress, refillAmount); inflationAmount -= refillAmount; var phantomOrg = Runtime.GetOrganization(DomainSettings.PhantomForceOrganizationName); if (phantomOrg != null) { var phantomFunding = inflationAmount / 3; Runtime.MintTokens(DomainSettings.StakingTokenSymbol, this.Address, phantomOrg.Address, phantomFunding); inflationAmount -= phantomFunding; if (phantomOrg.Size == 1) { Runtime.CallNativeContext(NativeContractKind.Stake, nameof(StakeContract.Stake), phantomOrg.Address, phantomFunding); } } var bpOrg = Runtime.GetOrganization(DomainSettings.ValidatorsOrganizationName); if (bpOrg != null) { Runtime.MintTokens(DomainSettings.StakingTokenSymbol, this.Address, bpOrg.Address, inflationAmount); if (bpOrg.Size == 1) { Runtime.CallNativeContext(NativeContractKind.Stake, nameof(StakeContract.Stake), bpOrg.Address, inflationAmount); } } Runtime.Notify(EventKind.Inflation, from, new TokenEventData(DomainSettings.StakingTokenSymbol, mintedAmount, Runtime.Chain.Name)); _lastInflationDate = Runtime.Time; _inflationReady = false; }
public void EditAuction(Address from, string baseSymbol, string quoteSymbol, BigInteger tokenID, BigInteger price, BigInteger endPrice, Timestamp startDate, Timestamp endDate, BigInteger extensionPeriod) { Runtime.Expect(Runtime.IsWitness(from), "invalid witness"); Runtime.Expect(Runtime.TokenExists(quoteSymbol), "invalid quote token"); var quoteToken = Runtime.GetToken(quoteSymbol); Runtime.Expect(quoteToken.Flags.HasFlag(TokenFlags.Fungible), "quote token must be fungible"); var nft = Runtime.ReadToken(baseSymbol, tokenID); Runtime.Expect(nft.CurrentChain == Runtime.Chain.Name, "token not currently in this chain"); var marketAddress = SmartContract.GetAddressForNative(NativeContractKind.Market); Runtime.Expect(nft.CurrentOwner == marketAddress, "invalid owner"); var auctionID = baseSymbol + "." + tokenID; Runtime.Expect(_auctionMap.ContainsKey <string>(auctionID), "invalid auction"); var auction = _auctionMap.Get <string, MarketAuction>(auctionID); Runtime.Expect(auction.Creator == from, "invalid auction creator"); if (auction.Type != TypeAuction.Fixed) // prevent edit already started auctions { Runtime.Expect(auction.StartDate > Runtime.Time, "EditAuction can only be used before listing start"); } if (price == 0) { price = auction.Price; } if (endPrice == 0) { endPrice = auction.EndPrice; } if (startDate == 0 || startDate == null) { startDate = auction.StartDate; } if (endDate == 0 || endDate == null) { endDate = auction.EndDate; } Runtime.Expect(endDate > startDate, "invalid end date"); if (extensionPeriod == 0 || auction.Type == TypeAuction.Fixed) { extensionPeriod = auction.ExtensionPeriod; } if (auction.Type == TypeAuction.Classic || auction.Type == TypeAuction.Reserve) { Runtime.Expect(extensionPeriod <= oneHour, "extensionPeriod must be <= 1 hour"); } var auctionNew = new MarketAuction(from, startDate, endDate, baseSymbol, quoteSymbol, tokenID, price, endPrice, extensionPeriod, auction.Type, auction.ListingFee, auction.ListingFeeAddress, auction.BuyingFee, auction.BuyingFeeAddress, auction.CurrentBidWinner); _auctionMap.Set(auctionID, auctionNew); Runtime.Notify(EventKind.OrderCancelled, auctionNew.Creator, new MarketEventData() { ID = auction.TokenID, BaseSymbol = auction.BaseSymbol, QuoteSymbol = auction.QuoteSymbol, Price = auction.Price, EndPrice = auction.EndPrice, Type = auction.Type }); Runtime.Notify(EventKind.OrderCreated, auctionNew.Creator, new MarketEventData() { ID = auctionNew.TokenID, BaseSymbol = auctionNew.BaseSymbol, QuoteSymbol = auctionNew.QuoteSymbol, Price = auctionNew.Price, EndPrice = auctionNew.EndPrice, Type = auctionNew.Type }); }
private void SpendGasV2(Address from) { var availableAmount = _allowanceMap.Get <Address, BigInteger>(from); var spentGas = Runtime.UsedGas; var requiredAmount = spentGas * Runtime.GasPrice; Runtime.Expect(requiredAmount > 0, $"{Runtime.GasPrice} {spentGas} gas fee must exist"); Runtime.Expect(availableAmount >= requiredAmount, "gas allowance is not enough"); var leftoverAmount = availableAmount - requiredAmount; var targetAddress = _allowanceTargets.Get <Address, Address>(from); BigInteger targetGas; Runtime.Notify(EventKind.GasPayment, from, new GasEventData(targetAddress, Runtime.GasPrice, spentGas)); // return leftover escrowed gas to transaction creator if (leftoverAmount > 0) { Runtime.TransferTokens(DomainSettings.FuelTokenSymbol, this.Address, from, leftoverAmount); } Runtime.Expect(spentGas > 1, "gas spent too low"); var burnGas = spentGas / 2; if (burnGas > 0) { BigInteger burnAmount; if (Runtime.ProtocolVersion >= 4) { burnAmount = burnGas * Runtime.GasPrice; } else { burnAmount = burnGas; } Runtime.BurnTokens(DomainSettings.FuelTokenSymbol, this.Address, burnAmount); spentGas -= burnGas; } targetGas = spentGas / 2; // 50% for dapps (or reward accum if dapp not specified) if (targetGas > 0) { var targetPayment = targetGas * Runtime.GasPrice; if (targetAddress == Runtime.Chain.Address) { _rewardAccum += targetPayment; Runtime.Notify(EventKind.CrownRewards, from, new TokenEventData(DomainSettings.FuelTokenSymbol, targetPayment, Runtime.Chain.Name)); } else { Runtime.TransferTokens(DomainSettings.FuelTokenSymbol, this.Address, targetAddress, targetPayment); } spentGas -= targetGas; } if (spentGas > 0) { var validatorPayment = spentGas * Runtime.GasPrice; var validatorAddress = SmartContract.GetAddressForNative(NativeContractKind.Block); Runtime.TransferTokens(DomainSettings.FuelTokenSymbol, this.Address, validatorAddress, validatorPayment); spentGas = 0; } _allowanceMap.Remove(from); _allowanceTargets.Remove(from); CheckInflation(); }