Skip to content

Commit

Permalink
Merge pull request #139 from rsksmart/add-should-reject-and-refund-pe…
Browse files Browse the repository at this point in the history
…gout-below-minimum-test

Adds 'should reject and refund a pegout with value exactly below mini…
  • Loading branch information
marcos-iov authored Oct 30, 2024
2 parents 02d04ef + a3ba996 commit 8845a44
Show file tree
Hide file tree
Showing 4 changed files with 1,485 additions and 411 deletions.
15 changes: 14 additions & 1 deletion lib/2wp-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const { getBridge } = require('./precompiled-abi-forks-util');
const { getBridgeState } = require('@rsksmart/bridge-state-data-parser');
const { getDerivedRSKAddressInformation } = require('@rsksmart/btc-rsk-derivation');
const btcEthUnitConverter = require('@rsksmart/btc-eth-unit-converter');
const { PEGIN_EVENTS, DEFAULT_RSK_ADDRESS_FUNDING_IN_BTC } = require("./constants");
const { PEGIN_EVENTS, DEFAULT_RSK_ADDRESS_FUNDING_IN_BTC, PEGOUT_EVENTS } = require("./constants");

const peginVerifier = require('pegin-address-verificator');
const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider');
Expand Down Expand Up @@ -352,6 +352,18 @@ const fundRskAccountThroughAPegin = async (rskTxHelper, btcTxHelper, btcSenderAd
return btcPeginTxHash;
};

const createExpectedReleaseRequestRejectedEvent = (rskSenderAddress, amountInSatoshis, rejectionReason) => {
const expectedEvent = {
...PEGOUT_EVENTS.RELEASE_REQUEST_REJECTED,
arguments: {
sender: rskSenderAddress,
amount: amountInSatoshis.toString(),
reason: rejectionReason,
},
}
return expectedEvent;
};

