public static bool Transfer(UInt160 from, UInt160 to, BigInteger amount, object data)
        {
            Assert(from.IsValid && to.IsValid, "Invalid From or To Address");
            Assert(amount > 0, "The parameter amount MUST be greater than 0.");
            Assert(Runtime.CheckWitness(from), "No authorization.");
            var me = Runtime.ExecutingScriptHash;

            if (to == me)
            {
                Assert(CheckIsRouter(Runtime.CallingScriptHash), "Not Allowed To Transfer");
            }
            Assert(AssetStorage.Get(from) >= amount, "Insufficient balance.");
            if (from == to)
            {
                return(true);
            }

            AssetStorage.Reduce(from, amount);
            AssetStorage.Increase(to, amount);

            onTransfer(from, to, amount);

            // Validate payable
            if (ContractManagement.GetContract(to) != null)
            {
                Contract.Call(to, "onNEP17Payment", CallFlags.All, new object[] { from, amount, data });
            }
            return(true);
        }