Skip to content

Conversation

@nathanieliov
Copy link
Contributor

@nathanieliov nathanieliov commented Aug 11, 2025

This pull request introduces ITs for the Union Bridge methods.

Integration tests:

  • Added integration tests for Union Bridge methods, when calls before Reed are made. (tests/01_00_00-calls-union-bridge-methods-fail.js)
  • Added integration tests for Union Bridge Method after Reed got activated. (tests/01_01_01-union-bridge-methods.js)

Union Bridge Contract and Deployment:

  • Added the new UnionBridgeContract Solidity contract, which acts as a wrapper over the bridge contract to request and release RBTC, and includes fallback and receive functions. (contracts/UnionBridgeContract.sol)
  • Updated the contract deployment utilities to support deploying the UnionBridgeContract, including a new deployUnionBridgeContract function. (lib/contractDeployer.js) [1] [2]

Constants and Utilities:

  • Added a new constants file for the Union Bridge Integration, defining addresses, authorizer keys, event names, storage indices, and response codes. (lib/constants/union-bridge-constants.js)
  • Added utility function getBridgeStorageIndexFromLongKey for generating storage indices using keccak256. (lib/utils.js) [1] [2] [3]

Dependency Updates:

  • Updated package dependencies to use the latest or correct versions for bridge and ABI packages, ensuring compatibility with new Union Bridge methods. (package.json)

rskj:union_bridge_integration
fed:union_bridge_integration

@nathanieliov nathanieliov requested a review from a team as a code owner August 11, 2025 12:40
@sonarqubecloud
Copy link


const UNION_BRIDGE_ADDRESS = '0x5988645D30cD01E4B3bC2c02CB3909dEC991Ae31';

// 400 RBTC initial locking cap
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// 400 RBTC initial locking cap
// 500 RBTC initial locking cap

?

Base automatically changed from segwit-test-initial-setup to main August 21, 2025 17:42
const {BRIDGE_ADDRESS} = require("../constants/bridge-constants");
const {getBridgeStorageValueDecodedHexString, removePrefix0x} = require("../utils");


Copy link
Contributor

Choose a reason for hiding this comment

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

nit: Too many empty lines.


const {btcToWeis, ethToWeis, weisToEth} = require("@rsksmart/btc-eth-unit-converter");

const {CHANGE_LOCKING_CAP_AUTHORIZERS_PKS, CHANGE_UNION_BRIDGE_CONTRACT_ADDRESS_AUTHORIZER_PK,
Copy link
Contributor

@jeremy-then jeremy-then Aug 21, 2025

Choose a reason for hiding this comment

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

nit: can we format it like?:

const {
CHANGE_LOCKING_CAP_AUTHORIZERS_PKS,
CHANGE_UNION_BRIDGE_CONTRACT_ADDRESS_AUTHORIZER_PK,
CHANGE_TRANSFER_PERMISSIONS_AUTHORIZERS_PKS,
UNION_RESPONSE_CODES,
UNION_BRIDGE_ADDRESS,
UNION_BRIDGE_STORAGE_INDICES,
INITIAL_LOCKING_CAP,
LOCKING_CAP_INCREMENTS_MULTIPLIER,
UNION_BRIDGE_EVENTS,
} = require("../constants/union-bridge-constants");

const RELEASE_PERMISSION_ENABLED = true;
const RELEASE_PERMISSION_DISABLED = false;

let rskTxHelpers;
Copy link
Contributor

Choose a reason for hiding this comment

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

No big deal, but let's put all these variables inside execute.

await deployAndFundUnionBridgeContract();
});

