Skip to content

Commit

Permalink
Merge pull request #1602 from input-output-hk/fix/LW-12198-incorrect-…
Browse files Browse the repository at this point in the history
…withdrawal-calculation

fix(core): withdrawal calculation in computeImplicitCoin [LW-12198]
  • Loading branch information
przemyslaw-wlodek authored Feb 19, 2025
2 parents a78683f + 46771ce commit 0c27328
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 5 deletions.
11 changes: 9 additions & 2 deletions packages/core/src/Cardano/util/computeImplicitCoin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,11 @@ const getTxDeposits = (
};
};

const getOwnWithdrawalsTotal = (withdrawals: Cardano.Withdrawal[], rewardAccounts: Address.RewardAccount[]) =>
BigIntMath.sum(
withdrawals.filter(({ stakeAddress }) => rewardAccounts.includes(stakeAddress)).map(({ quantity }) => quantity)
);

/**
* Computes the implicit coin from the given transaction.
* If rewardAccounts is provided, it will only count the deposits from
Expand All @@ -166,7 +171,7 @@ export const computeImplicitCoin = (
{
certificates,
proposalProcedures,
withdrawals
withdrawals = []
}: Pick<Cardano.HydratedTxBody, 'certificates' | 'proposalProcedures' | 'withdrawals'>,
rewardAccounts?: Address.RewardAccount[],
dRepKeyHash?: Crypto.Ed25519KeyHashHex
Expand All @@ -179,7 +184,9 @@ export const computeImplicitCoin = (
proposalProcedures
);

const withdrawalsTotal = (withdrawals && BigIntMath.sum(withdrawals.map(({ quantity }) => quantity))) || 0n;
const hasRewardAccount = !!rewardAccounts?.length;
const allWithdrawalsTotal = BigIntMath.sum(withdrawals.map(({ quantity }) => quantity));
const withdrawalsTotal = hasRewardAccount ? getOwnWithdrawalsTotal(withdrawals, rewardAccounts) : allWithdrawalsTotal;

return {
deposit,
Expand Down
36 changes: 33 additions & 3 deletions packages/core/test/Cardano/util/computeImplicitCoin.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Crypto from '@cardano-sdk/crypto';
import { Cardano } from '../../../src';
import { Ed25519KeyHashHex } from '@cardano-sdk/crypto';

describe('Cardano.util.computeImplicitCoin', () => {
let rewardAccount: Cardano.RewardAccount;
Expand Down Expand Up @@ -61,18 +62,19 @@ describe('Cardano.util.computeImplicitCoin', () => {

it('sums registrations for deposit, withdrawals and deregistrations for input', () => {
const protocolParameters = { dRepDeposit: 5, poolDeposit: 3, stakeKeyDeposit: 2 } as Cardano.ProtocolParameters;
const poolId = Cardano.PoolId.fromKeyHash(Ed25519KeyHashHex(Cardano.RewardAccount.toHash(rewardAccount)));
const certificates: Cardano.Certificate[] = [
{ __typename: Cardano.CertificateType.StakeRegistration, stakeCredential },
{ __typename: Cardano.CertificateType.StakeDeregistration, stakeCredential },
{ __typename: Cardano.CertificateType.StakeRegistration, stakeCredential },
{
__typename: Cardano.CertificateType.PoolRetirement,
epoch: Cardano.EpochNo(500),
poolId: Cardano.PoolId('pool1zuevzm3xlrhmwjw87ec38mzs02tlkwec9wxpgafcaykmwg7efhh')
poolId
},
{
__typename: Cardano.CertificateType.StakeDelegation,
poolId: Cardano.PoolId('pool1zuevzm3xlrhmwjw87ec38mzs02tlkwec9wxpgafcaykmwg7efhh'),
poolId,
stakeCredential
},
{
Expand All @@ -88,7 +90,7 @@ describe('Cardano.util.computeImplicitCoin', () => {
}
];
const withdrawals: Cardano.Withdrawal[] = [{ quantity: 5n, stakeAddress: rewardAccount }];
const coin = Cardano.util.computeImplicitCoin(protocolParameters, { certificates, withdrawals });
const coin = Cardano.util.computeImplicitCoin(protocolParameters, { certificates, withdrawals }, [rewardAccount]);
expect(coin.deposit).toBe(2n + 2n + 7n);
expect(coin.input).toBe(2n + 3n + 5n + 7n);
expect(coin.withdrawals).toBe(5n);
Expand Down Expand Up @@ -203,6 +205,34 @@ describe('Cardano.util.computeImplicitCoin', () => {
expect(coin.withdrawals).toBe(withdrawals[0].quantity);
});

it('sums withdrawals for input for own reward accounts', () => {
const protocolParameters = { dRepDeposit: 5, poolDeposit: 3, stakeKeyDeposit: 2 } as Cardano.ProtocolParameters;
const certificates: Cardano.Certificate[] = [];
const foreignRewardAccount = Cardano.RewardAccount(
'stake_test17rphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcljw6kf'
);
const withdrawals: Cardano.Withdrawal[] = [
{ quantity: 15n, stakeAddress: foreignRewardAccount },
{ quantity: 5n, stakeAddress: rewardAccount }
];
const coin = Cardano.util.computeImplicitCoin(protocolParameters, { certificates, withdrawals }, [rewardAccount]);
expect(coin.withdrawals).toBe(5n);
});

it('sums all withdrawals for input if there are no reward accounts provided', () => {
const protocolParameters = { dRepDeposit: 5, poolDeposit: 3, stakeKeyDeposit: 2 } as Cardano.ProtocolParameters;
const certificates: Cardano.Certificate[] = [];
const foreignRewardAccount = Cardano.RewardAccount(
'stake_test17rphkx6acpnf78fuvxn0mkew3l0fd058hzquvz7w36x4gtcljw6kf'
);
const withdrawals: Cardano.Withdrawal[] = [
{ quantity: 15n, stakeAddress: foreignRewardAccount },
{ quantity: 5n, stakeAddress: rewardAccount }
];
const coin = Cardano.util.computeImplicitCoin(protocolParameters, { certificates, withdrawals });
expect(coin.withdrawals).toBe(20n);
});

it('sums certificates and proposal procedures for deposit', () => {
const protocolParameters = { governanceActionDeposit: 4, stakeKeyDeposit: 2 } as Cardano.ProtocolParameters;
const governanceActionDeposit = BigInt(protocolParameters.governanceActionDeposit!);
Expand Down

0 comments on commit 0c27328

Please sign in to comment.