コード例 #1
0
        public async Task CanGetContractBalanceFromCall()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var record = await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fx.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(400),
                FunctionName = "get_balance"
            }, ctx => ctx.Memo = "Call Contract");

            Assert.NotNull(record);
            Assert.Equal(ResponseCode.Success, record.Status);
            Assert.False(record.Hash.IsEmpty);
            Assert.NotNull(record.Concensus);
            Assert.Equal("Call Contract", record.Memo);
            Assert.InRange(record.Fee, 0UL, ulong.MaxValue);
            Assert.Empty(record.CallResult.Error);
            Assert.True(record.CallResult.Bloom.IsEmpty);
            Assert.InRange(record.CallResult.Gas, 0UL, 30_000UL);
            Assert.Empty(record.CallResult.Events);
            Assert.Empty(record.CallResult.CreatedContracts);
            Assert.Equal(fx.ContractParams.InitialBalance, record.CallResult.Result.As <long>());

            // Ensure matches API vesion.
            var apiBalance = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, apiBalance);
        }
コード例 #2
0
        public async Task CanGetContractBalanceFromLocalCall()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var result = await fx.Client.QueryContractAsync(new QueryContractParams
            {
                Contract     = fx.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(400),
                FunctionName = "get_balance",
            });

            Assert.NotNull(result);
            Assert.Empty(result.Error);
            Assert.True(result.Bloom.IsEmpty);
            Assert.InRange(result.Gas, 0UL, 30_000UL);
            Assert.Empty(result.Events);
            Assert.Equal(fx.ContractParams.InitialBalance, result.Result.As <long>());
            Assert.Empty(result.CreatedContracts);

            // Ensure matches API vesion.
            var apiBalance = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, apiBalance);

            // Ensure matches Info version
            var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, info.Balance);
        }
コード例 #3
0
        public async Task CanCallContractMethodSendingFunds()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            await using var fx2 = await TestAccount.CreateAsync(_network);

            var infoBefore = await fx2.Client.GetAccountInfoAsync(fx2.Record.Address);

            var record = await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fx.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(600),
                FunctionName = "send_to",
                FunctionArgs = new[] { fx2.Record.Address }
            });

            Assert.NotNull(record);
            Assert.Equal(ResponseCode.Success, record.Status);
            Assert.False(record.Hash.IsEmpty);
            Assert.NotNull(record.Concensus);
            Assert.Empty(record.Memo);
            Assert.InRange(record.Fee, 0UL, ulong.MaxValue);
            Assert.Empty(record.CallResult.Error);
            Assert.True(record.CallResult.Bloom.IsEmpty);
            Assert.InRange(record.CallResult.Gas, 0UL, 30_000UL);
            Assert.Empty(record.CallResult.Events);
            Assert.Empty(record.CallResult.CreatedContracts);

            var infoAfter = await fx2.Client.GetAccountInfoAsync(fx2.Record.Address);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, infoAfter.Balance - infoBefore.Balance);
        }
コード例 #4
0
        public async Task CanGetEventPayableContractBytecode()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var bytecode = await fx.Client.GetContractBytecodeAsync(fx.ContractRecord.Contract);

            Assert.False(bytecode.IsEmpty);
        }
コード例 #5
0
        public async Task CanGetBalancesForContractAsync()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var balances = await fx.Client.GetContractBalancesAsync(fx.ContractRecord.Contract);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, balances.Crypto);
            Assert.Empty(balances.Tokens);
        }
コード例 #6
0
        public async Task MissingPayerAccountDosNotThrowException()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            await using var client = new Client(ctx => { ctx.Gateway = _network.Gateway; });
            var balance = await client.GetContractBalanceAsync(fx.ContractRecord.Contract);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, balance);
        }
コード例 #7
0
        public async Task CanGetContractBalanceFromCall()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var record = await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fx.ContractRecord.Contract,
                Gas          = 300_000,
                FunctionName = "get_balance"
            });
