Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds 'should reject and refund a pegout when fee per kb is above valu… #140

10 changes: 10 additions & 0 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ const PEGIN_V1_RSKT_PREFIX_HEX = '52534b54';
const MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS = 250_000;
const DEFAULT_RSK_ADDRESS_FUNDING_IN_BTC = 0.5;

const FEE_PER_KB_CHANGER_PRIVATE_KEY = '6a4b49312b91e203ddfb9bc2d900ebbd46fbede46a7462e770bedcb11ad405e9';
const FEE_PER_KB_CHANGER_ADDRESS = '53f8f6dabd612b6137215ddd7758bb5cdd638922';

const FEE_PER_KB_RESPONSE_CODES = {
SUCCESSFUL_VOTE: 1,
};

module.exports = {
KEY_TYPE_BTC,
KEY_TYPE_RSK,
Expand All @@ -143,4 +150,7 @@ module.exports = {
MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS,
DEFAULT_RSK_ADDRESS_FUNDING_IN_BTC,
PEGOUT_REJECTION_REASONS,
FEE_PER_KB_CHANGER_PRIVATE_KEY,
FEE_PER_KB_CHANGER_ADDRESS,
FEE_PER_KB_RESPONSE_CODES,
};
30 changes: 28 additions & 2 deletions lib/rsk-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider');
const { wait, retryWithCheck, removePrefix0x } = require('./utils');
const { waitForBitcoinMempoolToGetTxs } = require('./btc-utils');
const { getLogger } = require('../logger');
const { PEGOUT_EVENTS } = require('./constants');
const {
PEGOUT_EVENTS,
FEE_PER_KB_CHANGER_PRIVATE_KEY,
FEE_PER_KB_CHANGER_ADDRESS,
FEE_PER_KB_RESPONSE_CODES,
} = require('./constants');
const BtcTransactionHelper = require('btc-transaction-helper/btc-transaction-helper');

const BTC_TO_RSK_MINIMUM_ACCEPTABLE_CONFIRMATIONS = 3;
Expand Down Expand Up @@ -502,7 +507,27 @@ const getFedsPubKeys = async (bridge) => {
FEDS_PUBKEYS_LIST.push(removePrefix0x(fedPubKey));
}
return FEDS_PUBKEYS_LIST;
}
};

/**
* Calls `Bridge::voteFeePerKbChange` to set a new fee per kb.
* @param {RskTransactionHelper} rskTxHelper
* @param {number} feePerKbInSatoshis the value to be set as the new fee per kb
*/
const setFeePerKb = async (rskTxHelper, feePerKbInSatoshis) => {

await rskTxHelper.getClient().eth.personal.importRawKey(FEE_PER_KB_CHANGER_PRIVATE_KEY, '');
await rskTxHelper.getClient().eth.personal.unlockAccount(FEE_PER_KB_CHANGER_ADDRESS, '');
const bridge = getBridge(rskTxHelper.getClient());

await sendTxWithCheck(rskTxHelper, bridge.methods.voteFeePerKbChange(feePerKbInSatoshis), FEE_PER_KB_CHANGER_ADDRESS, (result) => {
expect(Number(result)).to.equal(FEE_PER_KB_RESPONSE_CODES.SUCCESSFUL_VOTE);
});

const finalFeePerKb = await bridge.methods.getFeePerKb().call();
expect(Number(finalFeePerKb)).to.equal(Number(feePerKbInSatoshis));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also do a call before sending the transaction, and assert the response code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A call to voteFeePerKbChange or getFeePerKb?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, by calling sendTxWithCheck.


};

module.exports = {
mineAndSync,
Expand All @@ -522,4 +547,5 @@ module.exports = {
waitAndUpdateBridge,
sendTransaction,
getPegoutEventsInBlockRange,
setFeePerKb,
};
48 changes: 46 additions & 2 deletions lib/tests/2wp.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { getBridge } = require('../precompiled-abi-forks-util');
const { getBtcClient } = require('../btc-client-provider');
const { getRskTransactionHelper, getRskTransactionHelpers } = require('../rsk-tx-helper-provider');
const { satoshisToBtc, btcToSatoshis, satoshisToWeis } = require('@rsksmart/btc-eth-unit-converter');
const { findEventInBlock, triggerRelease, getPegoutEventsInBlockRange } = require('../rsk-utils');
const { findEventInBlock, triggerRelease, getPegoutEventsInBlockRange, setFeePerKb } = require('../rsk-utils');
const {
PEGIN_REJECTION_REASONS,
PEGIN_UNREFUNDABLE_REASONS,
Expand Down Expand Up @@ -774,6 +774,51 @@ const execute = (description, getRskHost) => {

});

it('should reject and refund a pegout when fee per kb is above value', 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);
const pegoutValueInSatoshis = MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS;

const initialFeePerKb = Number(await bridge.methods.getFeePerKb().call());
// We just need to have a feePerKB that will cause the pegout to rejected due to FEE_ABOVE_VALUE reason.
// This value is way bigger than what we need, but actual calculation is complex and and estimation so we cannot know for sure.
// That's we we just use a big enough value. The MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS is perfect for this in this case.
const newFeePerKbInSatoshis = MINIMUM_PEGOUT_AMOUNT_IN_SATOSHIS;
await setFeePerKb(rskTxHelper, newFeePerKbInSatoshis);

// Act

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

// Assert

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

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);

// Setting fee per kb back to its original value
await setFeePerKb(rskTxHelper, initialFeePerKb);

});

});

};
Expand Down Expand Up @@ -940,4 +985,3 @@ const assertExpectedReleaseRequestRejectedEventIsEmitted = async (rskSenderAddre
module.exports = {
execute,
};

Loading
Loading