Skip to content

Commit

Permalink
Simplified moving funds proposal validation
Browse files Browse the repository at this point in the history
  • Loading branch information
tomaszslabon committed Dec 19, 2023
1 parent 6b58e86 commit 7a889db
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 520 deletions.
105 changes: 27 additions & 78 deletions solidity/contracts/bridge/WalletProposalValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -603,100 +603,49 @@ contract WalletProposalValidator {
/// most of the work can be done using a single readonly contract
/// call.
/// @param proposal The moving funds proposal to validate.
/// @param walletMainUtxo The main UTXO of the source wallet.
/// @return True if the proposal is valid. Reverts otherwise.
/// @dev Requirements:
/// - The source wallet must be in the MovingFunds state,
/// - The source wallet must not have any pending redemptions,
/// - The source wallet must not have any pending moved funds sweep
/// requests,
/// - The source wallet's BTC balance must be greater than zero,
/// - The number of target wallets in the proposal must match the
/// expected count, based on the Live wallets count, source wallet's
/// BTC balance and maximum BTC transfer limit,
/// - All target wallets must be in the Live state and ordered correctly
/// (i.e. no duplicates and in ascending order of wallet addresses),
/// - The proposed moving funds transaction fee must be greater than
/// zero,
/// - The proposed moving funds transaction fee must not exceed the
/// maximum total fee allowed for moving funds.
function validateMovingFundsProposal(
MovingFundsProposal calldata proposal,
BitcoinTx.UTXO calldata walletMainUtxo
) external view returns (bool) {
/// @dev Notice that this function is meant to be invoked after the moving
/// funds commitment has already been submitted. This function skips
/// some checks related to the moving funds procedure as they were
/// already checked on the commitment submission.
/// Requirements:
/// - The source wallet must be in the MovingFunds state,
/// - The target wallets commitment must be submitted,
/// - The target wallets commitment hash must match the target wallets
/// from the proposal,
/// - The proposed moving funds transaction fee must be greater than
/// zero,
/// - The proposed moving funds transaction fee must not exceed the
/// maximum total fee allowed for moving funds.
function validateMovingFundsProposal(MovingFundsProposal calldata proposal)
external
view
returns (bool)
{
Wallets.Wallet memory sourceWallet = bridge.wallets(
proposal.walletPubKeyHash
);

// Make sure the source wallet is eligible for moving funds.
// Make sure the source wallet is in MovingFunds state.
require(
sourceWallet.state == Wallets.WalletState.MovingFunds,
"Source wallet is not in MovingFunds state"
);

// Make sure the moving funds commitment has been submitted and
// the commitment hash matches the target wallets from the proposal.
require(
sourceWallet.pendingRedemptionsValue == 0,
"Source wallet has pending redemptions"
);

require(
sourceWallet.pendingMovedFundsSweepRequestsCount == 0,
"Source wallet has pending moved funds sweep requests"
);

// Make sure the number of target wallets is correct.
uint64 sourceWalletBtcBalance = getWalletBtcBalance(
sourceWallet.mainUtxoHash,
walletMainUtxo
sourceWallet.movingFundsTargetWalletsCommitmentHash != bytes32(0),
"Target wallets commitment is not submitted"
);

require(
sourceWalletBtcBalance > 0,
"Source wallet BTC balance is zero"
sourceWallet.movingFundsTargetWalletsCommitmentHash ==
keccak256(abi.encodePacked(proposal.targetWallets)),
"Target wallets do not match target wallets commitment hash"
);

uint32 liveWalletsCount = bridge.liveWalletsCount();

(, , , , , uint64 walletMaxBtcTransfer, ) = bridge.walletParameters();

uint256 expectedTargetWalletsCount = Math.min(
liveWalletsCount,
Math.ceilDiv(sourceWalletBtcBalance, walletMaxBtcTransfer)
);

require(expectedTargetWalletsCount > 0, "No target wallets available");

require(
proposal.targetWallets.length == expectedTargetWalletsCount,
"Submitted target wallets count is other than expected"
);

// Make sure the target wallets are Live and are ordered correctly.
uint160 lastProcessedTargetWallet = 0;

for (uint256 i = 0; i < proposal.targetWallets.length; i++) {
bytes20 targetWallet = proposal.targetWallets[i];

require(
targetWallet != proposal.walletPubKeyHash,
"Target wallet is equal to source wallet"
);

require(
uint160(targetWallet) > lastProcessedTargetWallet,
"Target wallet order is incorrect"
);

// slither-disable-next-line calls-loop
require(
bridge.wallets(targetWallet).state == Wallets.WalletState.Live,
"Target wallet is not in Live state"
);

lastProcessedTargetWallet = uint160(targetWallet);
}

// Make sure the proposed fee does not exceed the total fee limit.
// Make sure the proposed fee is valid.
(uint64 movingFundsTxMaxTotalFee, , , , , , , , , , ) = bridge
.movingFundsParameters();

Expand Down
Loading

0 comments on commit 7a889db

Please sign in to comment.