コード例 #8
0
        public async Task TransferFundsToPayableContractWithExternalPayableRaisesContractBalanceVersion070Regression()
        {
            // Version 0.6.0 allowed for transfer of crypto to an account using the
            // crypto API calls if the contract had a default payable method.  This
            // has changed with version 0.7.0.  We are marking this as a regression for
            // now in the case that this change is reverted in a subsequent revision.
            // We will need to revisit this in the future to decide how to test this
            // behavior.
            var testFailException = (await Assert.ThrowsAsync <TransactionException>(TransferFundsToPayableContractWithExternalPayableRaisesContractBalance));

            Assert.StartsWith("Unable to execute transfers, status: InvalidAccountId", testFailException.Message);

            //[Fact(DisplayName = "Payable Contract: Transfer Funds to External Payable Default Function Raises Contract's Account Balance")]
            async Task TransferFundsToPayableContractWithExternalPayableRaisesContractBalance()
            {
                await using var fx = await PayableContract.CreateAsync(_network);

                ulong initialBalance   = (ulong)fx.ContractParams.InitialBalance;
                var   apiBalanceBefore = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

                var infoBalanceBefore = (await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract)).Balance;
                var callBalanceBefore = (ulong)(await fx.Client.CallContractWithRecordAsync(new CallContractParams
                {
                    Contract = fx.ContractRecord.Contract,
                    Gas = await _network.TinybarsFromGas(400),
                    FunctionName = "get_balance"
                })).CallResult.Result.As <long>();

                Assert.Equal(initialBalance, apiBalanceBefore);
                Assert.Equal(initialBalance, infoBalanceBefore);
                Assert.Equal(initialBalance, callBalanceBefore);

                var extraFunds = Generator.Integer(500, 1000);
                var record     = await fx.Client.TransferAsync(_network.Payer, fx.ContractRecord.Contract, extraFunds);

                Assert.Equal(ResponseCode.Success, record.Status);

                ulong finalBalance    = (ulong)fx.ContractParams.InitialBalance + (ulong)extraFunds;
                var   apiBalanceAfter = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

                var infoBalanceAfter = (await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract)).Balance;
                var callBalanceAfter = (ulong)(await fx.Client.CallContractWithRecordAsync(new CallContractParams
                {
                    Contract = fx.ContractRecord.Contract,
                    Gas = await _network.TinybarsFromGas(400),
                    FunctionName = "get_balance"
                })).CallResult.Result.As <long>();

                Assert.Equal(finalBalance, apiBalanceAfter);
                Assert.Equal(finalBalance, infoBalanceAfter);
                Assert.Equal(finalBalance, callBalanceAfter);
            }
        }
コード例 #9
0
        public async Task CanGetTinybarBalanceForContractAsync()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var balance = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

            Assert.Equal((ulong)fx.ContractParams.InitialBalance, balance);

            var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract);

            Assert.Equal(balance, info.Balance);
        }
コード例 #10
0
        public async Task CanCreateAPayableContract()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            Assert.NotNull(fx.ContractRecord);
            Assert.NotNull(fx.ContractRecord.Contract);
            Assert.Equal(ResponseCode.Success, fx.ContractRecord.Status);
            Assert.NotEmpty(fx.ContractRecord.Hash.ToArray());
            Assert.NotNull(fx.ContractRecord.Concensus);
            Assert.NotNull(fx.ContractRecord.Memo);
            Assert.InRange(fx.ContractRecord.Fee, 0UL, ulong.MaxValue);
        }
コード例 #11
0
        public async Task RetrievingAccountBalanceDoesNotCreateReceipt()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            await using var client = _network.NewClient();
            var txId    = client.CreateNewTxId();
            var balance = await client.GetContractBalanceAsync(fx.ContractRecord.Contract, ctx => ctx.Transaction = txId);

            var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
            {
                var receipt = await client.GetReceiptAsync(txId);
            });

            Assert.Equal(txId, tex.TxId);
            Assert.Equal(ResponseCode.ReceiptNotFound, tex.Status);
            Assert.StartsWith("Network failed to return a transaction receipt", tex.Message);
        }
