Fix: Payout Transaction not matching when rate provided longer decima… (#2518)

* Fix: Payout Transaction not matching when rate provided longer decimal precision

fixes #2513 most likely

* Do not sue rounding and ensure crypto amount is saved with correct decimal places

* Round pull payment payout to the nearest digit supported by network

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
This commit is contained in:
Andrew Camilleri
2021-05-13 10:50:08 +02:00
committed by GitHub
parent 2961a2ed53
commit 6c9c7328bb
3 changed files with 27 additions and 3 deletions

View File

@@ -471,6 +471,25 @@ namespace BTCPayServer.Tests
{
Revision = payout.Revision
}));
// Create one pull payment with an amount of 9 decimals
var test3 = await client.CreatePullPayment(storeId, new Client.Models.CreatePullPaymentRequest()
{
Name = "Test 2",
Amount = 12.303228134m,
Currency = "BTC",
PaymentMethods = new[] { "BTC" }
});
destination = (await tester.ExplorerNode.GetNewAddressAsync()).ToString();
payout = await unauthenticated.CreatePayout(test3.Id, new CreatePayoutRequest()
{
Destination = destination,
PaymentMethod = "BTC"
});
payout = await client.ApprovePayout(storeId, payout.Id, new ApprovePayoutRequest());
// The payout should round the value of the payment down to the network of the payment method
Assert.Equal(12.30322814m, payout.PaymentMethodAmount);
Assert.Equal(12.303228134m, payout.Amount);
}
}

View File

@@ -227,7 +227,10 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
if (!payoutByDestination.TryGetValue(destination.Key, out var payout))
continue;
var payoutBlob = payout.GetBlob(_jsonSerializerSettings);
if (destination.Value != payoutBlob.CryptoAmount)
if (payoutBlob.CryptoAmount is null ||
// The round up here is not strictly necessary, this is temporary to fix existing payout before we
// were properly roundup the crypto amount
destination.Value != BTCPayServer.Extensions.RoundUp(payoutBlob.CryptoAmount.Value, network.Divisibility))
continue;
var proof = ParseProof(payout) as PayoutTransactionOnChainBlob;
if (proof is null)

View File

@@ -274,13 +274,14 @@ namespace BTCPayServer.HostedServices
var cryptoAmount = payoutBlob.Amount / req.Rate;
var payoutHandler = _payoutHandlers.First(handler => handler.CanHandle(paymentMethod));
var dest = await payoutHandler.ParseClaimDestination(paymentMethod, payoutBlob.Destination);
decimal minimumCryptoAmount = await payoutHandler.GetMinimumPayoutAmount(paymentMethod, dest);
if (cryptoAmount < minimumCryptoAmount)
{
req.Completion.TrySetResult(PayoutApproval.Result.TooLowAmount);
return;
}
payoutBlob.CryptoAmount = cryptoAmount;
payoutBlob.CryptoAmount = BTCPayServer.Extensions.RoundUp(cryptoAmount, _networkProvider.GetNetwork(paymentMethod.CryptoCode).Divisibility);
payout.SetBlob(payoutBlob, _jsonSerializerSettings);
await ctx.SaveChangesAsync();
req.Completion.SetResult(PayoutApproval.Result.Ok);
@@ -298,6 +299,7 @@ namespace BTCPayServer.HostedServices
DateTimeOffset now = DateTimeOffset.UtcNow;
await using var ctx = _dbContextFactory.CreateContext();
var pp = await ctx.PullPayments.FindAsync(req.ClaimRequest.PullPaymentId);
if (pp is null || pp.Archived)
{
req.Completion.TrySetResult(new ClaimRequest.ClaimResponse(ClaimRequest.ClaimResult.Archived));
@@ -316,7 +318,7 @@ namespace BTCPayServer.HostedServices
var ppBlob = pp.GetBlob();
var payoutHandler =
_payoutHandlers.FirstOrDefault(handler => handler.CanHandle(req.ClaimRequest.PaymentMethodId));
if (!ppBlob.SupportedPaymentMethods.Contains(req.ClaimRequest.PaymentMethodId) || payoutHandler is null )
if (!ppBlob.SupportedPaymentMethods.Contains(req.ClaimRequest.PaymentMethodId) || payoutHandler is null)
{
req.Completion.TrySetResult(new ClaimRequest.ClaimResponse(ClaimRequest.ClaimResult.PaymentMethodNotSupported));
return;