public static object transferToCelerWallet(byte[] invoker, byte[] from, byte[] walletAddr, byte[] walletId, BigInteger value)
        {
            BasicMethods.assert(BasicMethods._isLegalAddress(invoker), "invoker or spender address is illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(from), "from address is illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(walletAddr), "to address is illegal");
            BasicMethods.assert(BasicMethods._isByte32(walletId), "walletId is not byte32");
            BasicMethods.assert(value >= 0, "amount is less than 0");

            BasicMethods.assert(Runtime.CheckWitness(invoker), "CheckWitness failed");

            BigInteger approvedBalance = allowance(from, invoker);

            BasicMethods.assert(value <= approvedBalance, "value is greater than allowance of spender allowed to spend");
            Storage.Put(Storage.CurrentContext, ApprovePrefix.Concat(from).Concat(invoker), approvedBalance - value);
            Approved(from, invoker, allowance(from, invoker));

            BigInteger fromBalance = balanceOf(from);

            BasicMethods.assert(value <= fromBalance, "value is greater than the owner's balance");
            Storage.Put(Storage.CurrentContext, BalancePrefix.Concat(from), fromBalance - value);
            Transferred(from, walletAddr, value);


            byte[] celerWalletHash      = Storage.Get(Storage.CurrentContext, CelerWalletHashKey);
            byte[] nep5Hash             = Storage.Get(Storage.CurrentContext, NEP5HashKey);
            DynamicCallContract dyncall = (DynamicCallContract)celerWalletHash.ToDelegate();

            BasicMethods.assert((bool)dyncall("depositNEP5", new object[] { invoker, walletId, nep5Hash, value }), "transfer NEP5 token to the to the celer wallet failed");

            return(true);
        }
        public static void _resolvePayment(PbEntity.ConditionalPay _pay, byte[] _payHash, BigInteger _amount)
        {
            BasicMethods.assert(_amount >= 0, "amount is less than zero");

            BigInteger now = Blockchain.GetHeight();

            BasicMethods.assert(now <= _pay.resolveDeadline, "passed pay resolve deadline in condPay msg");

            byte[] payId = _calculatePayId(_payHash, ExecutionEngine.ExecutingScriptHash);

            byte[] payRegistryHash      = getPayRegistryHash();
            DynamicCallContract dyncall = (DynamicCallContract)payRegistryHash.ToDelegate();

            BigInteger[] res             = (BigInteger[])dyncall("getPayInfo", new object[] { payId });
            BigInteger   currentAmt      = res[0];
            BigInteger   currentDeadline = res[1];

            BasicMethods.assert(
                currentDeadline == 0 || now <= currentDeadline,
                "Passed onchain resolve pay deadline"
                );
            PbEntity.TransferFunction transferFunction = _pay.transferFunc;
            PbEntity.TokenTransfer    tokenTransfer    = transferFunction.maxTransfer;
            PbEntity.AccountAmtPair   accountAmtPair   = tokenTransfer.receiver;
            if (currentDeadline > 0)
            {
                BasicMethods.assert(_amount > currentAmt, "New amount is not larger");

                if (_amount == accountAmtPair.amt)
                {
                    BasicMethods.assert((bool)dyncall("setPayInfo", new object[] { _payHash, _amount, now }), "setPayInfo error");
                    ResolvePayment(payId, _amount, now);
                }
                else
                {
                    BasicMethods.assert((bool)dyncall("setPayAmount", new object[] { _payHash, _amount }), "setPayAmount error");
                    ResolvePayment(payId, _amount, currentDeadline);
                }
            }
            else
            {
                BigInteger newDeadline = 0;
                if (_amount == accountAmtPair.amt)
                {
                    newDeadline = now;
                }
                else
                {
                    newDeadline = min(now + _pay.resolveTimeout, _pay.resolveDeadline);
                    BasicMethods.assert(newDeadline > 0, "new resolve deadline is not greater than 0");
                }

                BasicMethods.assert((bool)dyncall("setPayInfo", new object[] { _payHash, _amount, newDeadline }), "setPayInfo error");
                ResolvePayment(payId, _amount, currentDeadline);
            }
        }
        //Transfer NEP5 for a specified addresses
        private static bool _transfer(byte[] from, byte[] to, BigInteger value)
        {
            Storage.Put(Storage.CurrentContext, BalancePrefix.Concat(from), balanceOf(from) - value);

            byte[] nep5Hash             = Storage.Get(Storage.CurrentContext, NEP5HashKey);
            DynamicCallContract dyncall = (DynamicCallContract)nep5Hash.ToDelegate();

            BasicMethods.assert((bool)dyncall("transfer", new object[] { ExecutionEngine.ExecutingScriptHash, to, value }), "transfer NEP5 token to the to as the withdrawer'd like to failed");

            Transferred(from, to, value);
            return(true);
        }
        private static BigInteger _calculateBooleanOrPayment(PbEntity.ConditionalPay _pay, byte[][] _preimages)
        {
            int  j = 0;
            bool hasContractCond     = false;
            bool hasTrueContractCond = false;

            PbEntity.ConditionType ConditionType = PbEntity.getConditionType();
            PbEntity.Condition[]   conditions    = _pay.conditions;
            for (var i = 0; i < conditions.Length; i++)
            {
                PbEntity.Condition cond = _pay.conditions[i];
                if (cond.conditionType == ConditionType.HASH_LOCK)
                {
                    BasicMethods.assert(SmartContract.Sha256(_preimages[j]) == cond.hashLock, "wrong preimage");
                    j++;
                }
                else if (
                    cond.conditionType == ConditionType.DEPLOYED_CONTRACT ||
                    cond.conditionType == ConditionType.VIRTUAL_CONTRACT
                    )
                {
                    byte[] booleanCondHash      = _getCondAddress(cond);
                    DynamicCallContract dyncall = (DynamicCallContract)booleanCondHash.ToDelegate();
                    BasicMethods.assert((bool)dyncall("isFinalized", new object[] { cond.argsQueryFinalization }), "Condition is not finalized");
                    hasContractCond = true;

                    bool outcome = (bool)dyncall("getOutcome", new object[] { cond.argsQueryOutcome });
                    if (outcome)
                    {
                        hasTrueContractCond = true;
                    }
                }
                else
                {
                    BasicMethods.assert(false, "condition type error");
                }
            }
            if (!hasContractCond || hasTrueContractCond)
            {
                PbEntity.TransferFunction transferFunction = _pay.transferFunc;
                PbEntity.TokenTransfer    tokenTransfer    = transferFunction.maxTransfer;
                PbEntity.AccountAmtPair   accountAmtPair   = tokenTransfer.receiver;
                return(accountAmtPair.amt);
            }
            else
            {
                return(0);
            }
        }
    public static LedgerStruct.Channel _importChannelMigrationArgs(LedgerStruct.Channel _c, byte[] _fromLedgerAddr, byte[] _channelId)
    {
        BasicMethods.assert(BasicMethods._isLegalAddress(_fromLedgerAddr), "invalid contract address");
        BasicMethods.assert(BasicMethods._isByte32(_channelId), "invalid _channelId");

        DynamicCallContract dyncall = (DynamicCallContract)_fromLedgerAddr.ToDelegate();

        LedgerStruct.ChannelMigrationArgs args = (LedgerStruct.ChannelMigrationArgs)dyncall("getChannelMigrationArgs", new object[] { _channelId });
        _c.disputeTimeout = args.disputeTimeout;
        PbEntity.TokenInfo token = new PbEntity.TokenInfo();
        token.tokenType = args.tokenType;
        token.address   = args.tokenAddress;
        _c.token        = token;
        _c.cooperativeWithdrawSeqNum = args.cooperativeWithdrawSeqNum;
        return(_c);
    }
        public static object withdraw(byte[] withdrawer, BigInteger value)
        {
            BasicMethods.assert(BasicMethods._isLegalAddress(withdrawer), "withdrawer address is illegal");
            BasicMethods.assert(value >= 0, "amount is less than zero");

            BasicMethods.assert(Runtime.CheckWitness(withdrawer), "Checkwitness failed");

            byte[] nep5Hash             = Storage.Get(Storage.CurrentContext, NEP5HashKey);
            DynamicCallContract dyncall = (DynamicCallContract)nep5Hash.ToDelegate();

            BasicMethods.assert((BigInteger)dyncall("balanceOf", new object[] { ExecutionEngine.ExecutingScriptHash }) >= value, "the contract accout nep5 balance not enough");
            BasicMethods.assert(balanceOf(withdrawer) >= value, "withdrawer does not have enough balance");

            BasicMethods.assert(_transfer(withdrawer, withdrawer, value), "withdraw nep5 token failed");
            return(true);
        }
 private static byte[] _getCondAddress(PbEntity.Condition _cond)
 {
     PbEntity.ConditionType ConditionType = PbEntity.getConditionType();
     if (_cond.conditionType == ConditionType.DEPLOYED_CONTRACT)
     {
         return(_cond.deployedContractAddress);
     }
     else if (_cond.conditionType == ConditionType.VIRTUAL_CONTRACT)
     {
         byte[] virtResolverHash     = Storage.Get(Storage.CurrentContext, VirtResolverHashKey);
         DynamicCallContract dyncall = (DynamicCallContract)virtResolverHash.ToDelegate();
         return((byte[])dyncall("resolve", new object[] { _cond.virtualContractAddress }));
     }
     BasicMethods.assert(false, "conditiontype error");
     return(new byte[] { 0x00 });
 }
        public static object deposit(byte[] depositer, byte[] receiver, BigInteger amount)
        {
            BasicMethods.assert(BasicMethods._isLegalAddress(depositer), "depositer address is illegal");
            BasicMethods.assert(BasicMethods._isLegalAddress(receiver), "receiver address is illegal");
            BasicMethods.assert(amount >= 0, "amount is less than 0");

            BasicMethods.assert(Runtime.CheckWitness(depositer), "Checkwitness failed");

            byte[] nep5Hash             = Storage.Get(Storage.CurrentContext, NEP5HashKey);
            DynamicCallContract dyncall = (DynamicCallContract)nep5Hash.ToDelegate();

            BasicMethods.assert((bool)dyncall("transfer", new object[] { depositer, ExecutionEngine.ExecutingScriptHash, amount }), "transfer NEP5 token to the contract failed");
            Storage.Put(Storage.CurrentContext, BalancePrefix.Concat(receiver), balanceOf(receiver) + amount);

            DepositEvent(receiver, amount);
            return(true);
        }
    public static LedgerStruct.Channel _importPeersMigrationInfo(LedgerStruct.Channel _c, byte[] _fromLedgerAddr, byte[] _channelId)
    {
        BasicMethods.assert(BasicMethods._isLegalAddress(_fromLedgerAddr), "invalid contract address");
        BasicMethods.assert(BasicMethods._isByte32(_channelId), "invalid _channelId");
        object[]            input   = new object[] { _channelId };
        DynamicCallContract dyncall = (DynamicCallContract)_fromLedgerAddr.ToDelegate();

        LedgerStruct.PeersMigrationInfo args = (LedgerStruct.PeersMigrationInfo)dyncall("getPeersMigrationInfo", input);
        byte[][]     peerAddr      = args.peerAddr;
        BigInteger[] deposit       = args.deposit;
        BigInteger[] withdrawal    = args.withdrawal;
        BigInteger[] seqNum        = args.seqNum;
        BigInteger[] transferOut   = args.transferOut;
        BigInteger[] pendingPayout = args.pendingPayout;
        LedgerStruct.PeerProfile[] peerProfiles = _c.peerProfiles;
        for (int i = 0; i < 2; i++)
        {
            LedgerStruct.PeerProfile originalPeerProfile = peerProfiles[i];
            LedgerStruct.PeerState   originaPeerState    = originalPeerProfile.state;
            LedgerStruct.PeerState   peerState           = new LedgerStruct.PeerState
            {
                seqNum                 = seqNum[i],
                transferOut            = transferOut[i],
                nextPayIdListHash      = originaPeerState.nextPayIdListHash,
                lastPayResolveDeadline = originaPeerState.lastPayResolveDeadline,
                pendingPayOut          = pendingPayout[i]
            };
            LedgerStruct.PeerProfile peerProfile = new LedgerStruct.PeerProfile()
            {
                peerAddr   = peerAddr[i],
                deposit    = deposit[i],
                withdrawal = withdrawal[i],
                state      = peerState
            };
            peerProfiles[i] = peerProfile;
        }
        return(_c);
    }
        private static BigInteger _calculateNumericLogicPayment(PbEntity.ConditionalPay _pay, byte[][] _preimages, byte _funcType)
        {
            int        j              = 0;
            BigInteger amount         = 0;
            bool       hasContracCond = false;

            PbEntity.ConditionType        ConditionType        = PbEntity.getConditionType();
            PbEntity.TransferFunctionType TransferFunctionType = PbEntity.getTransferFunctionType();
            PbEntity.Condition[]          conditions           = _pay.conditions;
            for (var i = 0; i < conditions.Length; i++)
            {
                PbEntity.Condition cond = _pay.conditions[i];
                if (cond.conditionType == ConditionType.HASH_LOCK)
                {
                    BasicMethods.assert(SmartContract.Sha256(_preimages[j]) == cond.hashLock, "wrong preimage");
                    j++;
                }
                else if (
                    cond.conditionType == ConditionType.DEPLOYED_CONTRACT ||
                    cond.conditionType == ConditionType.VIRTUAL_CONTRACT
                    )
                {
                    byte[] numericCondHash      = _getCondAddress(cond);
                    DynamicCallContract dyncall = (DynamicCallContract)numericCondHash.ToDelegate();
                    BasicMethods.assert((bool)dyncall("isFinalized", new object[] { cond.argsQueryFinalization }), "Condition is not finalized");

                    BigInteger outcome = (BigInteger)dyncall("getOutcome", new object[] { cond.argsQueryOutcome });

                    if (_funcType == TransferFunctionType.NUMERIC_ADD)
                    {
                        amount = amount + outcome;
                    }
                    else if (_funcType == TransferFunctionType.NUMERIC_MAX)
                    {
                        amount = max(amount, outcome);
                    }
                    else if (_funcType == TransferFunctionType.NUMERIC_MIN)
                    {
                        if (hasContracCond)
                        {
                            amount = min(amount, outcome);
                        }
                        else
                        {
                            amount = outcome;
                        }
                    }
                    else
                    {
                        BasicMethods.assert(false, "error");
                    }
                    hasContracCond = true;
                }
                else
                {
                    BasicMethods.assert(false, "condition type error");
                }
            }
            PbEntity.TransferFunction transferFunction = _pay.transferFunc;
            PbEntity.TokenTransfer    tokenTransfer    = transferFunction.maxTransfer;
            PbEntity.AccountAmtPair   accountAmtPair   = tokenTransfer.receiver;
            if (hasContracCond)
            {
                BasicMethods.assert(amount <= accountAmtPair.amt, "exceed max transfer amount");
                return(amount);
            }
            else
            {
                return(accountAmtPair.amt);
            }
        }