コード例 #12
0
    public static async Task <PayableContract> CreateAsync(NetworkCredentials networkCredentials, Action <PayableContract> customize = null)
    {
        var fx = new PayableContract();

        networkCredentials.Output?.WriteLine("STARTING SETUP: Creating Payable Contract Instance");
        (fx.PublicKey, fx.PrivateKey) = Generator.KeyPair();
        fx.Network    = networkCredentials;
        fx.FileParams = new CreateFileParams
        {
            Expiration   = DateTime.UtcNow.AddSeconds(7890000),
            Endorsements = new Endorsement[] { networkCredentials.PublicKey },
            Contents     = Encoding.UTF8.GetBytes(PAYABLE_CONTRACT_BYTECODE)
        };
        fx.Client     = networkCredentials.NewClient();
        fx.FileRecord = await fx.Client.RetryKnownNetworkIssues(async client =>
        {
            return(await fx.Client.CreateFileWithRecordAsync(fx.FileParams, ctx =>
            {
                ctx.Memo = "Payable Contract Create: Uploading Contract File " + Generator.Code(10);
            }));
        });

        Assert.Equal(ResponseCode.Success, fx.FileRecord.Status);
        fx.ContractParams = new CreateContractParams
        {
            File           = fx.FileRecord.File,
            Administrator  = fx.PublicKey,
            Signatory      = fx.PrivateKey,
            Gas            = 300000,
            InitialBalance = 1_000_000,
            RenewPeriod    = TimeSpan.FromSeconds(7890000),
            Memo           = "Payable Contract " + Generator.Code(10)
        };
        customize?.Invoke(fx);
        fx.ContractRecord = await fx.Client.RetryKnownNetworkIssues(async client =>
        {
            return(await fx.Client.CreateContractWithRecordAsync(fx.ContractParams, ctx =>
            {
                ctx.Memo = "Payable Contract Create: Instantiating Payable Instance " + Generator.Code(10);
            }));
        });

        Assert.Equal(ResponseCode.Success, fx.FileRecord.Status);
        fx.Network.Output?.WriteLine("SETUP COMPLETED: Payable Contract Instance Created");
        return(fx);
    }
コード例 #13
0
        public async Task SendFundsToInvalidAccountRaisesError()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
            {
                await fx.Client.CallContractWithRecordAsync(new CallContractParams
                {
                    Contract     = fx.ContractRecord.Contract,
                    Gas          = await _network.TinybarsFromGas(3000),
                    FunctionName = "send_to",
                    FunctionArgs = new[] { new Address(0, 0, long.MaxValue) }
                });
            });

            Assert.Equal(ResponseCode.InvalidSolidityAddress, tex.Status);
            Assert.StartsWith("Contract call failed, status: InvalidSolidityAddress", tex.Message);
        }
コード例 #14
0
        public async Task SendFundsToPayableContractWithExternalPayableRaisesContractBalance()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            ulong initialBalance   = (ulong)fx.ContractParams.InitialBalance;
            var   apiBalanceBefore = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

            var infoBalanceBefore = (await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract)).Balance;
            var callBalanceBefore = (ulong)(await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract = fx.ContractRecord.Contract,
                Gas = await _network.TinybarsFromGas(400),
                FunctionName = "get_balance"
            })).CallResult.Result.As <long>();

            Assert.Equal(initialBalance, apiBalanceBefore);
            Assert.Equal(initialBalance, infoBalanceBefore);
            Assert.Equal(initialBalance, callBalanceBefore);

            var extraFunds = Generator.Integer(500, 1000);
            var record     = await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract      = fx.ContractRecord.Contract,
                Gas           = await _network.TinybarsFromGas(400),
                PayableAmount = extraFunds
            });

            Assert.Equal(ResponseCode.Success, record.Status);

            ulong finalBalance    = (ulong)fx.ContractParams.InitialBalance + (ulong)extraFunds;
            var   apiBalanceAfter = await fx.Client.GetContractBalanceAsync(fx.ContractRecord.Contract);

            var infoBalanceAfter = (await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract)).Balance;
            var callBalanceAfter = (ulong)(await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract = fx.ContractRecord.Contract,
                Gas = await _network.TinybarsFromGas(400),
                FunctionName = "get_balance"
            })).CallResult.Result.As <long>();

            Assert.Equal(finalBalance, apiBalanceAfter);
            Assert.Equal(finalBalance, infoBalanceAfter);
            Assert.Equal(finalBalance, callBalanceAfter);
        }
