编译器
0.8.20+commit.a1b79de6
文件 1 的 30:Address.sol
pragma solidity ^0.8.20;
library Address {
error AddressInsufficientBalance(address account);
error AddressEmptyCode(address target);
error FailedInnerCall();
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}
文件 2 的 30:BaseAssetManager.sol
pragma solidity >=0.8.20;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IAssetPool} from "../interfaces/IAssetPool.sol";
import {IVerifier} from "../interfaces/IVerifier.sol";
import {IVerifierHub} from "../interfaces/IVerifierHub.sol";
import {IRelayerHub} from "../interfaces/IRelayerHub.sol";
import {IFeeManager} from "../interfaces/IFeeManager.sol";
import {IComplianceManager} from "../interfaces/IComplianceManager.sol";
import {IMerkleTreeOperator} from "../interfaces/IMerkleTreeOperator.sol";
import {IMimc254} from "../interfaces/IMimc254.sol";
import {BaseInputBuilder} from "./BaseInputBuilder.sol";
abstract contract BaseAssetManager is Ownable, BaseInputBuilder {
using SafeERC20 for IERC20;
struct FundReleaseDetails {
address assetAddress;
address payable recipient;
address payable relayer;
uint256 relayerGasFee;
uint256 amount;
}
IVerifierHub internal _verifierHub;
IAssetPool internal _assetPoolERC20;
IAssetPool internal _assetPoolERC721;
IAssetPool internal _assetPoolETH;
IRelayerHub internal _relayerHub;
IFeeManager internal _feeManager;
IComplianceManager internal _complianceManager;
IMerkleTreeOperator internal immutable _merkleTreeOperator;
IMimc254 internal immutable _mimc254;
address public constant ETH_ADDRESS =
0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
bytes32 public constant ASSET_ETH = keccak256(abi.encode(ETH_ADDRESS));
uint256 public constant P =
21888242871839275222246405745257275088548364400416034343698204186575808495617;
error RelayerNotRegistered();
error NullifierUsed();
error NullifierLocked();
error MerkleRootNotAllowed();
error NoteFooterUsed();
error NoteAlreadyCreated();
error InvalidNoteParameters();
error ZeroAddress();
error NoteFooterDuplicated();
error RelayerMismatch();
modifier onlyETHAssetPool() {
require(
msg.sender == address(_assetPoolETH),
"BaseAssetManager: Only ETH Asset Pool"
);
_;
}
constructor(
address assetPoolERC20,
address assetPoolERC721,
address assetPoolETH,
address verifierHub,
address relayerHub,
address feeManager,
address complianceManager,
address merkleTreeOperator,
address mimc254,
address initialOwner
) Ownable(initialOwner) {
if (assetPoolERC20 == address(0) ||
assetPoolERC721 == address(0) ||
assetPoolETH == address(0) ||
verifierHub == address(0) ||
relayerHub == address(0) ||
feeManager == address(0) ||
complianceManager == address(0) ||
merkleTreeOperator == address(0) ||
mimc254 == address(0) ||
initialOwner == address(0)
) {
revert ZeroAddress();
}
_assetPoolERC20 = IAssetPool(assetPoolERC20);
_assetPoolERC721 = IAssetPool(assetPoolERC721);
_assetPoolETH = IAssetPool(assetPoolETH);
_verifierHub = IVerifierHub(verifierHub);
_relayerHub = IRelayerHub(relayerHub);
_feeManager = IFeeManager(feeManager);
_complianceManager = IComplianceManager(complianceManager);
_merkleTreeOperator = IMerkleTreeOperator(merkleTreeOperator);
_mimc254 = IMimc254(mimc254);
}
receive() external payable {}
function releaseToAsssetPool(
address asset,
uint256 amount
) external onlyOwner {
require(amount > 0, "BaseAssetManager: amount must be greater than 0");
if (asset == address(0) || asset == ETH_ADDRESS) {
(bool success, ) = address(_assetPoolETH).call{value: amount}("");
require(success, "BaseAssetManager: Failed to send Ether");
} else {
IERC20(asset).safeTransfer(address(_assetPoolERC20), amount);
}
}
function setAssetPoolERC20(address assetPoolERC20) public onlyOwner {
if (assetPoolERC20 != address(0)) {
_assetPoolERC20 = IAssetPool(assetPoolERC20);
}
}
function setAssetPoolERC721(address assetPoolERC721) public onlyOwner {
if (assetPoolERC721 != address(0)) {
_assetPoolERC721 = IAssetPool(assetPoolERC721);
}
}
function setAssetPoolETH(address assetPoolETH) public onlyOwner {
if (assetPoolETH != address(0)) {
_assetPoolETH = IAssetPool(assetPoolETH);
}
}
function setVerifierHub(address verifierHub) public onlyOwner {
if (verifierHub != address(0)) {
_verifierHub = IVerifierHub(verifierHub);
}
}
function setRelayerHub(address relayerHub) public onlyOwner {
if (relayerHub != address(0)) {
_relayerHub = IRelayerHub(relayerHub);
}
}
function setFeeManager(address feeManager) public onlyOwner {
if (feeManager != address(0)) {
_feeManager = IFeeManager(feeManager);
}
}
function setComplianceManager(address complianceManager) public onlyOwner {
if (complianceManager != address(0)) {
_complianceManager = IComplianceManager(complianceManager);
}
}
function getAssetPoolERC20() public view returns (address) {
return address(_assetPoolERC20);
}
function getAssetPoolERC721() public view returns (address) {
return address(_assetPoolERC721);
}
function getAssetPoolETH() public view returns (address) {
return address(_assetPoolETH);
}
function getVerifierHub() public view returns (address) {
return address(_verifierHub);
}
function getRelayerHub() public view returns (address) {
return address(_relayerHub);
}
function getFeeManager() public view returns (address) {
return address(_feeManager);
}
function getComplianceManager() public view returns (address) {
return address(_complianceManager);
}
function getMerkleTreeOperator() public view returns (address) {
return address(_merkleTreeOperator);
}
function getMimc254() public view returns (address) {
return address(_mimc254);
}
function _postDeposit(bytes32 _noteCommitment) internal {
_merkleTreeOperator.setNoteCommitmentCreated(_noteCommitment);
_merkleTreeOperator.appendMerkleLeaf(bytes32(_noteCommitment));
}
function _postWithdraw(bytes32 _nullifier) internal {
_merkleTreeOperator.setNullifierUsed(_nullifier);
}
function _setNullifierLock(bytes32 _nullifier, bool _locked) internal {
_merkleTreeOperator.setNullifierLocked(_nullifier, _locked);
}
function _registerNoteFooter(bytes32 _noteFooter) internal {
_merkleTreeOperator.setNoteFooterUsed(_noteFooter);
}
function _releaseERC20WithFee(
address _asset,
address _to,
address _relayer,
uint256 _relayerGasFee,
uint256 _amount
) internal returns (uint256, uint256, uint256) {
(
uint256 actualAmount,
uint256 serviceFee,
uint256 relayerRefund
) = _feeManager.calculateFee(_amount, _relayerGasFee);
_assetPoolERC20.release(_asset, _to, actualAmount);
if (relayerRefund > 0) {
_assetPoolERC20.release(_asset, _relayer, relayerRefund);
}
if (serviceFee > 0) {
_assetPoolERC20.release(_asset, address(_feeManager), serviceFee);
}
return (actualAmount, serviceFee, relayerRefund);
}
function _releaseETHWithFee(
address payable _to,
address payable _relayer,
uint256 _relayerGasFee,
uint256 _amount
) internal returns (uint256, uint256, uint256) {
(
uint256 actualAmount,
uint256 serviceFee,
uint256 relayerRefund
) = _feeManager.calculateFee(_amount, _relayerGasFee);
_assetPoolETH.release(_to, actualAmount);
if (relayerRefund > 0) {
_assetPoolETH.release(_relayer, relayerRefund);
}
if (serviceFee > 0) {
_assetPoolETH.release(payable(address(_feeManager)), serviceFee);
}
return (actualAmount, serviceFee, relayerRefund);
}
function _releaseFunds(
FundReleaseDetails memory details
) internal returns (uint256, uint256, uint256) {
if (
details.assetAddress == ETH_ADDRESS ||
details.assetAddress == address(0)
) {
return
_releaseETHWithFee(
details.recipient,
details.relayer,
details.relayerGasFee,
details.amount
);
} else {
return
_releaseERC20WithFee(
details.assetAddress,
details.recipient,
details.relayer,
details.relayerGasFee,
details.amount
);
}
}
function _verifyProof(
bytes calldata _proof,
bytes32[] memory _inputs,
string memory verifierType
) internal view {
IVerifier verifier = _verifierHub.getVerifier(verifierType);
require(verifier.verify(_proof, _inputs), "invalid proof");
}
function _buildNoteForERC20(
address asset,
uint256 amount,
bytes32 noteFooter
) internal view returns (bytes32) {
return _buildNote(
asset,
amount,
noteFooter,
IMimc254.NoteDomainSeparator.FUNGIBLE
);
}
function _buildNoteForERC721(
address asset,
uint256 tokenId,
bytes32 noteFooter
) internal view returns (bytes32) {
return _buildNote(
asset,
tokenId,
noteFooter,
IMimc254.NoteDomainSeparator.NON_FUNGIBLE
);
}
function _validateRelayerIsRegistered(address relayer) internal view {
if (!_relayerHub.isRelayerRegistered(relayer)) {
revert RelayerNotRegistered();
}
}
function _validateNullifierIsNotUsed(bytes32 nullifier) internal view {
if (!_merkleTreeOperator.nullifierIsNotUsed(nullifier)) {
revert NullifierUsed();
}
}
function _validateNullifierIsNotLocked(bytes32 nullifier) internal view {
if (!_merkleTreeOperator.nullifierIsNotLocked(nullifier)) {
revert NullifierLocked();
}
}
function _validateMerkleRootIsAllowed(bytes32 merkleRoot) internal view {
if (!_merkleTreeOperator.merkleRootIsAllowed(merkleRoot)) {
revert MerkleRootNotAllowed();
}
}
function _validateNoteFooterIsNotUsed(bytes32 noteFooter) internal view {
if (!_merkleTreeOperator.noteFooterIsNotUsed(noteFooter)) {
revert NoteFooterUsed();
}
}
function _validateNoteIsNotCreated(bytes32 noteCommitment) internal view {
if (!_merkleTreeOperator.noteIsNotCreated(noteCommitment)) {
revert NoteAlreadyCreated();
}
}
function _buildNote(
address asset,
uint256 amount,
bytes32 noteFooter,
IMimc254.NoteDomainSeparator domainSeparator
) private view returns (bytes32) {
if (asset == address(0) || amount == 0 || noteFooter == bytes32(0)){
revert InvalidNoteParameters();
}
uint256[] memory array = new uint256[](4);
array[0] = uint256(domainSeparator);
array[1] = uint256(_bytifyToNoir(asset));
array[2] = amount;
array[3] = uint256(noteFooter);
return
bytes32(_mimc254.mimcBn254(array));
}
}
文件 3 的 30:BaseInputBuilder.sol
pragma solidity ^0.8.20;
contract BaseInputBuilder {
uint256 internal _primeField;
constructor(uint256 primeField) {
_primeField = primeField;
}
function _bytifyToNoir(address value) internal pure returns (bytes32) {
return bytes32(uint256(uint160(ripemd160(abi.encode(value)))));
}
}
文件 4 的 30:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 5 的 30:IAssetPool.sol
pragma solidity >=0.8.20;
interface IAssetPool {
function setAssetManager(address assetManager,bool registered) external;
function release(address tokenOrNft, address to, uint256 amountOrNftId) external;
function release(address payable to, uint256 amount) external;
function getAssetManagerRegistration( address assetManager)
external view returns(bool);
}
文件 6 的 30:IComplianceManager.sol
pragma solidity >=0.8.20;
interface IComplianceManager {
function isAuthorized(address observer, address subject) external returns (bool);
}
文件 7 的 30:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 8 的 30:IERC20.sol
pragma solidity ^0.8.20;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
文件 9 的 30:IERC20Permit.sol
pragma solidity ^0.8.20;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 10 的 30:IERC721.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC721 is IERC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
function balanceOf(address owner) external view returns (uint256 balance);
function ownerOf(uint256 tokenId) external view returns (address owner);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function setApprovalForAll(address operator, bool approved) external;
function getApproved(uint256 tokenId) external view returns (address operator);
function isApprovedForAll(address owner, address operator) external view returns (bool);
}
文件 11 的 30:IERC721Enumerable.sol
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
interface IERC721Enumerable is IERC721 {
function totalSupply() external view returns (uint256);
function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);
function tokenByIndex(uint256 index) external view returns (uint256);
}
文件 12 的 30:IERC721Metadata.sol
pragma solidity ^0.8.20;
import {IERC721} from "../IERC721.sol";
interface IERC721Metadata is IERC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
文件 13 的 30:IERC721Permit.sol
pragma solidity >=0.7.5;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
interface IERC721Permit is IERC721 {
function PERMIT_TYPEHASH() external pure returns (bytes32);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address spender,
uint256 tokenId,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external payable;
}
文件 14 的 30:IFeeManager.sol
pragma solidity >=0.8.20;
interface IFeeManager {
function calculateFee(
uint256 amount,
uint256 relayerRefund
) external view returns (uint256, uint256, uint256);
function calculateFee(
uint256[4] calldata amount,
uint256[4] calldata relayerRefund
) external view returns (uint256[4] memory, uint256[4] memory, uint256[4] memory);
function calculateFeeForFSN(
uint256[4] calldata amount,
uint256[4] calldata relayerRefund
) external view returns (uint256[] memory, uint256[4] memory, uint256[4] memory);
}
文件 15 的 30:IMerkleTreeOperator.sol
pragma solidity >=0.8.20;
interface IMerkleTreeOperator {
function appendMerkleLeaf(bytes32 leaf) external;
function setNoteCommitmentCreated(bytes32 commitment) external;
function setNullifierUsed(bytes32 nullifier) external;
function setNullifierLocked(bytes32 nullifier, bool locked) external;
function setNoteFooterUsed(bytes32 noteFooter) external;
function isRelayerRegistered(address _relayer) external view returns (bool);
function merkleRootIsAllowed(
bytes32 _merkleRoot
) external view returns (bool);
function nullifierIsNotUsed(
bytes32 _nullifier
) external view returns (bool);
function nullifierIsNotLocked(
bytes32 _nullifier
) external view returns (bool);
function noteIsNotCreated(
bytes32 _noteCommitment
) external view returns (bool);
function noteFooterIsNotUsed(
bytes32 _noteFooter
) external view returns (bool);
function getMerkleRoot() external view returns (bytes32);
function getMerklePath(
bytes32 _noteCommitment
) external view returns (bytes32[] memory, bool[] memory, bytes32);
}
文件 16 的 30:IMimc254.sol
pragma solidity >=0.8.20;
interface IMimc254 {
enum NoteDomainSeparator {
FUNGIBLE,
NON_FUNGIBLE
}
function mimcBn254(uint256[] memory array) external view returns (uint256);
}
文件 17 的 30:INonfungiblePositionManager.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Enumerable.sol";
import "./IPoolInitializer.sol";
import "./IERC721Permit.sol";
import "./IPeripheryPayments.sol";
import "./IPeripheryImmutableState.sol";
import "../libraries/PoolAddress.sol";
interface INonfungiblePositionManager is
IPoolInitializer,
IPeripheryPayments,
IPeripheryImmutableState,
IERC721Metadata,
IERC721Enumerable,
IERC721Permit
{
event IncreaseLiquidity(
uint256 indexed tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
event DecreaseLiquidity(
uint256 indexed tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
event Collect(
uint256 indexed tokenId,
address recipient,
uint256 amount0,
uint256 amount1
);
function positions(
uint256 tokenId
)
external
view
returns (
uint96 nonce,
address operator,
address token0,
address token1,
uint24 fee,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
function mint(
MintParams calldata params
)
external
payable
returns (
uint256 tokenId,
uint128 liquidity,
uint256 amount0,
uint256 amount1
);
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
function increaseLiquidity(
IncreaseLiquidityParams calldata params
)
external
payable
returns (uint128 liquidity, uint256 amount0, uint256 amount1);
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
function decreaseLiquidity(
DecreaseLiquidityParams calldata params
) external payable returns (uint256 amount0, uint256 amount1);
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
function collect(
CollectParams calldata params
) external payable returns (uint256 amount0, uint256 amount1);
function burn(uint256 tokenId) external payable;
}
文件 18 的 30:IPeripheryImmutableState.sol
pragma solidity >=0.5.0;
interface IPeripheryImmutableState {
function factory() external view returns (address);
function WETH9() external view returns (address);
}
文件 19 的 30:IPeripheryPayments.sol
pragma solidity >=0.7.5;
interface IPeripheryPayments {
function unwrapWETH9(
uint256 amountMinimum,
address recipient
) external payable;
function refundETH() external payable;
function sweepToken(
address token,
uint256 amountMinimum,
address recipient
) external payable;
}
文件 20 的 30:IPoolInitializer.sol
pragma solidity >=0.7.5;
pragma abicoder v2;
interface IPoolInitializer {
function createAndInitializePoolIfNecessary(
address token0,
address token1,
uint24 fee,
uint160 sqrtPriceX96
) external payable returns (address pool);
}
文件 21 的 30:IRelayerHub.sol
pragma solidity >=0.8.20;
interface IRelayerHub {
function isRelayerRegistered(address _relayer) external view returns (bool);
}
文件 22 的 30:IVerifier.sol
pragma solidity >=0.8.20;
interface IVerifier {
function verify(
bytes calldata _proof,
bytes32[] calldata _publicInputs
) external view returns (bool);
}
文件 23 的 30:IVerifierHub.sol
pragma solidity ^0.8.20;
import {IVerifier} from "./IVerifier.sol";
interface IVerifierHub {
function setVerifier(string memory verifierName, address addr) external;
function getVerifierNames() external returns (string[] memory);
function getVerifier(
string memory verifierName
) external view returns (IVerifier);
}
文件 24 的 30:IWETH9.sol
pragma solidity >=0.8.20;
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IWETH9 is IERC20 {
function deposit() external payable;
function withdraw(uint256) external;
}
文件 25 的 30:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 26 的 30:PoolAddress.sol
pragma solidity >=0.5.0;
library PoolAddress {
bytes32 internal constant POOL_INIT_CODE_HASH =
0xe34f199b19b2b4f47f68442619d555527d244f78a3297ea89325f843f87b8b54;
struct PoolKey {
address token0;
address token1;
uint24 fee;
}
function getPoolKey(
address tokenA,
address tokenB,
uint24 fee
) internal pure returns (PoolKey memory) {
if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA);
return PoolKey({token0: tokenA, token1: tokenB, fee: fee});
}
function computeAddress(
address factory,
PoolKey memory key
) internal pure returns (address pool) {
require(key.token0 < key.token1);
pool = address(
uint160(
uint256(
keccak256(
abi.encodePacked(
hex"ff",
factory,
keccak256(
abi.encode(key.token0, key.token1, key.fee)
),
POOL_INIT_CODE_HASH
)
)
)
)
);
}
}
文件 27 的 30:SafeERC20.sol
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
error SafeERC20FailedOperation(address token);
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}
文件 28 的 30:UniswapCoreAssetManager.sol
pragma solidity ^0.8.20;
import {BaseAssetManager} from "../../core/base/BaseAssetManager.sol";
import {UniswapInputBuilder} from "./UniswapInputBuilder.sol";
import {IWETH9} from "../../core/interfaces/IWETH9.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract UniswapCoreAssetManager is BaseAssetManager, UniswapInputBuilder {
using SafeERC20 for IERC20;
struct UniswapNoteData {
address assetAddress;
uint256 amount;
bytes32 nullifier;
}
struct FeesDetails {
uint256 serviceFee;
uint256 relayerRefund;
}
struct AutoSplitArgs {
address asset;
uint256 actualAmount;
uint256 desiredAmount;
bytes32 nullifier;
bytes32 noteFooter;
bytes32 changeNoteFooter;
}
struct AutoSplitDetails {
bytes32 note;
bytes32 changeNote;
uint256 changeAmount;
}
struct TransferFundsToVaultWithFeesAndCreateNoteData {
uint256 actualAmount;
address normalizedAsset;
bytes32 noteCommitment;
FeesDetails feesDetails;
}
address public WETH_ADDRESS;
constructor(
address assetPoolERC20,
address assetPoolERC721,
address assetPoolETH,
address verifierHub,
address relayerHub,
address feeManager,
address keyringManager,
address merkleTreeOperator,
address mimcBn254,
address initialOwner,
address wethAddress
)
BaseAssetManager(
assetPoolERC20,
assetPoolERC721,
assetPoolETH,
verifierHub,
relayerHub,
feeManager,
keyringManager,
merkleTreeOperator,
mimcBn254,
initialOwner
)
UniswapInputBuilder(P)
{
WETH_ADDRESS = wethAddress;
}
function _convertToWethIfNecessary(
address assetAddress,
uint256 amount
) internal returns (address) {
if (assetAddress == ETH_ADDRESS || assetAddress == address(0)) {
if (amount > 0) {
IWETH9(WETH_ADDRESS).deposit{value: amount}();
}
return WETH_ADDRESS;
}
return assetAddress;
}
function _convertToEthIfNecessary(
address assetAddress,
uint256 amount
) internal returns (address) {
if (assetAddress == WETH_ADDRESS) {
IWETH9(WETH_ADDRESS).withdraw(amount);
return ETH_ADDRESS;
}
return assetAddress;
}
function _transferETH(address to, uint256 amount) internal {
if (amount > 0) {
(bool success, ) = to.call{value: amount}("");
require(success, "transferETH: transfer failed");
}
}
function _transferERC20(
address token,
address to,
uint256 amount
) internal {
if (amount > 0) {
IERC20(token).safeTransfer(to, amount);
}
}
function _transferAsset(
address asset,
address to,
uint256 amount
) internal {
if (asset == ETH_ADDRESS || asset == address(0)) {
_transferETH(to, amount);
} else {
_transferERC20(asset, to, amount);
}
}
function _transferAssetToVault(
address assetAddress,
uint256 amount
) internal {
address transferTo = (assetAddress == ETH_ADDRESS ||
assetAddress == address(0))
? address(_assetPoolETH)
: address(_assetPoolERC20);
_transferAsset(assetAddress, transferTo, amount);
}
function _transferFundsToVaultWithFeesAndCreateNote(
address asset,
uint256 amount,
bytes32 noteFooter,
uint256 relayerGasFee,
address payable relayer
)
internal
returns (TransferFundsToVaultWithFeesAndCreateNoteData memory data)
{
data.normalizedAsset = _convertToEthIfNecessary(asset, amount);
(
data.actualAmount,
data.feesDetails.serviceFee,
data.feesDetails.relayerRefund
) = _feeManager.calculateFee(amount, relayerGasFee);
_chargeFees(data.normalizedAsset, relayer, data.feesDetails);
if (data.actualAmount > 0 ){
_transferAssetToVault(data.normalizedAsset, data.actualAmount);
data.noteCommitment = _buildNoteForERC20(
data.normalizedAsset,
data.actualAmount,
noteFooter
);
_postDeposit(bytes32(data.noteCommitment));
}
}
function _releaseAssetFromVaultWithoutFee(
address asset,
address to,
uint256 amount
) internal {
if (amount > 0) {
if (asset == ETH_ADDRESS || asset == address(0)) {
_assetPoolETH.release(payable(to), amount);
} else {
_assetPoolERC20.release(asset, to, amount);
}
}
}
function _releaseAndPackDetails(
FundReleaseDetails memory fundReleaseDetails
)
internal
returns (uint256 releasedAmount, FeesDetails memory feesDetails)
{
(
releasedAmount,
feesDetails.serviceFee,
feesDetails.relayerRefund
) = _releaseFunds(fundReleaseDetails);
}
function _chargeFees(
address asset,
address payable relayer,
FeesDetails memory feesDetails
) internal {
_transferAsset(asset, relayer, feesDetails.relayerRefund);
_transferAsset(asset, address(_feeManager), feesDetails.serviceFee);
}
function _chargeFeesFromVault(
address asset,
address payable relayer,
FeesDetails memory feesDetails
) internal {
_releaseAssetFromVaultWithoutFee(
asset,
relayer,
feesDetails.relayerRefund
);
_releaseAssetFromVaultWithoutFee(
asset,
address(_feeManager),
feesDetails.serviceFee
);
}
function _autosplit(
AutoSplitArgs memory args
) internal returns (AutoSplitDetails memory autoSplitDetails) {
require(
args.actualAmount >= args.desiredAmount,
"autosplit: actual amount is less than desired amount"
);
autoSplitDetails.changeAmount = args.actualAmount - args.desiredAmount;
autoSplitDetails.note = _buildNoteForERC20(
args.asset,
args.desiredAmount,
args.noteFooter
);
autoSplitDetails.changeNote = _buildNoteForERC20(
args.asset,
autoSplitDetails.changeAmount,
args.changeNoteFooter
);
_postWithdraw(args.nullifier);
_postDeposit(bytes32(autoSplitDetails.note));
_postDeposit(bytes32(autoSplitDetails.changeNote));
}
function _sortTokens(
address[2] memory tokens,
uint256[2] memory amounts
) internal pure returns (address[2] memory, uint256[2] memory, uint8[2] memory) {
if (uint256(uint160(tokens[0])) < uint256(uint160(tokens[1]))) {
return (tokens, amounts, [0, 1]);
}
return ([tokens[1], tokens[0]], [amounts[1], amounts[0]], [1, 0]);
}
function _sortAndConvertToWeth(
address[2] memory tokens,
uint256[2] memory amounts
)
internal
returns (
address[2] memory sortedTokens,
uint256[2] memory sortedAmounts,
uint8[2] memory originalIndices
)
{
address[2] memory wethedTokens = [
_convertToWethIfNecessary(tokens[0], amounts[0]),
_convertToWethIfNecessary(tokens[1], amounts[1])
];
(sortedTokens, sortedAmounts, originalIndices) = _sortTokens(wethedTokens, amounts);
}
}
文件 29 的 30:UniswapInputBuilder.sol
pragma solidity ^0.8.20;
import {BaseInputBuilder} from "../../core/base/BaseInputBuilder.sol";
contract UniswapInputBuilder is BaseInputBuilder {
struct UniswapSimpleSwapInputs {
bytes32 merkleRoot;
address assetIn;
uint256 amountIn;
bytes32 nullifierIn;
address assetOut;
bytes32 noteFooter;
uint24 poolFee;
uint256 amountOutMin;
address relayer;
}
struct UniswapCollectFeesInputs {
bytes32 merkleRoot;
address positionAddress;
uint256 tokenId;
bytes32 fee1NoteFooter;
bytes32 fee2NoteFooter;
address relayer;
}
struct UniswapLiquidityProvisionInputs {
bytes32 merkleRoot;
address asset1Address;
address asset2Address;
uint256 amount1;
uint256 amount2;
bytes32 nullifier1;
bytes32 nullifier2;
int24 tickMin;
int24 tickMax;
bytes32 noteFooter;
bytes32 changeNoteFooter1;
bytes32 changeNoteFooter2;
address relayer;
uint256 amount1Min;
uint256 amount2Min;
uint256 deadline;
uint24 poolFee;
}
struct UniswapRemoveLiquidityInputs {
bytes32 merkleRoot;
address positionAddress;
bytes32 positionNullifier;
uint256 tokenId;
bytes32 out1NoteFooter;
bytes32 out2NoteFooter;
address relayer;
uint256 amount1Min;
uint256 amount2Min;
uint256 deadline;
}
constructor(uint256 primeField) BaseInputBuilder(primeField) {}
function _buildUniswapSimpleSwapInputs(
UniswapSimpleSwapInputs memory _rawInputs
) internal view returns (bytes32[] memory) {
bytes32[] memory inputs = new bytes32[](9);
inputs[0] = _rawInputs.merkleRoot;
inputs[1] = _bytifyToNoir(_rawInputs.assetIn);
inputs[2] = bytes32(_rawInputs.amountIn);
inputs[3] = _rawInputs.nullifierIn;
inputs[4] = _bytifyToNoir(_rawInputs.assetOut);
inputs[5] = _rawInputs.noteFooter;
inputs[6] = bytes32(uint256(_rawInputs.poolFee));
inputs[7] = bytes32(_rawInputs.amountOutMin);
inputs[8] = _bytifyToNoir(_rawInputs.relayer);
return inputs;
}
function _buildUniswapCollectFeesInputs(
UniswapCollectFeesInputs memory _rawInputs
) internal pure returns (bytes32[] memory) {
bytes32[] memory inputs = new bytes32[](6);
inputs[0] = _rawInputs.merkleRoot;
inputs[1] = _bytifyToNoir(_rawInputs.positionAddress);
inputs[2] = bytes32(_rawInputs.tokenId);
inputs[3] = _rawInputs.fee1NoteFooter;
inputs[4] = _rawInputs.fee2NoteFooter;
inputs[5] = _bytifyToNoir(_rawInputs.relayer);
return inputs;
}
function _buildUniswapRemoveLiquidityInputs(
UniswapRemoveLiquidityInputs memory _rawInputs
) internal pure returns (bytes32[] memory) {
bytes32[] memory inputs = new bytes32[](10);
inputs[0] = _rawInputs.merkleRoot;
inputs[1] = _bytifyToNoir(_rawInputs.positionAddress);
inputs[2] = bytes32(_rawInputs.tokenId);
inputs[3] = _rawInputs.positionNullifier;
inputs[4] = _rawInputs.out1NoteFooter;
inputs[5] = _rawInputs.out2NoteFooter;
inputs[6] = bytes32(_rawInputs.deadline);
inputs[7] = _bytifyToNoir(_rawInputs.relayer);
inputs[8] = bytes32(_rawInputs.amount1Min);
inputs[9] = bytes32(_rawInputs.amount2Min);
return inputs;
}
function _buildUniswapLiquidityProvisionInputs(
UniswapLiquidityProvisionInputs memory _rawInputs
) internal pure returns (bytes32[] memory) {
bytes32[] memory inputs = new bytes32[](19);
inputs[0] = _rawInputs.merkleRoot;
inputs[1] = _bytifyToNoir(_rawInputs.asset1Address);
inputs[2] = _bytifyToNoir(_rawInputs.asset2Address);
inputs[3] = bytes32(_rawInputs.amount1);
inputs[4] = bytes32(_rawInputs.amount2);
inputs[5] = _int24ToBytes32(_abs(_rawInputs.tickMin));
inputs[6] = _int24ToBytes32(_abs(_rawInputs.tickMax));
inputs[7] = _boolToBytes32(_rawInputs.tickMin >= 0);
inputs[8] = _boolToBytes32(_rawInputs.tickMax >= 0);
inputs[9] = _rawInputs.nullifier1;
inputs[10] = _rawInputs.nullifier2;
inputs[11] = _rawInputs.noteFooter;
inputs[12] = _rawInputs.changeNoteFooter1;
inputs[13] = _rawInputs.changeNoteFooter2;
inputs[14] = _bytifyToNoir(_rawInputs.relayer);
inputs[15] = bytes32(_rawInputs.amount1Min);
inputs[16] = bytes32(_rawInputs.amount2Min);
inputs[17] = bytes32(_rawInputs.deadline);
inputs[18] = bytes32(uint256(_rawInputs.poolFee));
return inputs;
}
function _int24ToBytes32(
int24 value
) internal pure returns (bytes32 result) {
assembly {
result := value
}
}
function _boolToBytes32(bool value) public pure returns (bytes32) {
return value ? bytes32(uint256(1)) : bytes32(uint256(0));
}
function _abs(int24 value) internal pure returns (int24) {
return value < 0 ? -value : value;
}
}
文件 30 的 30:UniswapLiquidityAssetManager.sol
pragma solidity ^0.8.20;
import {UniswapCoreAssetManager} from "./UniswapCoreAssetManager.sol";
import {INonfungiblePositionManager} from "./interfaces/INonfungiblePositionManager.sol";
import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract UniswapLiquidityAssetManager is UniswapCoreAssetManager {
using SafeERC20 for IERC20;
struct UniswapLPData {
address token1;
address token2;
}
struct UniswapLiquidityProvisionArgs {
UniswapNoteData noteData1;
UniswapNoteData noteData2;
address payable relayer;
uint256[2] relayerGasFees;
bytes32 merkleRoot;
bytes32[2] changeNoteFooters;
int24 tickMin;
int24 tickMax;
uint256 deadline;
bytes32 positionNoteFooter;
uint24 poolFee;
uint256[2] amountsMin;
}
struct UniswapCollectFeesArgs {
bytes32 merkleRoot;
uint256 tokenId;
bytes32[2] feeNoteFooters;
uint256[2] relayerGasFees;
address payable relayer;
}
struct UniswapRemoveLiquidityArgs {
bytes32 merkleRoot;
UniswapNoteData positionNote;
bytes32[2] outNoteFooters;
uint256[2] relayerGasFees;
uint256 deadline;
address payable relayer;
uint256[2] amountsMin;
}
mapping(uint256 tokenId => UniswapLPData data) public uniswapLPData;
INonfungiblePositionManager public immutable nonfungiblePositionManager;
event UniswapLiquidityProvision(
uint256 tokenId,
bytes32 positionNote,
bytes32[2] nullifiers,
uint256[2] changeAmounts,
bytes32[2] changeNoteCommitments,
bytes32[2] changeNoteFooters
);
event UniswapCollectFees(
uint256 tokenId,
address[2] assets,
uint256[2] amounts,
bytes32[2] feeNoteCommitments,
bytes32[2] feeNoteFooters
);
event UniswapRemoveLiquidity(
uint256 tokenId,
bytes32 positionNullifier,
uint256[2] amounts,
bytes32[2] outNoteCommitments,
bytes32[2] outNoteFooters
);
constructor(
address assetPoolERC20,
address assetPoolERC721,
address assetPoolETH,
address verifierHub,
address relayerHub,
address feeManager,
address keyringManager,
address merkleTreeOperator,
address mimcBn254,
address initialOwner,
INonfungiblePositionManager _nonfungiblePositionManager,
address wethAddress
)
UniswapCoreAssetManager(
assetPoolERC20,
assetPoolERC721,
assetPoolETH,
verifierHub,
relayerHub,
feeManager,
keyringManager,
merkleTreeOperator,
mimcBn254,
initialOwner,
wethAddress
)
{
nonfungiblePositionManager = _nonfungiblePositionManager;
}
function uniswapLiquidityProvision(
UniswapLiquidityProvisionArgs memory args,
bytes calldata proof
) public returns (uint256 tokenId) {
_validateLiquidityProvisionArgs(args);
_verifyProofForLiquidityProvision(args, proof);
INonfungiblePositionManager.MintParams memory mintParams;
uint8[2] memory originalIndices;
(
mintParams,
originalIndices
) = _releaseFundsAndPrepareLiquidityProvisionArgs(args);
bytes32[2] memory changeNoteCommitments;
uint256[2] memory changeAmounts;
bytes32 positionNote;
(
changeNoteCommitments,
changeAmounts,
positionNote,
tokenId
) = _executeLPMint(args, mintParams, originalIndices);
emit UniswapLiquidityProvision(
tokenId,
positionNote,
[args.noteData1.nullifier, args.noteData2.nullifier],
[changeAmounts[originalIndices[0]], changeAmounts[originalIndices[1]]],
[changeNoteCommitments[originalIndices[0]], changeNoteCommitments[originalIndices[1]]],
args.changeNoteFooters
);
}
function uniswapCollectFees(
UniswapCollectFeesArgs memory args,
bytes calldata proof
)
public
returns (
TransferFundsToVaultWithFeesAndCreateNoteData memory dataToken1,
TransferFundsToVaultWithFeesAndCreateNoteData memory dataToken2
)
{
_validateCollectFeesArgs(args);
_verifyProofForCollectFees(args, proof);
_releaseERC721Position(args.tokenId);
_registerNoteFooter(args.feeNoteFooters[0]);
_registerNoteFooter(args.feeNoteFooters[1]);
(uint256 amount0, uint256 amount1) = nonfungiblePositionManager.collect(
_prepareCollectFeeParams(args.tokenId)
);
_transferERC721PositionToVault(args.tokenId);
(dataToken1) = _transferFundsToVaultWithFeesAndCreateNote(
uniswapLPData[args.tokenId].token1,
amount0,
args.feeNoteFooters[0],
args.relayerGasFees[0],
args.relayer
);
(dataToken2) = _transferFundsToVaultWithFeesAndCreateNote(
uniswapLPData[args.tokenId].token2,
amount1,
args.feeNoteFooters[1],
args.relayerGasFees[1],
args.relayer
);
emit UniswapCollectFees(
args.tokenId,
[uniswapLPData[args.tokenId].token1, uniswapLPData[args.tokenId].token2],
[dataToken1.actualAmount, dataToken2.actualAmount],
[dataToken1.noteCommitment, dataToken2.noteCommitment],
args.feeNoteFooters
);
}
function uniswapRemoveLiquidity(
UniswapRemoveLiquidityArgs memory args,
bytes calldata proof
)
public
returns (
TransferFundsToVaultWithFeesAndCreateNoteData memory dataToken1,
TransferFundsToVaultWithFeesAndCreateNoteData memory dataToken2
)
{
_validateRemoveLiquidityArgs(args);
_verifyProofForRemoveLiquidity(args, proof);
_postWithdraw(args.positionNote.nullifier);
_registerNoteFooter(args.outNoteFooters[0]);
_registerNoteFooter(args.outNoteFooters[1]);
_releaseERC721Position(args.positionNote.amount);
(
,
,
address token1,
address token2,
,
,
,
uint128 liquidity,
,
,
,
) = nonfungiblePositionManager.positions(args.positionNote.amount);
nonfungiblePositionManager.decreaseLiquidity(
_prepareRemoveLiquidityParams(args, liquidity)
);
(uint256 amount0, uint256 amount1) = nonfungiblePositionManager.collect(
_prepareCollectFeeParams(args.positionNote.amount)
);
_burnERC721Position(args.positionNote.amount);
(dataToken1) = _transferFundsToVaultWithFeesAndCreateNote(
token1,
amount0,
args.outNoteFooters[0],
args.relayerGasFees[0],
args.relayer
);
(dataToken2) = _transferFundsToVaultWithFeesAndCreateNote(
token2,
amount1,
args.outNoteFooters[1],
args.relayerGasFees[1],
args.relayer
);
emit UniswapRemoveLiquidity(
args.positionNote.amount,
args.positionNote.nullifier,
[dataToken1.actualAmount, dataToken2.actualAmount],
[dataToken1.noteCommitment, dataToken2.noteCommitment],
args.outNoteFooters
);
}
function _validateLiquidityProvisionArgs(
UniswapLiquidityProvisionArgs memory args
) internal view {
_validateMerkleRootIsAllowed(args.merkleRoot);
_validateNullifierIsNotUsed(args.noteData1.nullifier);
_validateNullifierIsNotUsed(args.noteData2.nullifier);
_validateNullifierIsNotLocked(args.noteData1.nullifier);
_validateNullifierIsNotLocked(args.noteData2.nullifier);
_validateNoteFooterIsNotUsed(args.positionNoteFooter);
_validateNoteFooterIsNotUsed(args.changeNoteFooters[0]);
_validateNoteFooterIsNotUsed(args.changeNoteFooters[1]);
_validateRelayerIsRegistered(args.relayer);
if(msg.sender != args.relayer) {
revert RelayerMismatch();
}
if(args.changeNoteFooters[0] == args.changeNoteFooters[1] ||
args.positionNoteFooter == args.changeNoteFooters[0] ||
args.positionNoteFooter == args.changeNoteFooters[1]) {
revert NoteFooterDuplicated();
}
}
function _validateCollectFeesArgs(
UniswapCollectFeesArgs memory args
) internal view {
_validateMerkleRootIsAllowed(args.merkleRoot);
_validateNoteFooterIsNotUsed(args.feeNoteFooters[0]);
_validateNoteFooterIsNotUsed(args.feeNoteFooters[1]);
_validateRelayerIsRegistered(args.relayer);
if(msg.sender != args.relayer) {
revert RelayerMismatch();
}
if(args.feeNoteFooters[0] == args.feeNoteFooters[1]) {
revert NoteFooterDuplicated();
}
}
function _validateRemoveLiquidityArgs(
UniswapRemoveLiquidityArgs memory args
) internal view {
_validateMerkleRootIsAllowed(args.merkleRoot);
_validateNullifierIsNotUsed(args.positionNote.nullifier);
_validateNullifierIsNotLocked(args.positionNote.nullifier);
_validateNoteFooterIsNotUsed(args.outNoteFooters[0]);
_validateNoteFooterIsNotUsed(args.outNoteFooters[1]);
_validateRelayerIsRegistered(args.relayer);
if(msg.sender != args.relayer) {
revert RelayerMismatch();
}
if (args.outNoteFooters[0] == args.outNoteFooters[1]) {
revert NoteFooterDuplicated();
}
}
function _verifyProofForLiquidityProvision(
UniswapLiquidityProvisionArgs memory args,
bytes calldata proof
) internal view {
UniswapLiquidityProvisionInputs memory inputs;
inputs.merkleRoot = args.merkleRoot;
inputs.asset1Address = args.noteData1.assetAddress;
inputs.asset2Address = args.noteData2.assetAddress;
inputs.amount1 = args.noteData1.amount;
inputs.amount2 = args.noteData2.amount;
inputs.nullifier1 = args.noteData1.nullifier;
inputs.nullifier2 = args.noteData2.nullifier;
inputs.noteFooter = args.positionNoteFooter;
inputs.tickMin = args.tickMin;
inputs.tickMax = args.tickMax;
inputs.changeNoteFooter1 = args.changeNoteFooters[0];
inputs.changeNoteFooter2 = args.changeNoteFooters[1];
inputs.relayer = args.relayer;
inputs.amount1Min = args.amountsMin[0];
inputs.amount2Min = args.amountsMin[1];
inputs.poolFee = args.poolFee;
inputs.deadline = args.deadline;
_verifyProof(
proof,
_buildUniswapLiquidityProvisionInputs(inputs),
"uniswapLiquidityProvision"
);
}
function _verifyProofForCollectFees(
UniswapCollectFeesArgs memory args,
bytes calldata proof
) internal view {
UniswapCollectFeesInputs memory inputs;
inputs.merkleRoot = args.merkleRoot;
inputs.positionAddress = address(nonfungiblePositionManager);
inputs.tokenId = args.tokenId;
inputs.fee1NoteFooter = args.feeNoteFooters[0];
inputs.fee2NoteFooter = args.feeNoteFooters[1];
inputs.relayer = args.relayer;
_verifyProof(
proof,
_buildUniswapCollectFeesInputs(inputs),
"uniswapCollectFees"
);
}
function _verifyProofForRemoveLiquidity(
UniswapRemoveLiquidityArgs memory args,
bytes calldata proof
) internal view {
UniswapRemoveLiquidityInputs memory inputs;
inputs.merkleRoot = args.merkleRoot;
inputs.positionAddress = address(nonfungiblePositionManager);
inputs.positionNullifier = args.positionNote.nullifier;
inputs.tokenId = args.positionNote.amount;
inputs.out1NoteFooter = args.outNoteFooters[0];
inputs.out2NoteFooter = args.outNoteFooters[1];
inputs.deadline = args.deadline;
inputs.relayer = args.relayer;
inputs.amount1Min = args.amountsMin[0];
inputs.amount2Min = args.amountsMin[1];
_verifyProof(
proof,
_buildUniswapRemoveLiquidityInputs(inputs),
"uniswapRemoveLiquidity"
);
}
function _executeLPMint(
UniswapLiquidityProvisionArgs memory args,
INonfungiblePositionManager.MintParams memory mintParams,
uint8[2] memory originalIndices
)
internal
returns (
bytes32[2] memory changeNoteCommitments,
uint256[2] memory changeAmounts,
bytes32 positionNote,
uint256 tokenId
)
{
uint256 mintedAmount0;
uint256 mintedAmount1;
_registerNoteFooter(args.positionNoteFooter);
_registerNoteFooter(args.changeNoteFooters[0]);
_registerNoteFooter(args.changeNoteFooters[1]);
(tokenId, , mintedAmount0, mintedAmount1) = nonfungiblePositionManager
.mint(mintParams);
(changeNoteCommitments, changeAmounts) = _handleChangeAfterUniswapLp(
mintParams,
[mintedAmount0, mintedAmount1],
args.changeNoteFooters,
originalIndices
);
uniswapLPData[tokenId] = UniswapLPData({
token1: mintParams.token0,
token2: mintParams.token1
});
positionNote = _buildNoteForERC721(
address(nonfungiblePositionManager),
tokenId,
args.positionNoteFooter
);
_transferERC721PositionToVault(tokenId);
_postDeposit(positionNote);
if (changeAmounts[0] > 0) {
_postDeposit(changeNoteCommitments[0]);
}
if (changeAmounts[1] > 0) {
_postDeposit(bytes32(changeNoteCommitments[1]));
}
}
function _handleChangeAfterUniswapLp(
INonfungiblePositionManager.MintParams memory mintParams,
uint256[2] memory actuallyMintedAmounts,
bytes32[2] memory noteFooters,
uint8[2] memory originalIndices
)
internal
returns (
bytes32[2] memory changeNoteCommitments,
uint256[2] memory changeAmounts
)
{
changeAmounts = [
mintParams.amount0Desired - actuallyMintedAmounts[0],
mintParams.amount1Desired - actuallyMintedAmounts[1]
];
address normalizedToken0 = _convertToEthIfNecessary(mintParams.token0, changeAmounts[0]);
address normalizedToken1 = _convertToEthIfNecessary(mintParams.token1, changeAmounts[1]);
_transferAssetToVault(normalizedToken0, changeAmounts[0]);
_transferAssetToVault(normalizedToken1, changeAmounts[1]);
if (changeAmounts[0] > 0) {
changeNoteCommitments[0] = _buildNoteForERC20(
normalizedToken0,
changeAmounts[0],
noteFooters[originalIndices[0]]
);
}
if (changeAmounts[1] > 0) {
changeNoteCommitments[1] = _buildNoteForERC20(
normalizedToken1,
changeAmounts[1],
noteFooters[originalIndices[1]]
);
}
}
function _releaseFundsAndPrepareLiquidityProvisionArgs(
UniswapLiquidityProvisionArgs memory args
)
internal
returns (
INonfungiblePositionManager.MintParams memory mintParams,
uint8[2] memory originalIndices
)
{
_postWithdraw(bytes32(args.noteData1.nullifier));
_postWithdraw(bytes32(args.noteData2.nullifier));
FundReleaseDetails memory fundReleaseDetails1;
fundReleaseDetails1.assetAddress = args.noteData1.assetAddress;
fundReleaseDetails1.recipient = payable(address(this));
fundReleaseDetails1.relayer = args.relayer;
fundReleaseDetails1.relayerGasFee = args.relayerGasFees[0];
fundReleaseDetails1.amount = args.noteData1.amount;
(
uint256 actualReleasedAmountToken1,
) = _releaseAndPackDetails(fundReleaseDetails1);
FundReleaseDetails memory fundReleaseDetails2;
fundReleaseDetails2.assetAddress = args.noteData2.assetAddress;
fundReleaseDetails2.recipient = payable(address(this));
fundReleaseDetails2.relayer = args.relayer;
fundReleaseDetails2.relayerGasFee = args.relayerGasFees[1];
fundReleaseDetails2.amount = args.noteData2.amount;
(
uint256 actualReleasedAmountToken2,
) = _releaseAndPackDetails(fundReleaseDetails2);
address[2] memory tokens;
uint256[2] memory amounts;
(
tokens,
amounts,
originalIndices
) = _sortAndConvertToWeth(
[args.noteData1.assetAddress, args.noteData2.assetAddress],
[actualReleasedAmountToken1, actualReleasedAmountToken2]
);
mintParams.token0 = tokens[0];
mintParams.token1 = tokens[1];
mintParams.fee = args.poolFee;
mintParams.tickLower = args.tickMin;
mintParams.tickUpper = args.tickMax;
mintParams.amount0Desired = amounts[0];
mintParams.amount1Desired = amounts[1];
mintParams.amount0Min = args.amountsMin[originalIndices[0]];
mintParams.amount1Min = args.amountsMin[originalIndices[1]];
mintParams.recipient = payable(address(this));
mintParams.deadline = args.deadline;
IERC20(mintParams.token0).forceApprove(
address(nonfungiblePositionManager),
mintParams.amount0Desired
);
IERC20(mintParams.token1).forceApprove(
address(nonfungiblePositionManager),
mintParams.amount1Desired
);
}
function _prepareCollectFeeParams(
uint256 tokenId
)
internal
view
returns (INonfungiblePositionManager.CollectParams memory collectParams)
{
collectParams.tokenId = tokenId;
collectParams.recipient = address(this);
collectParams.amount0Max = type(uint128).max;
collectParams.amount1Max = type(uint128).max;
}
function _prepareRemoveLiquidityParams(
UniswapRemoveLiquidityArgs memory args,
uint128 liquidity
)
internal
view
returns (
INonfungiblePositionManager.DecreaseLiquidityParams
memory decreaseLiquidityParams
)
{
decreaseLiquidityParams.tokenId = args.positionNote.amount;
decreaseLiquidityParams.liquidity = liquidity;
decreaseLiquidityParams.amount0Min = args.amountsMin[0];
decreaseLiquidityParams.amount1Min = args.amountsMin[1];
decreaseLiquidityParams.deadline = args.deadline;
}
function _releaseERC721Position(uint256 tokenId) internal {
_assetPoolERC721.release(
address(nonfungiblePositionManager),
address(this),
tokenId
);
}
function _transferERC721PositionToVault(uint256 tokenId) internal {
IERC721(address(nonfungiblePositionManager)).safeTransferFrom(
address(this),
address(_assetPoolERC721),
tokenId
);
}
function _burnERC721Position(uint256 tokenId) internal {
nonfungiblePositionManager.burn(tokenId);
}
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external pure returns (bytes4) {
return this.onERC721Received.selector;
}
}
{
"compilationTarget": {
"contracts/defi/uniswap/UniswapLiquidityAssetManager.sol": "UniswapLiquidityAssetManager"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 4000
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"assetPoolERC20","type":"address"},{"internalType":"address","name":"assetPoolERC721","type":"address"},{"internalType":"address","name":"assetPoolETH","type":"address"},{"internalType":"address","name":"verifierHub","type":"address"},{"internalType":"address","name":"relayerHub","type":"address"},{"internalType":"address","name":"feeManager","type":"address"},{"internalType":"address","name":"keyringManager","type":"address"},{"internalType":"address","name":"merkleTreeOperator","type":"address"},{"internalType":"address","name":"mimcBn254","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"contract INonfungiblePositionManager","name":"_nonfungiblePositionManager","type":"address"},{"internalType":"address","name":"wethAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidNoteParameters","type":"error"},{"inputs":[],"name":"MerkleRootNotAllowed","type":"error"},{"inputs":[],"name":"NoteAlreadyCreated","type":"error"},{"inputs":[],"name":"NoteFooterDuplicated","type":"error"},{"inputs":[],"name":"NoteFooterUsed","type":"error"},{"inputs":[],"name":"NullifierLocked","type":"error"},{"inputs":[],"name":"NullifierUsed","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"RelayerMismatch","type":"error"},{"inputs":[],"name":"RelayerNotRegistered","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"address[2]","name":"assets","type":"address[2]"},{"indexed":false,"internalType":"uint256[2]","name":"amounts","type":"uint256[2]"},{"indexed":false,"internalType":"bytes32[2]","name":"feeNoteCommitments","type":"bytes32[2]"},{"indexed":false,"internalType":"bytes32[2]","name":"feeNoteFooters","type":"bytes32[2]"}],"name":"UniswapCollectFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"positionNote","type":"bytes32"},{"indexed":false,"internalType":"bytes32[2]","name":"nullifiers","type":"bytes32[2]"},{"indexed":false,"internalType":"uint256[2]","name":"changeAmounts","type":"uint256[2]"},{"indexed":false,"internalType":"bytes32[2]","name":"changeNoteCommitments","type":"bytes32[2]"},{"indexed":false,"internalType":"bytes32[2]","name":"changeNoteFooters","type":"bytes32[2]"}],"name":"UniswapLiquidityProvision","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"positionNullifier","type":"bytes32"},{"indexed":false,"internalType":"uint256[2]","name":"amounts","type":"uint256[2]"},{"indexed":false,"internalType":"bytes32[2]","name":"outNoteCommitments","type":"bytes32[2]"},{"indexed":false,"internalType":"bytes32[2]","name":"outNoteFooters","type":"bytes32[2]"}],"name":"UniswapRemoveLiquidity","type":"event"},{"inputs":[],"name":"ASSET_ETH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"P","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"_boolToBytes32","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getAssetPoolERC20","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssetPoolERC721","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssetPoolETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getComplianceManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeManager","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMerkleTreeOperator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMimc254","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRelayerHub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getVerifierHub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonfungiblePositionManager","outputs":[{"internalType":"contract INonfungiblePositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"releaseToAsssetPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetPoolERC20","type":"address"}],"name":"setAssetPoolERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetPoolERC721","type":"address"}],"name":"setAssetPoolERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetPoolETH","type":"address"}],"name":"setAssetPoolETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"complianceManager","type":"address"}],"name":"setComplianceManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeManager","type":"address"}],"name":"setFeeManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"relayerHub","type":"address"}],"name":"setRelayerHub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"verifierHub","type":"address"}],"name":"setVerifierHub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32[2]","name":"feeNoteFooters","type":"bytes32[2]"},{"internalType":"uint256[2]","name":"relayerGasFees","type":"uint256[2]"},{"internalType":"address payable","name":"relayer","type":"address"}],"internalType":"struct UniswapLiquidityAssetManager.UniswapCollectFeesArgs","name":"args","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"uniswapCollectFees","outputs":[{"components":[{"internalType":"uint256","name":"actualAmount","type":"uint256"},{"internalType":"address","name":"normalizedAsset","type":"address"},{"internalType":"bytes32","name":"noteCommitment","type":"bytes32"},{"components":[{"internalType":"uint256","name":"serviceFee","type":"uint256"},{"internalType":"uint256","name":"relayerRefund","type":"uint256"}],"internalType":"struct UniswapCoreAssetManager.FeesDetails","name":"feesDetails","type":"tuple"}],"internalType":"struct UniswapCoreAssetManager.TransferFundsToVaultWithFeesAndCreateNoteData","name":"dataToken1","type":"tuple"},{"components":[{"internalType":"uint256","name":"actualAmount","type":"uint256"},{"internalType":"address","name":"normalizedAsset","type":"address"},{"internalType":"bytes32","name":"noteCommitment","type":"bytes32"},{"components":[{"internalType":"uint256","name":"serviceFee","type":"uint256"},{"internalType":"uint256","name":"relayerRefund","type":"uint256"}],"internalType":"struct UniswapCoreAssetManager.FeesDetails","name":"feesDetails","type":"tuple"}],"internalType":"struct UniswapCoreAssetManager.TransferFundsToVaultWithFeesAndCreateNoteData","name":"dataToken2","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"uniswapLPData","outputs":[{"internalType":"address","name":"token1","type":"address"},{"internalType":"address","name":"token2","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"nullifier","type":"bytes32"}],"internalType":"struct UniswapCoreAssetManager.UniswapNoteData","name":"noteData1","type":"tuple"},{"components":[{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"nullifier","type":"bytes32"}],"internalType":"struct UniswapCoreAssetManager.UniswapNoteData","name":"noteData2","type":"tuple"},{"internalType":"address payable","name":"relayer","type":"address"},{"internalType":"uint256[2]","name":"relayerGasFees","type":"uint256[2]"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bytes32[2]","name":"changeNoteFooters","type":"bytes32[2]"},{"internalType":"int24","name":"tickMin","type":"int24"},{"internalType":"int24","name":"tickMax","type":"int24"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes32","name":"positionNoteFooter","type":"bytes32"},{"internalType":"uint24","name":"poolFee","type":"uint24"},{"internalType":"uint256[2]","name":"amountsMin","type":"uint256[2]"}],"internalType":"struct UniswapLiquidityAssetManager.UniswapLiquidityProvisionArgs","name":"args","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"uniswapLiquidityProvision","outputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"components":[{"internalType":"address","name":"assetAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"nullifier","type":"bytes32"}],"internalType":"struct UniswapCoreAssetManager.UniswapNoteData","name":"positionNote","type":"tuple"},{"internalType":"bytes32[2]","name":"outNoteFooters","type":"bytes32[2]"},{"internalType":"uint256[2]","name":"relayerGasFees","type":"uint256[2]"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address payable","name":"relayer","type":"address"},{"internalType":"uint256[2]","name":"amountsMin","type":"uint256[2]"}],"internalType":"struct UniswapLiquidityAssetManager.UniswapRemoveLiquidityArgs","name":"args","type":"tuple"},{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"uniswapRemoveLiquidity","outputs":[{"components":[{"internalType":"uint256","name":"actualAmount","type":"uint256"},{"internalType":"address","name":"normalizedAsset","type":"address"},{"internalType":"bytes32","name":"noteCommitment","type":"bytes32"},{"components":[{"internalType":"uint256","name":"serviceFee","type":"uint256"},{"internalType":"uint256","name":"relayerRefund","type":"uint256"}],"internalType":"struct UniswapCoreAssetManager.FeesDetails","name":"feesDetails","type":"tuple"}],"internalType":"struct UniswapCoreAssetManager.TransferFundsToVaultWithFeesAndCreateNoteData","name":"dataToken1","type":"tuple"},{"components":[{"internalType":"uint256","name":"actualAmount","type":"uint256"},{"internalType":"address","name":"normalizedAsset","type":"address"},{"internalType":"bytes32","name":"noteCommitment","type":"bytes32"},{"components":[{"internalType":"uint256","name":"serviceFee","type":"uint256"},{"internalType":"uint256","name":"relayerRefund","type":"uint256"}],"internalType":"struct UniswapCoreAssetManager.FeesDetails","name":"feesDetails","type":"tuple"}],"internalType":"struct UniswapCoreAssetManager.TransferFundsToVaultWithFeesAndCreateNoteData","name":"dataToken2","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]