module.exports = {
sendTxToBridge,
assertRefundUtxosSameAsPeginUtxos,
Expand All @@ -372,4 +384,5 @@ module.exports = {
createExpectedRejectedPeginEvent,
createExpectedUnrefundablePeginEvent,
fundRskAccountThroughAPegin,
createExpectedReleaseRequestRejectedEvent,
};
7 changes: 7 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ const PEGIN_UNREFUNDABLE_REASONS = {
INVALID_AMOUNT: '3',
};

const PEGOUT_REJECTION_REASONS = {
LOW_AMOUNT: '1',
CALLER_CONTRACT: '2',
FEE_ABOVE_VALUE: '3',
};

const PEGOUT_EVENTS = {
RELEASE_REQUEST_RECEIVED: {
name: 'release_request_received',
Expand Down Expand Up @@ -136,4 +142,5 @@ module.exports = {
PEGIN_V1_RSKT_PREFIX_HEX,
MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS,
DEFAULT_RSK_ADDRESS_FUNDING_IN_BTC,
PEGOUT_REJECTION_REASONS,
};
55 changes: 50 additions & 5 deletions lib/tests/2wp.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const {
PEGOUT_EVENTS,
PEGIN_V1_RSKT_PREFIX_HEX,
MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS,
PEGOUT_REJECTION_REASONS,
} = require("../constants");
const { sendPegin,
ensurePeginIsRegistered,
Expand All @@ -23,6 +24,7 @@ const { sendPegin,
assertRefundUtxosSameAsPeginUtxos,
sendTxToBridge,
fundRskAccountThroughAPegin,
createExpectedReleaseRequestRejectedEvent,
} = require('../2wp-utils');
const { getBtcAddressBalanceInSatoshis } = require('../btc-utils');
const { ensure0x, removePrefix0x } = require('../utils');
Expand Down Expand Up @@ -693,7 +695,7 @@ const execute = (description, getRskHost) => {

// Arrange

// Create a pegin for the serder to ensure there is enough funds to pegout and because this is the natural process
// Create a pegin for the sender to ensure there is enough funds to pegout and because this is the natural process
const senderRecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper);
await fundRskAccountThroughAPegin(rskTxHelper, btcTxHelper, senderRecipientInfo.btcSenderAddressInfo);

Expand Down Expand Up @@ -736,6 +738,42 @@ const execute = (description, getRskHost) => {

});

it('should reject and refund a pegout with value exactly below minimum', async () => {

// Arrange

// Create a pegin for the sender to ensure there is enough funds to pegout and because this is the natural process
const senderRecipientInfo = await createSenderRecipientInfo(rskTxHelper, btcTxHelper);
await fundRskAccountThroughAPegin(rskTxHelper, btcTxHelper, senderRecipientInfo.btcSenderAddressInfo);

const initial2wpBalances = await get2wpBalances(rskTxHelper, btcTxHelper);
const initialBtcRecipientAddressBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address);
const initialRskSenderBalanceInWeisBN = await rskTxHelper.getBalance(senderRecipientInfo.rskRecipientRskAddressInfo.address);
// Value exactly below minimum
const pegoutValueInSatoshis = MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS - 1;

// Act

const pegoutTransaction = await sendTxToBridge(rskTxHelper, new BN(satoshisToWeis(pegoutValueInSatoshis)), senderRecipientInfo.rskRecipientRskAddressInfo.address);

// Assert

await assertExpectedReleaseRequestRejectedEventIsEmitted(senderRecipientInfo.rskRecipientRskAddressInfo.address, pegoutValueInSatoshis, PEGOUT_REJECTION_REASONS.LOW_AMOUNT);

await assert2wpBalanceIsUnchanged(initial2wpBalances);

// The rsk sender balance is the same as the initial balance minus the gas fee, because the pegout amount was refunded.
const finalRskSenderBalanceInWeisBN = await rskTxHelper.getBalance(senderRecipientInfo.rskRecipientRskAddressInfo.address);
const gasFee = pegoutTransaction.gasUsed * pegoutTransaction.effectiveGasPrice;
const expectedRskSenderBalanceInWeisBN = initialRskSenderBalanceInWeisBN.sub(new BN(`${gasFee}`));
expect(finalRskSenderBalanceInWeisBN.eq(expectedRskSenderBalanceInWeisBN)).to.be.true;

// The btc recipient address balance is the same as the initial balance, because the pegout didn't go though.
const finalBtcRecipientBalanceInSatoshis = await getBtcAddressBalanceInSatoshis(btcTxHelper, senderRecipientInfo.btcSenderAddressInfo.address);
expect(finalBtcRecipientBalanceInSatoshis).to.be.equal(initialBtcRecipientAddressBalanceInSatoshis);

});

});

};
Expand Down Expand Up @@ -838,15 +876,15 @@ const assertSuccessfulPegoutEventsAreEmitted = async (pegoutsEvents, pegoutReque
// release_request_received event
const releaseRequestReceivedEvent = pegoutsEvents[0];
expect(releaseRequestReceivedEvent.arguments.sender).to.be.equal(rskSenderAddress);
expect(releaseRequestReceivedEvent.arguments.amount).to.be.equal(pegoutValueInSatoshis);
expect(Number(releaseRequestReceivedEvent.arguments.amount)).to.be.equal(pegoutValueInSatoshis);
expect(releaseRequestReceivedEvent.arguments.btcDestinationAddress).to.be.equal(senderRecipientInfo.btcSenderAddressInfo.address);

// release_requested event
const pegoutCreationRskTransactionHash = ensure0x(pegoutWaitingForConfirmationWhenPegoutWasCreated.rskTxHash.padStart(64, '0'));
const releaseRequestedEvent = pegoutsEvents[1];
expect(releaseRequestedEvent.arguments.rskTxHash).to.be.equal(pegoutCreationRskTransactionHash);
expect(removePrefix0x(releaseRequestedEvent.arguments.btcTxHash)).to.be.equal(btcTransaction.getId());
expect(releaseRequestReceivedEvent.arguments.amount).to.be.equal(pegoutValueInSatoshis);
expect(Number(releaseRequestReceivedEvent.arguments.amount)).to.be.equal(pegoutValueInSatoshis);

// batch_pegout_created event
const batchPegoutCreatedEvent = pegoutsEvents[2];
Expand Down Expand Up @@ -883,13 +921,20 @@ const assert2wpBalanceAfterSuccessfulPegout = async (initial2wpBalances, pegoutV

const final2wpBalances = await get2wpBalances(rskTxHelper, btcTxHelper);

expect(final2wpBalances.federationAddressBalanceInSatoshis).to.be.equal(initial2wpBalances.federationAddressBalanceInSatoshis - btcToSatoshis(pegoutValueInRbtc));
expect(final2wpBalances.federationAddressBalanceInSatoshis).to.be.equal(initial2wpBalances.federationAddressBalanceInSatoshis - pegoutValueInSatoshis);

const expectedFinalBridgeBalancesInWeisBN = initial2wpBalances.bridgeBalanceInWeisBN.add(new BN(satoshisToWeis(pegoutValueInSatoshis)));
expect(final2wpBalances.bridgeBalanceInWeisBN.eq(expectedFinalBridgeBalancesInWeisBN)).to.be.true;

expect(final2wpBalances.bridgeUtxosBalanceInSatoshis).to.be.equal(initial2wpBalances.bridgeUtxosBalanceInSatoshis - btcToSatoshis(pegoutValueInRbtc));
expect(final2wpBalances.bridgeUtxosBalanceInSatoshis).to.be.equal(initial2wpBalances.bridgeUtxosBalanceInSatoshis - pegoutValueInSatoshis);

};

const assertExpectedReleaseRequestRejectedEventIsEmitted = async (rskSenderAddress, amountInSatoshis, rejectionReason) => {
const rskSenderAddressChecksummed = rskTxHelper.getClient().utils.toChecksumAddress(ensure0x(rskSenderAddress));
const expectedEvent = createExpectedReleaseRequestRejectedEvent(rskSenderAddressChecksummed, amountInSatoshis, rejectionReason);
const releaseRequestRejectedEvent = await findEventInBlock(rskTxHelper, PEGOUT_EVENTS.RELEASE_REQUEST_REJECTED.name);
expect(releaseRequestRejectedEvent).to.be.deep.equal(expectedEvent);
};

module.exports = {
Expand Down
Loading

0 comments on commit 8845a44

Please sign in to comment.