コード例 #15
0
        public async Task CanSendFundsToPayableContractWithExternalPayable()
        {
            await using var fx = await PayableContract.CreateAsync(_network);

            var extraFunds = Generator.Integer(500, 1000);
            var record     = await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract      = fx.ContractRecord.Contract,
                Gas           = await _network.TinybarsFromGas(400),
                PayableAmount = extraFunds
            });

            Assert.Equal(ResponseCode.Success, record.Status);

            await using var fx2 = await TestAccount.CreateAsync(_network);

            var infoBefore = await fx2.Client.GetAccountInfoAsync(fx2.Record.Address);

            record = await fx.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fx.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(600),
                FunctionName = "send_to",
                FunctionArgs = new[] { fx2.Record.Address }
            }, ctx => ctx.Memo = "Call Contract");

            Assert.NotNull(record);
            Assert.Equal(ResponseCode.Success, record.Status);
            Assert.False(record.Hash.IsEmpty);
            Assert.NotNull(record.Concensus);
            Assert.Equal("Call Contract", record.Memo);
            Assert.InRange(record.Fee, 0UL, ulong.MaxValue);
            Assert.Empty(record.CallResult.Error);
            Assert.True(record.CallResult.Bloom.IsEmpty);
            Assert.InRange(record.CallResult.Gas, 0UL, 30_000UL);
            Assert.Empty(record.CallResult.Events);
            Assert.Empty(record.CallResult.CreatedContracts);

            var infoAfter = await fx2.Client.GetAccountInfoAsync(fx2.Record.Address);

            Assert.Equal((ulong)(fx.ContractParams.InitialBalance + extraFunds), infoAfter.Balance - infoBefore.Balance);
        }
コード例 #16
0
        public async Task AttemptsToMisplaceHbarsThruPayableContractShouldFail()
        {
            // Setup the Simple Payable Contract and An account for "send to".
            await using var fxAccount1 = await TestAccount.CreateAsync(_network);

            await using var fxAccount2 = await TestAccount.CreateAsync(_network);

            await using var fxContract = await PayableContract.CreateAsync(_network);

            // Get the Info for the account state and then delete the account.
            var info1Before = await fxAccount1.Client.GetAccountInfoAsync(fxAccount1.Record.Address);

            var info2Before = await fxAccount2.Client.GetAccountInfoAsync(fxAccount2.Record.Address);

            var delete1Receipt = await fxAccount1.Client.DeleteAccountAsync(fxAccount1.Record.Address, fxAccount1.Network.Payer, fxAccount1.PrivateKey);

            Assert.Equal(ResponseCode.Success, delete1Receipt.Status);

            // Double check the balance on the contract, confirm it has hbars
            var contractBalanceBefore = await fxContract.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fxContract.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(600),
                FunctionName = "get_balance"
            });

            Assert.NotNull(contractBalanceBefore);
            Assert.InRange(fxContract.ContractParams.InitialBalance, 1, int.MaxValue);
            Assert.Equal(fxContract.ContractParams.InitialBalance, contractBalanceBefore.CallResult.Result.As <long>());

            // Ensure matches API vesion.
            var apiBalance = await fxContract.Client.GetContractBalanceAsync(fxContract.ContractRecord.Contract);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance, apiBalance);

            // Call the contract, sending to the address of the now deleted account
            // Call the contract, sending to the address of the now deleted account
            var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
            {
                await fxContract.Client.CallContractWithRecordAsync(new CallContractParams
                {
                    Contract     = fxContract.ContractRecord.Contract,
                    Gas          = await _network.TinybarsFromGas(600),
                    FunctionName = "send_to",
                    FunctionArgs = new[] { fxAccount1.Record.Address }
                });
            });

            Assert.Equal(ResponseCode.InvalidSolidityAddress, tex.Status);
            Assert.StartsWith("Contract call failed, status: InvalidSolidityAddress", tex.Message);

            // Confirm that the balance on the contract did not change.
            var contractBalanceAfter = await fxContract.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fxContract.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(400),
                FunctionName = "get_balance"
            });

            Assert.NotNull(contractBalanceAfter);
            Assert.Equal(fxContract.ContractParams.InitialBalance, contractBalanceAfter.CallResult.Result.As <long>());

            // Ensure matches API vesion.
            apiBalance = await fxContract.Client.GetContractBalanceAsync(fxContract.ContractRecord.Contract);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance, apiBalance);

            // Try to get info on the deleted account, but this will fail because the
            // account is already deleted.
            var pex = await Assert.ThrowsAsync <PrecheckException>(async() =>
            {
                // So if this throws an error, why did the above call not fail?
                await fxAccount1.Client.GetAccountInfoAsync(fxAccount1.Record.Address);
            });

            // Delete the Contract, returning any hidden hbars to account number 2
            var deleteContractRecord = await fxContract.Client.DeleteContractAsync(fxContract.ContractRecord.Contract, fxAccount2.Record.Address, fxContract.PrivateKey);

            Assert.Equal(ResponseCode.Success, deleteContractRecord.Status);

            // Check the balance of account number 2, the hBars should be there?
            var info2After = await fxAccount2.Client.GetAccountInfoAsync(fxAccount2.Record.Address);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance + info2Before.Balance, info2After.Balance); // NOPE!
        }
