Skip to content

Commit

Permalink
Boltz verifier claim amount (#165)
Browse files Browse the repository at this point in the history
* feat: boltz verifier claim amount

* docs: add the description to specify what it does

* build: version

---------

Co-authored-by: Antonio <[email protected]>
  • Loading branch information
franciscotobar and antomor authored Aug 6, 2024
1 parent 59b67d6 commit d72976f
Show file tree
Hide file tree
Showing 11 changed files with 609 additions and 399 deletions.
4 changes: 2 additions & 2 deletions contracts/smartwallet/MinimalBoltzSmartWallet.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier:MIT
pragma solidity ^0.6.12;

import "../utils/BoltzBytesUtil.sol";
import "../utils/BoltzUtils.sol";

/* solhint-disable no-inline-assembly */
/* solhint-disable avoid-low-level-calls */
Expand Down Expand Up @@ -32,7 +32,7 @@ contract MinimalBoltzSmartWallet {

_isInitialized = true;

BoltzBytesUtil.validateClaimSignature(data);
BoltzUtils.validateClaimSignature(data);

(bool success, bytes memory ret) = to.call(data);
if (!success) {
Expand Down
33 changes: 0 additions & 33 deletions contracts/utils/BoltzBytesUtil.sol

This file was deleted.

89 changes: 89 additions & 0 deletions contracts/utils/BoltzUtils.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier:MIT
pragma solidity ^0.6.12;
pragma experimental ABIEncoderV2;

import "../interfaces/NativeSwap.sol";

library BoltzUtils {
//c3c37fbc => claim(bytes32,uint256,address,uint256)
bytes4 internal constant _EXTERNAL_SIGNATURE = 0xc3c37fbc;

//cd413efa => claim(bytes32,uint256,address,address,uint256)
bytes4 internal constant _PUBLIC_SIGNATURE = 0xcd413efa;

function validateClaimSignature(bytes memory data) internal pure {
bytes4 signature = toBytes4(data, 0);

if (
signature != _EXTERNAL_SIGNATURE && signature != _PUBLIC_SIGNATURE
) {
revert("Method not allowed");
}
}

function toBytes4(
bytes memory input,
uint256 offset
) internal pure returns (bytes4) {
bytes4 output;

/* solhint-disable-next-line no-inline-assembly */
assembly {
output := mload(add(add(input, 0x20), offset))
}

return output;
}

/**
* @dev Decode the claim data and validate if
* a swap is stored in the Swap contract.
* @param data The claim data.
* @param to The address of the Swap contract.
* @param contractAddr The claiming address.
* @return The amount of RBTC to be claimed.
*/
function validateClaim(
bytes calldata data,
address to,
address contractAddr
) internal returns (uint256) {
bytes4 signature = toBytes4(data, 0);
/* solhint-disable-next-line no-unused-vars */
NativeSwap.PublicClaimInfo memory claim;

if (signature == _EXTERNAL_SIGNATURE) {
NativeSwap.ExternalClaimInfo memory localClaim = abi.decode(
data[4:],
(NativeSwap.ExternalClaimInfo)
);
claim = NativeSwap.PublicClaimInfo(
localClaim.preimage,
localClaim.amount,
contractAddr,
localClaim.refundAddress,
localClaim.timelock
);
} else if (signature == _PUBLIC_SIGNATURE) {
claim = abi.decode(data[4:], (NativeSwap.PublicClaimInfo));
} else {
revert("Method not allowed");
}

NativeSwap swap = NativeSwap(to);

bytes32 preimageHash = sha256(abi.encodePacked(claim.preimage));

bytes32 hashValue = swap.hashValues(
preimageHash,
claim.amount,
claim.claimAddress,
claim.refundAddress,
claim.timelock
);

require(swap.swaps(hashValue), "Verifier: swap has no RBTC");

return claim.amount;
}
}
45 changes: 27 additions & 18 deletions contracts/verifier/BoltzDeployVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "../factory/BoltzSmartWalletFactory.sol";
import "../interfaces/IDeployVerifier.sol";
import "../interfaces/EnvelopingTypes.sol";
import "../utils/ContractValidator.sol";
import "../utils/BoltzUtils.sol";

/**
* A Verifier to be used on deploys.
Expand Down Expand Up @@ -48,25 +49,33 @@ contract BoltzDeployVerifier is

destinationContractValidation(relayRequest.request.to);

if (relayRequest.request.tokenContract != address(0)) {
require(
tokens[relayRequest.request.tokenContract],
"Token contract not allowed"
);
if (relayRequest.request.tokenAmount > 0) {
if (relayRequest.request.tokenContract != address(0)) {
require(
tokens[relayRequest.request.tokenContract],
"Token contract not allowed"
);

require(
relayRequest.request.tokenAmount <=
IERC20(relayRequest.request.tokenContract).balanceOf(
contractAddr
),
"Token balance too low"
);
} else {
require(
relayRequest.request.tokenAmount <=
address(contractAddr).balance,
"Native balance too low"
);
require(
relayRequest.request.tokenAmount <=
IERC20(relayRequest.request.tokenContract).balanceOf(
contractAddr
),
"Token balance too low"
);
} else {
uint256 amount = BoltzUtils.validateClaim(
relayRequest.request.data,
relayRequest.request.to,
contractAddr
);

require(
relayRequest.request.tokenAmount <=
address(contractAddr).balance + amount,
"Native balance too low"
);
}
}

return (
Expand Down
47 changes: 28 additions & 19 deletions contracts/verifier/BoltzRelayVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "../interfaces/IWalletFactory.sol";
import "../interfaces/IRelayVerifier.sol";
import "../interfaces/EnvelopingTypes.sol";
import "../utils/ContractValidator.sol";
import "../utils/BoltzUtils.sol";

/* solhint-disable no-inline-assembly */
/* solhint-disable avoid-low-level-calls */
Expand Down Expand Up @@ -56,27 +57,35 @@ contract BoltzRelayVerifier is
"SW different to template"
);

require(
contracts[relayRequest.request.to],
"Destination contract not allowed"
);
destinationContractValidation(relayRequest.request.to);

if (relayRequest.request.tokenAmount > 0) {
if (relayRequest.request.tokenContract != address(0)) {
require(
tokens[relayRequest.request.tokenContract],
"Token contract not allowed"
);

if (relayRequest.request.tokenContract != address(0)) {
require(
tokens[relayRequest.request.tokenContract],
"Token contract not allowed"
);
require(
relayRequest.request.tokenAmount <=
IERC20(relayRequest.request.tokenContract).balanceOf(
payer
),
"Token balance too low"
);
} else {
uint256 amount = BoltzUtils.validateClaim(
relayRequest.request.data,
relayRequest.request.to,
relayRequest.relayData.callForwarder
);

require(
relayRequest.request.tokenAmount <=
IERC20(relayRequest.request.tokenContract).balanceOf(payer),
"Token balance too low"
);
} else {
require(
relayRequest.request.tokenAmount <= address(payer).balance,
"Native balance too low"
);
require(
relayRequest.request.tokenAmount <=
address(payer).balance + amount,
"Native balance too low"
);
}
}

return (
Expand Down
47 changes: 2 additions & 45 deletions contracts/verifier/MinimalBoltzDeployVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "../factory/MinimalBoltzSmartWalletFactory.sol";
import "../interfaces/IDeployVerifier.sol";
import "../interfaces/EnvelopingTypes.sol";
import "../utils/ContractValidator.sol";
import "../utils/BoltzBytesUtil.sol";
import "../utils/BoltzUtils.sol";
import "../interfaces/NativeSwap.sol";

/**
Expand Down Expand Up @@ -53,7 +53,7 @@ contract MinimalBoltzDeployVerifier is

destinationContractValidation(relayRequest.request.to);

uint256 amount = _validateClaim(
uint256 amount = BoltzUtils.validateClaim(
relayRequest.request.data,
relayRequest.request.to,
contractAddr
Expand All @@ -78,47 +78,4 @@ contract MinimalBoltzDeployVerifier is
)
);
}

function _validateClaim(
bytes calldata data,
address to,
address contractAddr
) private returns (uint256) {
bytes4 signature = BoltzBytesUtil.toBytes4(data, 0);
NativeSwap.PublicClaimInfo memory claim;

if (signature == BoltzBytesUtil._EXTERNAL_SIGNATURE) {
NativeSwap.ExternalClaimInfo memory localClaim = abi.decode(
data[4:],
(NativeSwap.ExternalClaimInfo)
);
claim = NativeSwap.PublicClaimInfo(
localClaim.preimage,
localClaim.amount,
contractAddr,
localClaim.refundAddress,
localClaim.timelock
);
} else if (signature == BoltzBytesUtil._PUBLIC_SIGNATURE) {
claim = abi.decode(data[4:], (NativeSwap.PublicClaimInfo));
} else {
revert("Method not allowed");
}

NativeSwap swap = NativeSwap(to);

bytes32 preimageHash = sha256(abi.encodePacked(claim.preimage));

bytes32 hashValue = swap.hashValues(
preimageHash,
claim.amount,
claim.claimAddress,
claim.refundAddress,
claim.timelock
);

require(swap.swaps(hashValue), "Verifier: swap has no RBTC");

return claim.amount;
}
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rsksmart/rif-relay-contracts",
"version": "2.1.0-beta.0",
"version": "2.1.1-beta.0",
"private": false,
"description": "This project contains all the contracts needed for the rif relay system.",
"license": "MIT",
Expand Down
Loading

0 comments on commit d72976f

Please sign in to comment.