public async Task QueryContractWithInsufficientFundsThrowsErrorByDefault() { await using var fx = await StatefulContract.CreateAsync(_network); var qex = await Assert.ThrowsAsync <ContractException>(async() => { await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = 1, ReturnValueCharge = 4000, FunctionName = "get_message" }); }); Assert.NotNull(qex); Assert.Equal(ResponseCode.InsufficientGas, qex.Status); Assert.NotNull(qex.TxId); Assert.Equal(0ul, qex.RequiredFee); Assert.NotNull(qex.CallResult); Assert.Equal("INSUFFICIENT_GAS", qex.CallResult.Error); Assert.False(qex.CallResult.Bloom.IsEmpty); Assert.InRange(qex.CallResult.Gas, 0UL, ulong.MaxValue); Assert.Empty(qex.CallResult.Events); Assert.Equal(0, qex.CallResult.Result.Size); Assert.Empty(qex.CallResult.CreatedContracts); }
public async Task QueryContractWithInsufficientFundsThrowsErrorByDefault() { await using var fx = await StatefulContract.CreateAsync(_network); var qex = await Assert.ThrowsAsync <ContractException>(async() => { await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = 1, ReturnValueCharge = await _network.TinybarsFromGas(400), FunctionName = "get_message" }); }); Assert.NotNull(qex); Assert.Equal(ResponseCode.InsufficientGas, qex.Status); Assert.NotNull(qex.TxId); Assert.Equal(0ul, qex.RequiredFee); Assert.NotNull(qex.CallResult); Assert.Equal("Not enough gas for 'PUSH1' cause spending: invokeGas[1], gas[3], usedGas[0];", qex.CallResult.Error); Assert.True(qex.CallResult.Bloom.IsEmpty); Assert.InRange(qex.CallResult.Gas, 0UL, ulong.MaxValue); Assert.Empty(qex.CallResult.Events); Assert.Equal(0, qex.CallResult.Result.Size); Assert.Empty(qex.CallResult.CreatedContracts); }
public async Task CanRetrieveRecordsFromContractMethodCalls() { await using var fxContract = await StatefulContract.CreateAsync(_network); var transactionCount = Generator.Integer(2, 3); for (int i = 0; i < transactionCount; i++) { await fxContract.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fxContract.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message" }); } var records = await fxContract.Client.GetContractRecordsAsync(fxContract.ContractRecord.Contract); Assert.NotNull(records); Assert.Equal(transactionCount + 1, records.Length); foreach (var record in records.Skip(1)) { Assert.Equal(ResponseCode.Success, record.Status); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.Empty(record.Memo); Assert.NotNull(record.Concensus); Assert.False(record.Hash.IsEmpty); } }
public async Task CanUpdateContractBytecode() { await using var fx = await GreetingContract.CreateAsync(_network); await using var fx2 = await StatefulContract.SetupAsync(_network); var record = await fx.Client.UpdateContractWithRecordAsync(new UpdateContractParams { Contract = fx.ContractRecord.Contract, File = fx2.FileRecord.File }); var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract); Assert.NotNull(info); Assert.Equal(fx.ContractRecord.Contract, info.Contract); Assert.Equal(fx.ContractRecord.Contract, info.Address); Assert.Equal(fx.ContractParams.Administrator, info.Administrator); Assert.Equal(fx.ContractParams.RenewPeriod, info.RenewPeriod); Assert.Equal(fx.Memo, info.Memo); // Call a method that was not part of the original contract to check update. // Note, this is a bug with the network, the call returned success but we are still // able to call the old contract method which should no longer exist. var callRecord = await fx.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = 30_000, FunctionName = "greet", });
public async Task CanGetStatefulContractBytecode() { await using var fx = await StatefulContract.CreateAsync(_network); var bytecode = await fx.Client.GetContractBytecodeAsync(fx.ContractRecord.Contract); Assert.False(bytecode.IsEmpty); }
public async Task CanRetrieveRecordFromContractCreateRemoved() { await using var fxContract = await StatefulContract.CreateAsync(_network); var records = await fxContract.Client.GetContractRecordsAsync(fxContract.ContractRecord.Contract); Assert.NotNull(records); Assert.Empty(records); }
public async Task CanGetStatefulContractAddressFromSmartContractAddress() { await using var fx = await StatefulContract.CreateAsync(_network); var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract); var address = await fx.Client.GetAddressFromSmartContractId(info.SmartContractId); Assert.Equal(fx.ContractRecord.Contract, address); }
public async Task CanCreateAContractWithParameters() { await using var fx = await StatefulContract.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); }
public async Task CreateWithoutRequiredContractParamsThrowsError() { await using var fx = await StatefulContract.SetupAsync(_network); fx.ContractParams.Arguments = null; var ex = await Assert.ThrowsAsync <TransactionException>(async() => { await fx.Client.CreateContractAsync(fx.ContractParams); }); Assert.StartsWith("Unable to create contract, status: ContractRevertExecuted", ex.Message); Assert.Equal(ResponseCode.ContractRevertExecuted, ex.Status); }
public async Task ContractWithNoRecords() { await using var fx = await StatefulContract.CreateAsync(_network); var transactionCount = Generator.Integer(2, 5); for (int i = 0; i < transactionCount; i++) { await fx.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = 30_000, FunctionName = "get_message" });
public async Task CanGetCreateContractRecipt() { await using var fx = await StatefulContract.CreateAsync(_network); var receipt = await fx.Client.GetReceiptAsync(fx.ContractRecord.Id); var createRecipt = Assert.IsType <CreateContractReceipt>(receipt); Assert.Equal(fx.ContractRecord.Id, createRecipt.Id); Assert.Equal(fx.ContractRecord.Status, createRecipt.Status); Assert.Equal(fx.ContractRecord.CurrentExchangeRate, createRecipt.CurrentExchangeRate); Assert.Equal(fx.ContractRecord.NextExchangeRate, createRecipt.NextExchangeRate); Assert.Equal(fx.ContractRecord.Contract, createRecipt.Contract); }
public async Task CanCreateAContractWithStateAlternateSignatoryAsync() { await using var fx = await StatefulContract.CreateAsync(_network); var receipt = await fx.Client.CallContractAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message", Signatory = _network.PrivateKey }, ctx => ctx.Signatory = null); Assert.NotNull(receipt); Assert.Equal(ResponseCode.Success, receipt.Status); }
public async Task CanGetStatefulContractInfo() { await using var fx = await StatefulContract.CreateAsync(_network); var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract); Assert.NotNull(info); Assert.Equal(fx.ContractRecord.Contract, info.Contract); Assert.Equal(fx.ContractRecord.Contract, info.Address); // Assume for now they are equal Assert.NotNull(info.SmartContractId); Assert.Equal(fx.ContractParams.Administrator, info.Administrator); Assert.InRange(info.Expiration, DateTime.UtcNow, DateTime.MaxValue); Assert.Equal(fx.ContractParams.RenewPeriod, info.RenewPeriod); Assert.InRange(info.Size, 0, fx.FileParams.Contents.Length); Assert.StartsWith("Stateful Contract Create: Instantiating Stateful Instance", info.Memo); }
public async Task CanRetrieveRecordFromContractCreate() { await using var fxContract = await StatefulContract.CreateAsync(_network); var records = await fxContract.Client.GetContractRecordsAsync(fxContract.ContractRecord.Contract); Assert.NotNull(records); Assert.Single(records); var record = records[0]; Assert.Equal(ResponseCode.Success, record.Status); Assert.Equal(fxContract.ContractRecord.Id, record.Id); Assert.InRange(record.Fee, 0UL, ulong.MaxValue); Assert.StartsWith("Stateful Contract Create: Instantiating Stateful Instance", record.Memo); Assert.NotNull(record.Concensus); Assert.False(record.Hash.IsEmpty); }
public async Task CanCreateAContractAndSetStateAsync() { await using var fx = await StatefulContract.CreateAsync(_network); var newMessage = Generator.Code(50); var setRecord = await fx.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(1200), FunctionName = "set_message", FunctionArgs = new object[] { newMessage } }, ctx => ctx.Memo = "Call Contract"); Assert.NotNull(setRecord); Assert.Equal(ResponseCode.Success, setRecord.Status); Assert.False(setRecord.Hash.IsEmpty); Assert.NotNull(setRecord.Concensus); Assert.Equal("Call Contract", setRecord.Memo); Assert.InRange(setRecord.Fee, 0UL, ulong.MaxValue); Assert.Empty(setRecord.CallResult.Error); Assert.True(setRecord.CallResult.Bloom.IsEmpty); Assert.InRange(setRecord.CallResult.Gas, 0UL, 50_000UL); Assert.Empty(setRecord.CallResult.Events); Assert.Empty(setRecord.CallResult.CreatedContracts); var getRecord = await fx.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message" }); Assert.NotNull(getRecord); Assert.Equal(ResponseCode.Success, getRecord.Status); Assert.False(getRecord.Hash.IsEmpty); Assert.NotNull(getRecord.Concensus); Assert.Empty(getRecord.Memo); Assert.InRange(getRecord.Fee, 0UL, ulong.MaxValue); Assert.Empty(getRecord.CallResult.Error); Assert.True(getRecord.CallResult.Bloom.IsEmpty); Assert.InRange(getRecord.CallResult.Gas, 0UL, 30_000UL); Assert.Empty(getRecord.CallResult.Events); Assert.Empty(getRecord.CallResult.CreatedContracts); Assert.Equal(newMessage, getRecord.CallResult.Result.As <string>()); Assert.InRange(getRecord.CallResult.Gas, 0UL, 30_000UL); }
public static async Task <StatefulContract> CreateAsync(NetworkCredentials networkCredentials, Action <StatefulContract> customize = null) { var fx = new StatefulContract(); networkCredentials.Output?.WriteLine("STARTING SETUP: Creating Stateful 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(STATEFUL_CONTRACT_BYTECODE) }; fx.Client = networkCredentials.NewClient(); fx.FileRecord = await fx.Client.RetryKnownNetworkIssues(async client => { return(await fx.Client.CreateFileWithRecordAsync(fx.FileParams, ctx => { ctx.Memo = "Stateful 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, Memo = "Stateful Contract " + Generator.Code(10), Gas = 150000, RenewPeriod = TimeSpan.FromSeconds(7890000), Arguments = new object[] { "Hello from .NET. " + DateTime.UtcNow.ToLongDateString() } }; customize?.Invoke(fx); fx.ContractRecord = await fx.Client.RetryKnownNetworkIssues(async client => { return(await fx.Client.CreateContractWithRecordAsync(fx.ContractParams, ctx => { ctx.Memo = "Stateful Contract Create: Instantiating Stateful Instance " + Generator.Code(10); })); }); fx.Network.Output?.WriteLine("SETUP COMPLETED: Stateful Contract Instance Created"); return(fx); }
public async Task CanCreateAContractWithStateAsync() { await using var fx = await StatefulContract.CreateAsync(_network); var result = await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), ReturnValueCharge = await _network.TinybarsFromGas(400), FunctionName = "get_message" }); Assert.NotNull(result); Assert.Empty(result.Error); Assert.True(result.Bloom.IsEmpty); Assert.InRange(result.Gas, 0UL, ulong.MaxValue); Assert.Empty(result.Events); Assert.Equal(fx.ContractParams.Arguments[0] as string, result.Result.As <string>()); }
public async Task CanCreateAContractAndSetStateAsync() { await using var fx = await StatefulContract.CreateAsync(_network); var newMessage = Generator.Code(50); var qex = await Assert.ThrowsAsync <ContractException>(async() => { await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = 30000, FunctionName = "set_message", FunctionArgs = new object[] { newMessage }, ReturnValueCharge = 900 }); }); Assert.Equal(ResponseCode.LocalCallModificationException, qex.Status); Assert.StartsWith("Contract Query Failed with Code: LocalCallModificationException", qex.Message); }
public async Task CanCreateAContractAndSetStateAsync() { await using var fx = await StatefulContract.CreateAsync(_network); var newMessage = Generator.Code(50); var pex = await Assert.ThrowsAsync <PrecheckException>(async() => { await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "set_message", FunctionArgs = new object[] { newMessage }, ReturnValueCharge = 900 }); }); Assert.Equal(ResponseCode.LocalCallModificationException, pex.Status); Assert.StartsWith("Transaction Failed Pre-Check: LocalCallModificationException", pex.Message); }
public async Task CanRetrieveRecordsFromContractMethodCalls() { await using var fxContract = await StatefulContract.CreateAsync(_network); var transactionCount = Generator.Integer(2, 3); for (int i = 0; i < transactionCount; i++) { await fxContract.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fxContract.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message" }); } var records = await fxContract.Client.GetContractRecordsAsync(fxContract.ContractRecord.Contract); Assert.NotNull(records); Assert.Empty(records); }
public async Task CanCreateAContractWithParameters() { await using var fx = await StatefulContract.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); Assert.Empty(fx.ContractRecord.CallResult.Error); Assert.True(fx.ContractRecord.CallResult.Bloom.IsEmpty); Assert.InRange(fx.ContractRecord.CallResult.Gas, 0UL, (ulong)fx.ContractParams.Gas); Assert.Empty(fx.ContractRecord.CallResult.Events); Assert.Empty(fx.ContractRecord.CallResult.CreatedContracts); Assert.Equal(0, fx.ContractRecord.CallResult.Result.Size); Assert.True(fx.ContractRecord.CallResult.Result.Data.IsEmpty); }
public async Task ErrorQueryContractWithoutFlagReturnsWithoutError() { await using var fx = await StatefulContract.CreateAsync(_network); var result = await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = 1, ReturnValueCharge = 4000, FunctionName = "get_message", ThrowOnFail = false }); Assert.NotNull(result); Assert.Equal("INSUFFICIENT_GAS", result.Error); Assert.False(result.Bloom.IsEmpty); Assert.InRange(result.Gas, 0UL, ulong.MaxValue); Assert.Empty(result.Events); Assert.Equal(0, result.Result.Size); Assert.Empty(result.CreatedContracts); }
public async Task ErrorQueryContractWithoutFlagReturnsWithoutError() { await using var fx = await StatefulContract.CreateAsync(_network); var result = await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = 1, ReturnValueCharge = await _network.TinybarsFromGas(400), FunctionName = "get_message", ThrowOnFail = false }); Assert.NotNull(result); Assert.Equal("Not enough gas for 'PUSH1' cause spending: invokeGas[1], gas[3], usedGas[0];", result.Error); Assert.True(result.Bloom.IsEmpty); Assert.InRange(result.Gas, 0UL, ulong.MaxValue); Assert.Empty(result.Events); Assert.Equal(0, result.Result.Size); Assert.Empty(result.CreatedContracts); }
public async Task CanNotScheduleCallContract() { await using var fxPayer = await TestAccount.CreateAsync(_network, fx => fx.CreateParams.InitialBalance = 20_00_000_000); await using var fxContract = await StatefulContract.CreateAsync(_network); var tex = await Assert.ThrowsAsync <TransactionException>(async() => { await fxContract.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fxContract.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message", Signatory = new PendingParams { PendingPayer = fxPayer } }); }); Assert.Equal(ResponseCode.ScheduledTransactionNotInWhitelist, tex.Status); Assert.StartsWith("Unable to schedule transaction, status: ScheduledTransactionNotInWhitelist", tex.Message); }
public async Task CanGetImutableStatefulContractInfo() { await using var fx = await StatefulContract.CreateAsync(_network, f => { f.ContractParams.Administrator = null; }); var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract); Assert.NotNull(info); Assert.Equal(fx.ContractRecord.Contract, info.Contract); Assert.Equal(fx.ContractRecord.Contract, info.Address); // Assume for now they are equal Assert.NotNull(info.SmartContractId); // Immutable Contracts list their "contract" key as the administrator Key. Assert.Equal(KeyType.Contract, info.Administrator.Type); Assert.Equal(Abi.EncodeAddressPart(info.Contract).ToArray(), info.Administrator.PublicKey.ToArray()); Assert.InRange(info.Expiration, DateTime.UtcNow, DateTime.MaxValue); Assert.Equal(fx.ContractParams.RenewPeriod, info.RenewPeriod); Assert.InRange(info.Size, 0, fx.FileParams.Contents.Length); Assert.StartsWith(fx.ContractParams.Memo, info.Memo); Assert.Equal((ulong)fx.ContractParams.InitialBalance, info.Balance); }
public async Task CallQueryAttemptingStateChangeFailsWithoutErrorWhenThrowOnFailFalse() { await using var fx = await StatefulContract.CreateAsync(_network); var newMessage = Generator.Code(50); var result = await fx.Client.QueryContractAsync(new QueryContractParams { Contract = fx.ContractRecord.Contract, Gas = 30000, FunctionName = "set_message", FunctionArgs = new object[] { newMessage }, ReturnValueCharge = 900, ThrowOnFail = false }); Assert.NotNull(result); Assert.Equal("ILLEGAL_STATE_CHANGE", result.Error); Assert.False(result.Bloom.IsEmpty); Assert.InRange(result.Gas, 0UL, ulong.MaxValue); Assert.Empty(result.Events); Assert.Equal(0, result.Result.Size); Assert.Empty(result.CreatedContracts); }
public async Task CanCreateAContractWithStateAsync() { await using var fx = await StatefulContract.CreateAsync(_network); var record = await fx.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "get_message" }, 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.Equal(fx.ContractParams.Arguments[0] as string, record.CallResult.Result.As <string>()); }
public async Task CanUpdateContractBytecode() { await using var fx = await GreetingContract.CreateAsync(_network); await using var fx2 = await StatefulContract.SetupAsync(_network); var record = await fx.Client.UpdateContractWithRecordAsync(new UpdateContractParams { Contract = fx.ContractRecord.Contract, File = fx2.FileRecord.File }); var info = await fx.Client.GetContractInfoAsync(fx.ContractRecord.Contract); Assert.NotNull(info); Assert.Equal(fx.ContractRecord.Contract, info.Contract); Assert.Equal(fx.ContractRecord.Contract, info.Address); Assert.Equal(fx.ContractParams.Administrator, info.Administrator); Assert.Equal(fx.ContractParams.RenewPeriod, info.RenewPeriod); Assert.Equal(fx.Memo, info.Memo); Assert.Equal((ulong)fx.ContractParams.InitialBalance, info.Balance); // Call a method that was not part of the original contract to check update. // Note, this is a bug with the network, the call returned success but we are still // able to call the old contract method which should no longer exist. var callRecord = await fx.Client.CallContractWithRecordAsync(new CallContractParams { Contract = fx.ContractRecord.Contract, Gas = await _network.TinybarsFromGas(400), FunctionName = "greet", }); Assert.NotNull(callRecord); Assert.Equal(ResponseCode.Success, record.Status); Assert.Empty(callRecord.CallResult.Error); Assert.Equal("Hello, world!", callRecord.CallResult.Result.As <string>()); }