コード例 #17
0
        public async Task SendFundsToDeletedAccountRaisesError()
        {
            // Setup the Simple Payable Contract and An account for "send to".
            await using var fxContract = await PayableContract.CreateAsync(_network);

            await using var fxAccount = await TestAccount.CreateAsync(_network);

            // Get the Info for the account state and then delete the account.
            var infoBefore = await fxAccount.Client.GetAccountInfoAsync(fxAccount.Record.Address);

            var deleteReceipt = await fxAccount.Client.DeleteAccountAsync(fxAccount.Record.Address, fxAccount.Network.Payer, fxAccount.PrivateKey);

            Assert.Equal(ResponseCode.Success, deleteReceipt.Status);

            // Double check the balance on the contract, confirm it has hbars
            var contractBalanceBefore = await fxContract.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fxContract.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(600),
                FunctionName = "get_balance"
            });

            Assert.NotNull(contractBalanceBefore);
            Assert.InRange(fxContract.ContractParams.InitialBalance, 1, int.MaxValue);
            Assert.Equal(fxContract.ContractParams.InitialBalance, contractBalanceBefore.CallResult.Result.As <long>());

            // Ensure matches API vesion.
            var apiBalance = await fxContract.Client.GetContractBalanceAsync(fxContract.ContractRecord.Contract);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance, apiBalance);

            // Ensure matches Info version
            var info = await fxContract.Client.GetContractInfoAsync(fxContract.ContractRecord.Contract);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance, info.Balance);

            // Call the contract, sending to the address of the now deleted account
            var tex = await Assert.ThrowsAsync <TransactionException>(async() =>
            {
                await fxContract.Client.CallContractWithRecordAsync(new CallContractParams
                {
                    Contract     = fxContract.ContractRecord.Contract,
                    Gas          = await _network.TinybarsFromGas(600),
                    FunctionName = "send_to",
                    FunctionArgs = new[] { fxAccount.Record.Address }
                });
            });

            Assert.Equal(ResponseCode.InvalidSolidityAddress, tex.Status);
            Assert.StartsWith("Contract call failed, status: InvalidSolidityAddress", tex.Message);

            // Confirm that the balance on the contract remained unchanged.
            var contractBalanceAfter = await fxContract.Client.CallContractWithRecordAsync(new CallContractParams
            {
                Contract     = fxContract.ContractRecord.Contract,
                Gas          = await _network.TinybarsFromGas(400),
                FunctionName = "get_balance"
            });

            Assert.NotNull(contractBalanceAfter);
            Assert.Equal(fxContract.ContractParams.InitialBalance, contractBalanceAfter.CallResult.Result.As <long>());

            // Ensure matches API vesion.
            apiBalance = await fxContract.Client.GetContractBalanceAsync(fxContract.ContractRecord.Contract);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance, apiBalance);

            // Ensure matches Info version
            info = await fxContract.Client.GetContractInfoAsync(fxContract.ContractRecord.Contract);

            Assert.Equal((ulong)fxContract.ContractParams.InitialBalance, info.Balance);
        }