// send to external chain
        public void WithdrawTokens(Address from, Address to, string symbol, BigInteger amount)
        {
            Runtime.Expect(amount > 0, "amount must be positive and greater than zero");
            Runtime.Expect(Runtime.IsWitness(from), "invalid witness");

            Runtime.Expect(from.IsUser, "source must be user address");
            Runtime.Expect(to.IsInterop, "destination must be interop address");

            Runtime.Expect(Runtime.TokenExists(symbol), "invalid token");

            var transferTokenInfo = this.Runtime.GetToken(symbol);

            Runtime.Expect(transferTokenInfo.Flags.HasFlag(TokenFlags.Transferable), "transfer token must be transferable");
            Runtime.Expect(transferTokenInfo.Flags.HasFlag(TokenFlags.External), "transfer token must be external");
            Runtime.Expect(transferTokenInfo.Flags.HasFlag(TokenFlags.Fungible), "transfer token must be fungible");

            string platform;

            byte[] dummy;
            to.DecodeInterop(out platform, out dummy, 0);
            Runtime.Expect(platform != DomainSettings.PlatformName, "must be external platform");
            Runtime.Expect(Runtime.PlatformExists(platform), "invalid platform");
            var platformInfo = Runtime.GetPlatform(platform);

            Runtime.Expect(to != platformInfo.Address, "invalid target address");

            var feeSymbol = platformInfo.Symbol;

            Runtime.Expect(Runtime.TokenExists(feeSymbol), "invalid fee token");

            var feeTokenInfo = this.Runtime.GetToken(feeSymbol);

            Runtime.Expect(feeTokenInfo.Flags.HasFlag(TokenFlags.Fungible), "fee token must be fungible");
            Runtime.Expect(feeTokenInfo.Flags.HasFlag(TokenFlags.Transferable), "fee token must be transferable");

            var basePrice = UnitConversion.GetUnitValue(DomainSettings.FiatTokenDecimals) / InteropFeeRacio; // 50cents
            var feeAmount = Runtime.GetTokenQuote(DomainSettings.FiatTokenSymbol, feeSymbol, basePrice);

            Runtime.Expect(feeAmount > 0, "fee is too small");

            Runtime.Expect(Runtime.TransferTokens(feeSymbol, from, this.Address, feeAmount), "fee transfer failed");

            Runtime.Expect(Runtime.TransferTokens(symbol, from, platformInfo.Address, amount), "burn failed");

            var collateralAmount = Runtime.GetTokenQuote(DomainSettings.FiatTokenSymbol, DomainSettings.FuelTokenSymbol, basePrice);

            var withdraw = new InteropWithdraw()
            {
                destination      = to,
                transferAmount   = amount,
                transferSymbol   = symbol,
                feeAmount        = feeAmount,
                feeSymbol        = feeSymbol,
                hash             = Runtime.Transaction.Hash,
                broker           = Address.Null,
                collateralAmount = collateralAmount,
                timestamp        = Runtime.Time
            };

            _withdraws.Add <InteropWithdraw>(withdraw);

            Runtime.Notify(EventKind.TokenSend, from, new TokenEventData()
            {
                chainAddress = this.Address, value = amount, symbol = symbol
            });
            Runtime.Notify(EventKind.TokenEscrow, from, new TokenEventData()
            {
                chainAddress = this.Address, value = feeAmount, symbol = symbol
            });
            Runtime.Notify(EventKind.BrokerRequest, from, to);
        }
Beispiel #2
0
        // send to external chain
        public void WithdrawTokens(Address from, Address to, string symbol, BigInteger amount)
        {
            Runtime.Expect(amount > 0, "amount must be positive and greater than zero");
            Runtime.Expect(Runtime.IsWitness(from), "invalid witness");

            Runtime.Expect(from.IsUser, "source must be user address");
            Runtime.Expect(to.IsInterop, "destination must be interop address");

            Runtime.Expect(Runtime.TokenExists(symbol), "invalid token");

            var transferTokenInfo = this.Runtime.GetToken(symbol);

            Runtime.Expect(transferTokenInfo.Flags.HasFlag(TokenFlags.Transferable), "transfer token must be transferable");
            Runtime.Expect(transferTokenInfo.Flags.HasFlag(TokenFlags.External), "transfer token must be external");
            Runtime.Expect(transferTokenInfo.Flags.HasFlag(TokenFlags.Fungible), "transfer token must be fungible");

            byte platformID;

            byte[] dummy;
            to.DecodeInterop(out platformID, out dummy);
            Runtime.Expect(platformID > 0, "invalid platform ID");
            var platform = Runtime.GetPlatformByIndex(platformID);

            Runtime.Expect(platform != null, "invalid platform");

            int interopIndex = -1;

            for (int i = 0; i < platform.InteropAddresses.Length; i++)
            {
                if (platform.InteropAddresses[i].LocalAddress == to)
                {
                    interopIndex = i;
                    break;
                }
            }

            Runtime.Expect(interopIndex == -1, "invalid target address");

            var feeSymbol = platform.Symbol;

            Runtime.Expect(Runtime.TokenExists(feeSymbol), "invalid fee token");

            var feeTokenInfo = this.Runtime.GetToken(feeSymbol);

            Runtime.Expect(feeTokenInfo.Flags.HasFlag(TokenFlags.Fungible), "fee token must be fungible");
            Runtime.Expect(feeTokenInfo.Flags.HasFlag(TokenFlags.Transferable), "fee token must be transferable");

            var basePrice = Runtime.GetGovernanceValue(InteropFeeTag);
            var feeAmount = Runtime.GetTokenQuote(DomainSettings.FiatTokenSymbol, feeSymbol, basePrice);

            Runtime.Expect(feeAmount > 0, "fee is too small");

            Runtime.TransferTokens(feeSymbol, from, this.Address, feeAmount);

            // TODO support NFT
            Runtime.SwapTokens(Runtime.Chain.Name, from, platform.Name, to, symbol, amount, null, null);

            var withdraw = new InteropWithdraw()
            {
                destination    = to,
                transferAmount = amount,
                transferSymbol = symbol,
                feeAmount      = feeAmount,
                feeSymbol      = feeSymbol,
                hash           = Runtime.Transaction.Hash,
                timestamp      = Runtime.Time
            };

            _withdraws.Add <InteropWithdraw>(withdraw);
        }