it('should setUnionBridgeContractAddressForTestnet change union address when calling on regtest', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('should setUnionBridgeContractAddressForTestnet change union address when calling on regtest', async () => {
it('should change union address when calling setUnionBridgeContractAddressForTestnet on regtest', async () => {

What do you think?

await assertNoEventWasEmitted(txReceipt);
});

it('should increaseUnionBridgeLockingCap fail and return UNAUTHORIZED_CALLER when calling from an unauthorized address', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('should increaseUnionBridgeLockingCap fail and return UNAUTHORIZED_CALLER when calling from an unauthorized address', async () => {
it('should fail and return UNAUTHORIZED_CALLER when calling increaseUnionBridgeLockingCap from an unauthorized address', async () => {

What do you think?

await assertNoEventWasEmitted(txReceipt);
});

it('should increaseUnionBridgeLockingCap first vote be successful when caller address is authorized', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('should increaseUnionBridgeLockingCap first vote be successful when caller address is authorized', async () => {
it('should successfully register a first vote while calling increaseUnionBridgeLockingCap when the caller address is authorized', async () => {

await assertNoEventWasEmitted(txReceipt);
});

it('should increaseUnionBridgeLockingCap second vote, to a different value than first vote, be successful when caller address is authorizer2', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('should increaseUnionBridgeLockingCap second vote, to a different value than first vote, be successful when caller address is authorizer2', async () => {
it('should successfully register a second vote with a different value than the first vote while calling increaseUnionBridgeLockingCap with authorizer2 address', async () => {

await assertNoEventWasEmitted(txReceipt);
});

it('should increaseUnionBridgeLockingCap third vote for same first vote value be successful when authorizer_2 vote again', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
it('should increaseUnionBridgeLockingCap third vote for same first vote value be successful when authorizer_2 vote again', async () => {
it('should successfully register a third vote for same first vote value while calling increaseUnionBridgeLockingCap when authorizer2 votes again', async () => {

await assertLogUnionLockingCapIncreased(txReceipt, changeLockingCapAuthorizer2Address, INITIAL_LOCKING_CAP, NEW_LOCKING_CAP_1);
});

it("should increaseUnionBridgeLockingCap(first vote after previous election ended) be successful when authorizer_2 vote again for previous second value value", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertNoEventWasEmitted(txReceipt);
});

it("should increaseUnionBridgeLockingCap return INVALID_VALUE when trying to decrease the locking cap", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertNoEventWasEmitted(txReceipt);
});

it("should requestUnionBridgeRbtc return UNAUTHORIZED_CALLER when caller is unauthorized", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertNoEventWasEmitted(txReceipt);
});

it("should requestUnionRbtc be successful when called from union bridge contract address", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertWeisTransferredToUnionBridgeBalance(expectedWeisTransferred);
});

it("should releaseUnionBridgeRbtc return UNAUTHORIZED_CALLER when caller is unauthorized", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertNoEventWasEmitted(txReceipt);
});

it("should releaseUnionBridgeRbtc be successful when called from union bridge contract", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertUnionBridgeBalance(expectedUnionBridgeBalanceAfter);
});

it("should setUnionBridgeTransferPermissions return UNAUTHORIZED_CALLER when caller is unauthorized", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertNoEventWasEmitted(txReceipt);
});

it("should setUnionBridgeTransferPermissions first vote be successful when called from authorized caller", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

await assertNoEventWasEmitted(txReceipt);
});

it("should setUnionBridgeTransferPermissions second vote for different value be successful when called from authorized caller", async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same description refactors as the others?

});
}

const importAccounts = async (privateKeys) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know there's a importAccounts function in change-federation.js. I think it's time for this function to be put into an util module and reuse it.

.padStart(66, '0x');
};

const getBridgeStorageIndexFromLongKey = (storageKey) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be in an utils file? Like 2wp-utils.js or something like that.


chai.use(require('chai-as-promised'));

const {CHANGE_LOCKING_CAP_AUTHORIZERS_PKS, CHANGE_UNION_BRIDGE_CONTRACT_ADDRESS_AUTHORIZER_PK,
Copy link
Contributor

Choose a reason for hiding this comment

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

Format this as my format suggestion above?

const REQUEST_PERMISSION_ENABLED = true;
const RELEASE_PERMISSION_ENABLED = true;

let rskTxHelpers;
Copy link
Contributor

Choose a reason for hiding this comment

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

All these variables inside execute? Check change-federation.js as an example.

});
}

const importAccounts = async (rskTxHelper, privateKeys) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as the one in the other file? Time to move these importAccounts functions to a utils file to reuse them.

@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants