Skip to content

Commit

Permalink
Merge branch 'main' into ver-5400
Browse files Browse the repository at this point in the history
  • Loading branch information
marcos-iov authored Sep 25, 2023
2 parents 20fda26 + 968f120 commit 2f21c59
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 116 deletions.
2 changes: 0 additions & 2 deletions lib/2wp-utils-legacy.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ const { getBridge, getLatestActiveForkName } = require('./precompiled-abi-forks-
const { getBridgeState } = require('@rsksmart/bridge-state-data-parser');

const BTC_TO_RSK_MINIMUM_CONFIRMATIONS = 3;
const MINIMUM_PEGIN_VALUE_IN_BTC = 1;

const assertEventFound = (rskClient) => async(eventName, callback, callBackParams, maxPastBlocksToCheck) => {
let eventFound = await rskUtilsLegacy.getBridgeEventAndRunAssertions(
Expand Down Expand Up @@ -239,5 +238,4 @@ module.exports = {
isUtxoRegisteredInBridge,
donateToBridge,
BTC_TO_RSK_MINIMUM_CONFIRMATIONS,
MINIMUM_PEGIN_VALUE_IN_BTC,
};
2 changes: 0 additions & 2 deletions lib/2wp-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ const ADDRESS_TYPES_CODES = {
};

const BTC_TO_RSK_MINIMUM_CONFIRMATIONS = 3;
const MINIMUM_PEGIN_VALUE_IN_BTC = 1;
const TO_BRIDGE_GAS_PRICE = 2;
const BRIDGE_ADDRESS = '0x0000000000000000000000000000000001000006';

Expand Down Expand Up @@ -248,7 +247,6 @@ module.exports = {
isUtxoRegisteredInBridge,
donateToBridge,
BTC_TO_RSK_MINIMUM_CONFIRMATIONS,
MINIMUM_PEGIN_VALUE_IN_BTC,
BRIDGE_ADDRESS,
createPeginV1TxData,
mineForPeginRegistration,
Expand Down
20 changes: 10 additions & 10 deletions lib/tests/2wp.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ const { getBtcClient } = require('../btc-client-provider');
const { getRskTransactionHelpers, getRskTransactionHelper } = require('../rsk-tx-helper-provider');
const { getDerivedRSKAddressInformation } = require('@rsksmart/btc-rsk-derivation');
const btcEthUnitConverter = require('btc-eth-unit-converter');
const { sendTxToBridge, sendPegin, ensurePeginIsRegistered, MINIMUM_PEGIN_VALUE_IN_BTC, donateToBridge } = require('../2wp-utils');
const { sendTxToBridge, sendPegin, ensurePeginIsRegistered, donateToBridge } = require('../2wp-utils');

const DONATION_AMOUNT = 250;
const REJECTED_REASON = 1;

let federationAddress;
let btcTxHelper;
let rskTxHelper;
let rskTxHelpers;
let federationAddress;
let minimumPeginValueInBtc;

const execute = (description, getRskHost) => {

Expand All @@ -29,6 +30,9 @@ const execute = (description, getRskHost) => {
const bridge = getBridge(rskTxHelper.getClient(), await getLatestActiveForkName());
federationAddress = await bridge.methods.getFederationAddress().call();

const minimumPeginValueInSatoshis = await bridge.methods.getMinimumLockTxValue().call();
minimumPeginValueInBtc = btcEthUnitConverter.satoshisToBtc(minimumPeginValueInSatoshis);

await btcTxHelper.importAddress(federationAddress, 'federations');

rskTxHelpers = getRskTransactionHelpers();
Expand All @@ -54,26 +58,22 @@ const execute = (description, getRskHost) => {
try {
const peginSenderAddressInfo = await btcTxHelper.generateBtcAddress('legacy');

await whitelistingAssertions.assertAddLimitedLockWhitelistAddress(rskTxHelper, peginSenderAddressInfo.address, btcEthUnitConverter.btcToSatoshis(MINIMUM_PEGIN_VALUE_IN_BTC));
await whitelistingAssertions.assertAddLimitedLockWhitelistAddress(rskTxHelper, peginSenderAddressInfo.address, btcEthUnitConverter.btcToSatoshis(minimumPeginValueInBtc));
await rskUtils.mineAndSync(rskTxHelpers);

const recipientRskAddressInfo = getDerivedRSKAddressInformation(peginSenderAddressInfo.privateKey, btcTxHelper.btcConfig.network);

const initialRskAddressBalanceInWeis = Number(await rskTxHelper.getBalance(recipientRskAddressInfo.address));

await btcTxHelper.fundAddress(peginSenderAddressInfo.address, MINIMUM_PEGIN_VALUE_IN_BTC + btcTxHelper.getFee());
await btcTxHelper.fundAddress(peginSenderAddressInfo.address, minimumPeginValueInBtc + btcTxHelper.getFee());

const peginBtcTxHash = await sendPegin(rskTxHelper, btcTxHelper, peginSenderAddressInfo, MINIMUM_PEGIN_VALUE_IN_BTC);

const peginBtcTxHash = await sendPegin(rskTxHelper, btcTxHelper, peginSenderAddressInfo, minimumPeginValueInBtc);
await ensurePeginIsRegistered(rskTxHelper, peginBtcTxHash);

const finalRskAddressBalanceInWeis = Number(await rskTxHelper.getBalance(recipientRskAddressInfo.address));

// Asserting that the received pegin amount in rsk is as expected

const peginValueInWeis = btcEthUnitConverter.btcToWeis(MINIMUM_PEGIN_VALUE_IN_BTC);
const peginValueInWeis = btcEthUnitConverter.btcToWeis(minimumPeginValueInBtc);
expect(finalRskAddressBalanceInWeis).to.equal(initialRskAddressBalanceInWeis + peginValueInWeis);

} catch (err) {
throw new CustomError('Transfer BTC to RBTC', err);
}
Expand Down
101 changes: 43 additions & 58 deletions tests/01_03_01-lock_whitelist_pre_papyrus.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ const {
const rskUtils = require('../lib/rsk-utils');
const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider');
const { getBtcClient } = require('../lib/btc-client-provider');
const { sendPegin, ensurePeginIsRegistered, MINIMUM_PEGIN_VALUE_IN_BTC } = require('../lib/2wp-utils');
const { sendPegin, ensurePeginIsRegistered } = require('../lib/2wp-utils');
const { getDerivedRSKAddressInformation } = require('@rsksmart/btc-rsk-derivation');
const { btcToWeis, btcToSatoshis, satoshisToBtc } = require('btc-eth-unit-converter');
const { getBridge, getLatestActiveForkName } = require('../lib/precompiled-abi-forks-util');

let federationAddress;
let rskTxHelpers;
let btcTxHelper;
let rskTxHelper;
let bridge;
let federationAddress;

const EXPECTED_UNSUCCESSFUL_RESULT = -10;
const FUND_AMOUNT_IN_WEIS = 1000000000;
Expand All @@ -35,50 +35,56 @@ const WHITELIST_ADDRESSES = {

const WHITELIST_RANDOM_PUBLIC_KEY = 'msJRGyaYvT8YNjvU3q9nPgBpZj9umAgetn';

/**
* Takes the blockchain to the required state for this test file to run in isolation.
*/
const fulfillRequirementsToRunAsSingleTestFile = async () => {
await rskUtils.activateFork(Runners.common.forks.wasabi100);
};

const assertLockCreatingWhiteListAddress = async (rskTxHelper, btcTxHelper, useUnlimitedWhitelist) => {
const minPeginValueInSatoshis = await bridge.methods.getMinimumLockTxValue().call();
const minPeginValueInBtc = satoshisToBtc(minPeginValueInSatoshis);

const btcAddressInformation = await btcTxHelper.generateBtcAddress('legacy');

const recipientRskAddressInfo = getDerivedRSKAddressInformation(btcAddressInformation.privateKey, btcTxHelper.btcConfig.network);

const initialRskAddressBalanceInWeis = Number(await rskTxHelper.getBalance(recipientRskAddressInfo.address));

await btcTxHelper.fundAddress(btcAddressInformation.address, MINIMUM_PEGIN_VALUE_IN_BTC + btcTxHelper.getFee());
await btcTxHelper.fundAddress(btcAddressInformation.address, minPeginValueInBtc + btcTxHelper.getFee());

if (useUnlimitedWhitelist) {
await assertAddUnlimitedWhitelistAddress(rskTxHelper, btcAddressInformation.address);
} else {
await assertAddOneOffWhitelistAddress(rskTxHelper, btcAddressInformation.address, btcToSatoshis(MINIMUM_PEGIN_VALUE_IN_BTC));
await assertAddOneOffWhitelistAddress(rskTxHelper, btcAddressInformation.address, minPeginValueInSatoshis);
}

await assertWhitelistAddressPresence(rskTxHelper, btcAddressInformation.address, true);

const peginBtcTxHash = await sendPegin(rskTxHelper, btcTxHelper, btcAddressInformation, MINIMUM_PEGIN_VALUE_IN_BTC);

const peginBtcTxHash = await sendPegin(rskTxHelper, btcTxHelper, btcAddressInformation, minPeginValueInBtc);
await ensurePeginIsRegistered(rskTxHelper, peginBtcTxHash);

await assertWhitelistAddressPresence(rskTxHelper, btcAddressInformation.address, useUnlimitedWhitelist);

const finalRskAddressBalanceInWeis = Number(await rskTxHelper.getBalance(recipientRskAddressInfo.address));

const peginValueInWeis = btcToWeis(MINIMUM_PEGIN_VALUE_IN_BTC);

const peginValueInWeis = btcToWeis(minPeginValueInBtc);
expect(finalRskAddressBalanceInWeis).to.equal(initialRskAddressBalanceInWeis + peginValueInWeis);

};
};

describe('Lock whitelisting', () => {
before(async () => {
if(process.env.RUNNING_SINGLE_TEST_FILE) {
await fulfillRequirementsToRunAsSingleTestFile();
}

rskTxHelpers = getRskTransactionHelpers();
btcTxHelper = getBtcClient();
rskTxHelper = rskTxHelpers[0];
bridge = getBridge(rskTxHelper.getClient(), await getLatestActiveForkName());

federationAddress = await bridge.methods.getFederationAddress().call();
await btcTxHelper.importAddress(federationAddress, 'federations');
});

it(`should prevent calling addOneOffLockWhitelistAddress without a correct key`, async () => {
const addOneOffLockWhitelistAddressMethod = bridge.methods.addOneOffLockWhitelistAddress(WHITELIST_RANDOM_PUBLIC_KEY, 1000000000);
const addOneOffLockWhitelistAddressMethod = bridge.methods.addOneOffLockWhitelistAddress(WHITELIST_RANDOM_PUBLIC_KEY, FUND_AMOUNT_IN_WEIS);
const rskTxSenderAddress = await rskTxHelper.newAccountWithSeed('test');
await rskUtils.sendFromCow(rskTxHelper, rskTxSenderAddress, FUND_AMOUNT_IN_WEIS);
const checkCallback = callResult => {
Expand Down Expand Up @@ -138,45 +144,36 @@ describe('Lock whitelisting', () => {
const nonWhitelistedCasesAmounts = [[15], [5, 7], [1, 23, 4]];

nonWhitelistedCasesAmounts.forEach(testCaseAmounts => {
it(`should return BTC from non-whitelisted addresses using same UTXOs as for lock attempt (${testCaseAmounts.length} UTXOs)`, async () => {
it(`should return BTC from non-whitelisted addresses using same UTXOs as for peg-in attempt (${testCaseAmounts.length} UTXOs)`, async () => {
const AMOUNT_TO_TRY_TO_LOCK = testCaseAmounts.reduce((a, b) => a + b);
const MAX_EXPECTED_FEE = 0.001;
// The extra 0.5 is to get some change back on the lock tx. This shouldn't really
// change anything, but it will end up considering the most common case.
const INITIAL_PEGIN_BALANCE = AMOUNT_TO_TRY_TO_LOCK + MAX_EXPECTED_FEE + 0.5;

const btcAddressInformation = await btcTxHelper.generateBtcAddress('legacy');

const recipientRskAddressInfo = getDerivedRSKAddressInformation(btcAddressInformation.privateKey, btcTxHelper.btcConfig.network);

await btcTxHelper.fundAddress(btcAddressInformation.address, INITIAL_PEGIN_BALANCE);

const initialFederationBalance = await btcTxHelper.getAddressBalance(federationAddress);

const peginBtcTxHash = await sendPegin(rskTxHelper, btcTxHelper, btcAddressInformation, testCaseAmounts);

const peginBtcTx = await btcTxHelper.getTransaction(peginBtcTxHash);
const btcBalanceAfterPegin = await btcTxHelper.getAddressBalance(btcAddressInformation.address);
expect(btcToSatoshis(btcBalanceAfterPegin)).to.equal(btcToSatoshis(INITIAL_PEGIN_BALANCE - AMOUNT_TO_TRY_TO_LOCK - MAX_EXPECTED_FEE), 'Lock BTC debit');

const btcBalance = await btcTxHelper.getAddressBalance(btcAddressInformation.address);

expect(btcToSatoshis(btcBalance)).to.equal(btcToSatoshis(INITIAL_PEGIN_BALANCE - AMOUNT_TO_TRY_TO_LOCK - MAX_EXPECTED_FEE), 'Lock BTC debit');

const federationBalance = await btcTxHelper.getAddressBalance(federationAddress);

expect(btcToSatoshis(federationBalance)).to.equal(btcToSatoshis(initialFederationBalance + AMOUNT_TO_TRY_TO_LOCK), `Lock BTC federation ${federationAddress} credit`);
const federationBalanceAfterPegin = await btcTxHelper.getAddressBalance(federationAddress);
expect(btcToSatoshis(federationBalanceAfterPegin)).to.equal(btcToSatoshis(initialFederationBalance + AMOUNT_TO_TRY_TO_LOCK), `Lock BTC federation ${federationAddress} credit`);

await rskTxHelper.updateBridge();
await rskUtils.mineAndSync(rskTxHelpers);

const initialBlockNumber = await rskTxHelper.getBlockNumber();

await rskUtils.mineAndSync(rskTxHelpers);

const currentBlockNumber = await rskTxHelper.getBlockNumber();
expect(currentBlockNumber).to.equal(initialBlockNumber + 1);

const currentRskBalance = await rskTxHelper.getBalance(recipientRskAddressInfo.address);

expect(Number(currentRskBalance), 'Wrong RSK balance').to.equal(0);
const currentRskBalance = Number(await rskTxHelper.getBalance(recipientRskAddressInfo.address));
expect(currentRskBalance, 'Wrong RSK balance').to.equal(0);

await rskUtils.triggerRelease(rskTxHelpers, getBtcClient());

Expand All @@ -189,13 +186,10 @@ describe('Lock whitelisting', () => {
expect(finalFederationBalance).to.equal(initialFederationBalance);

const utxos = await btcTxHelper.getUtxos(btcAddressInformation.address);

const nonLockUtxos = utxos.filter(utxo => utxo.txid !== peginBtcTxHash);

expect(nonLockUtxos.length).to.equal(1);

const returnUtxo = nonLockUtxos[0];

expect(AMOUNT_TO_TRY_TO_LOCK - returnUtxo.amount).to.be.at.most(MAX_EXPECTED_FEE);

const returnTx = await btcTxHelper.getTransaction(returnUtxo.txid);
Expand All @@ -214,52 +208,43 @@ describe('Lock whitelisting', () => {
});

expect(nonMatchedAmounts.length).to.equal(0);

});
});

it('should prevent locking RBTC when transfer is above maximum whitelisted', async () => {

const WHITELISTED_MAX_VALUE = MINIMUM_PEGIN_VALUE_IN_BTC - 0.1;
const PEGIN_VALUE_IN_BTC = 1;
const WHITELISTED_MAX_VALUE = PEGIN_VALUE_IN_BTC - 0.1;

const btcAddressInformation = await btcTxHelper.generateBtcAddress('legacy');
const recipientRskAddressInfo = getDerivedRSKAddressInformation(btcAddressInformation.privateKey, btcTxHelper.btcConfig.network);

await btcTxHelper.fundAddress(btcAddressInformation.address, MINIMUM_PEGIN_VALUE_IN_BTC + btcTxHelper.getFee());
await btcTxHelper.fundAddress(btcAddressInformation.address, PEGIN_VALUE_IN_BTC + btcTxHelper.getFee());

const initialFederationBalance = await btcTxHelper.getAddressBalance(federationAddress);

await assertAddOneOffWhitelistAddress(rskTxHelper, btcAddressInformation.address, btcToSatoshis(WHITELISTED_MAX_VALUE));

await sendPegin(rskTxHelper, btcTxHelper, btcAddressInformation, MINIMUM_PEGIN_VALUE_IN_BTC);

const midBtcAddressBalance = await btcTxHelper.getAddressBalance(btcAddressInformation.address);

expect(midBtcAddressBalance).to.equal(0, 'At this point the btc address should not have any balance');
await sendPegin(rskTxHelper, btcTxHelper, btcAddressInformation, PEGIN_VALUE_IN_BTC);

const finalFederationBalance = await btcTxHelper.getAddressBalance(federationAddress);
const btcAddressBalanceAfterPegin = await btcTxHelper.getAddressBalance(btcAddressInformation.address);
expect(btcAddressBalanceAfterPegin).to.equal(0, 'At this point the btc address should not have any balance');

expect(finalFederationBalance).to.equal(initialFederationBalance + MINIMUM_PEGIN_VALUE_IN_BTC, 'The federation address should have its balance increased by the pegin amount');
const federationBalanceAfterPegin = await btcTxHelper.getAddressBalance(federationAddress);
expect(federationBalanceAfterPegin).to.equal(initialFederationBalance + PEGIN_VALUE_IN_BTC, 'The federation address should have its balance increased by the pegin amount');

await rskTxHelper.updateBridge();
await rskUtils.mineAndSync(rskTxHelpers);

const currentRskBalance = await rskTxHelper.getBalance(recipientRskAddressInfo.address);

expect(Number(currentRskBalance)).to.equal(0, 'The recipient rsk address should not have any balance');
const recipientRskAddressBalance = Number(await rskTxHelper.getBalance(recipientRskAddressInfo.address));
expect(recipientRskAddressBalance).to.equal(0, 'The recipient rsk address should not have any balance');

// At this point there is a pegout waiting for confirmations, let's release it.
await rskUtils.triggerRelease(rskTxHelpers, getBtcClient());

const finalBtcAddressBalance = await btcTxHelper.getAddressBalance(btcAddressInformation.address);

const expectedFinalBtcAddressBalance = MINIMUM_PEGIN_VALUE_IN_BTC - btcTxHelper.getFee();

expect(expectedFinalBtcAddressBalance).to.be.at.most(finalBtcAddressBalance, 'The btc address should have its balance decreased by about the pegin amount and the fee');

const btcAddressBalanceAfterRefund = await btcTxHelper.getAddressBalance(btcAddressInformation.address);
expect(btcAddressBalanceAfterRefund).to.be.within(PEGIN_VALUE_IN_BTC - btcTxHelper.getFee(), PEGIN_VALUE_IN_BTC, 'The btc address should have its balance decreased by about the pegin amount and the fee');
});

it('should transfer BTC to RBTC from ONE-OFF whitelisted addresses', async () => {
await assertLockCreatingWhiteListAddress(rskTxHelper, btcTxHelper, false);
});
});
});
20 changes: 11 additions & 9 deletions tests/01_03_04-2wp_segwit_not_compatible.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const expect = require('chai').expect
const { satoshisToBtc } = require('btc-eth-unit-converter');
const rskUtils = require('../lib/rsk-utils');
const { getRskTransactionHelpers } = require('../lib/rsk-tx-helper-provider');

const { getBtcClient } = require('../lib/btc-client-provider');
const { sendPegin, MINIMUM_PEGIN_VALUE_IN_BTC } = require('../lib/2wp-utils');
const { sendPegin } = require('../lib/2wp-utils');
const { getBridge, getLatestActiveForkName } = require('../lib/precompiled-abi-forks-util');
const { isUtxoRegisteredInBridge } = require('../lib/2wp-utils');

Expand All @@ -27,28 +27,30 @@ describe('Lock p2sh-p2wpkh address', () => {
});

it('lock should fail when using p2sh-p2wpkh address', async () => {
const senderAddress = await btcTxHelper.generateBtcAddress('p2sh-segwit')

const latestActiveForkName = await getLatestActiveForkName();
const bridge = getBridge(rskTxHelper.getClient(), latestActiveForkName);
const federationAddress = await bridge.methods.getFederationAddress().call();

const minimumPeginValueInSatoshis = await bridge.methods.getMinimumLockTxValue().call();
const minimumPeginValueInBtc = satoshisToBtc(minimumPeginValueInSatoshis);

const federationAddress = await bridge.methods.getFederationAddress().call();
const federationAddressBalanceInitial = Number(await btcTxHelper.getAddressBalance(federationAddress));

await btcTxHelper.fundAddress(senderAddress.address, MINIMUM_PEGIN_VALUE_IN_BTC + btcTxHelper.getFee());
const senderAddress = await btcTxHelper.generateBtcAddress('p2sh-segwit')
await btcTxHelper.fundAddress(senderAddress.address, minimumPeginValueInBtc + btcTxHelper.getFee());

const btcPeginTxHash = await sendPegin(rskTxHelper, btcTxHelper, senderAddress, MINIMUM_PEGIN_VALUE_IN_BTC);
const btcPeginTxHash = await sendPegin(rskTxHelper, btcTxHelper, senderAddress, minimumPeginValueInBtc);

const federationAddressBalanceAfterPegin = Number(await btcTxHelper.getAddressBalance(federationAddress));
expect(Number(federationAddressBalanceAfterPegin)).to.be.equal(Number(federationAddressBalanceInitial + MINIMUM_PEGIN_VALUE_IN_BTC))
expect(Number(federationAddressBalanceAfterPegin)).to.be.equal(Number(federationAddressBalanceInitial + minimumPeginValueInBtc))

await rskUtils.triggerRelease(rskTxHelpers, btcTxHelper);

const isPeginUtxoRegistered = await isUtxoRegisteredInBridge(rskTxHelper, btcPeginTxHash);
expect(isPeginUtxoRegistered).to.be.false;

const federationAddressBalanceFinal = Number(await btcTxHelper.getAddressBalance(federationAddress));
expect(Number(federationAddressBalanceFinal)).to.be.equal(Number(federationAddressBalanceInitial + MINIMUM_PEGIN_VALUE_IN_BTC))
expect(Number(federationAddressBalanceFinal)).to.be.equal(Number(federationAddressBalanceInitial + minimumPeginValueInBtc))

const senderAddressBalanceFinal = await btcTxHelper.getAddressBalance(senderAddress.address);
expect(Number(senderAddressBalanceFinal)).to.be.equal(0)
Expand Down
Loading

0 comments on commit 2f21c59

Please sign in to comment.