Technical Reference
V3FactoryOwner.sol

V3FactoryOwner

Git Source (opens in a new tab)

Author: ScopeLift (opens in a new tab)

A contract that can serve as the owner of the Uniswap v3 Factory. This contract itself has an admin. That admin retains the exclusive right to call privileged methods on the v3 Factory, and on pools which it has deployed, via passthrough methods. This includes the ability to enable fee amounts on the factory, and set protocol fees on individual pools. The admin can also set a new admin. One privileged function that is not reserved exclusively for the admin is the ability to collect protocol fees from a pool. This method is instead exposed publicly by this contract's claimFees method. That method collects fees from the protocol as long as the caller pays for them with a transfer of a designated amount of a designated token. That payout is forwarded to a REWARD_RECEIVER. In the context of the broader system, if it is adopted by Uniswap Governance via a successful governance proposal, it is expected that:

  • Governance will transfer ownership of the Factory to an instance of this contract
  • this contract's REWARD_RECEIVER is a deployment of the UniStaker contract
  • the admin of this contract will be the Uniswap Governance timelock

Further, is it expected that:

  • subsequent proposals will turn on protocol fees for select pools
  • a competitive market of seekers will emerge racing to "buy" the fees for an arbitrage opportunity.

State Variables

FACTORY

The instance of the Uniswap v3 factory contract which this contract will own.

IUniswapV3FactoryOwnerActions public immutable FACTORY;

PAYOUT_TOKEN

The ERC-20 token which must be used to pay for fees when claiming pool fees.

IERC20 public immutable PAYOUT_TOKEN;

payoutAmount

The raw amount of the payout token which is paid by a user when claiming pool fees.

uint256 public payoutAmount;

REWARD_RECEIVER

The contract that receives the payout and is notified via method call, when pool fees are claimed.

INotifiableRewardReceiver public immutable REWARD_RECEIVER;

admin

The address that can call privileged methods, including passthrough owner functions to the factory itself.

address public admin;

Functions

constructor

constructor(
  address _admin,
  IUniswapV3FactoryOwnerActions _factory,
  IERC20 _payoutToken,
  uint256 _payoutAmount,
  INotifiableRewardReceiver _rewardReceiver
);

Parameters

NameTypeDescription
_adminaddressThe initial admin address for this deployment. Cannot be zero address.
_factoryIUniswapV3FactoryOwnerActionsThe v3 factory instance for which this deployment will serve as owner.
_payoutTokenIERC20The ERC-20 token in which payouts will be denominated.
_payoutAmountuint256The initial raw amount of the payout token required to claim fees from a pool.
_rewardReceiverINotifiableRewardReceiverThe contract that will receive the payout when fees are claimed.

setAdmin

Pass the admin role to a new address. Must be called by the existing admin.

function setAdmin(address _newAdmin) external;

Parameters

NameTypeDescription
_newAdminaddressThe address that will be the admin after this call completes.

setPayoutAmount

Update the payout amount to a new value. Must be called by admin.

function setPayoutAmount(uint256 _newPayoutAmount) external;

Parameters

NameTypeDescription
_newPayoutAmountuint256The value that will be the new payout amount.

enableFeeAmount

Passthrough method that enables a fee amount on the factory. Must be called by the admin.

See docs on IUniswapV3FactoryOwnerActions for more information on forwarded params.

function enableFeeAmount(uint24 _fee, int24 _tickSpacing) external;

Parameters

NameTypeDescription
_feeuint24The fee param to forward to the factory.
_tickSpacingint24The tick spacing param to forward to the factory.

setFeeProtocol

Passthrough method that sets the protocol fee on a v3 pool. Must be called by the admin.

See docs on IUniswapV3PoolOwnerActions for more information on forwarded params.

function setFeeProtocol(IUniswapV3PoolOwnerActions _pool, uint8 _feeProtocol0, uint8 _feeProtocol1)
  external;

Parameters

NameTypeDescription
_poolIUniswapV3PoolOwnerActionsThe Uniswap v3 pool on which the protocol fee is being set.
_feeProtocol0uint8The fee protocol 0 param to forward to the pool.
_feeProtocol1uint8The fee protocol 1 parm to forward to the pool.

claimFees

Public method that allows any caller to claim the protocol fees accrued by a given Uniswap v3 pool contract. Caller must pre-approve this factory owner contract on the payout token contract for at least the payout amount, which is transferred from the caller to the reward receiver. The reward receiver is "notified" of the payout via a method call. The protocol fees collected are sent to a receiver of the caller's specification. A quick example can help illustrate why an external party, such as an MEV searcher, would be incentivized to call this method. Imagine, purely for the sake of example, that protocol fees have been activated for the USDC/USDT stablecoin v3 pool. Imagine also the payout token and payout amount are WETH and 10e18 respectively. Finally, assume the spot USD price of ETH is $2,500, and both stablecoins are trading at their $1 peg. As regular users trade against the USDC/USDT pool, protocol fees amass in the pool contract in both stablecoins. Once the fees in the pool total more than 25,000 in stablecoins, it becomes profitable for an external party to arbitrage the fees by calling this method, paying 10 WETH (worth $25K) and getting more than $25K worth of stablecoins. (This ignores other details, which real searchers would take into consideration, such as the gas/builder fee they would pay to call the method). The same mechanic applies regardless of what the pool currencies, payout token, or payout amount are. Effectively, as each pool accrues fees, it eventually becomes possible to "buy" the pool fees for less than they are valued by "paying" the the payout amount of the payout token.

See docs on IUniswapV3PoolOwnerActions for more information on forwarded params.

function claimFees(
  IUniswapV3PoolOwnerActions _pool,
  address _recipient,
  uint128 _amount0Requested,
  uint128 _amount1Requested
) external returns (uint128, uint128);

Parameters

NameTypeDescription
_poolIUniswapV3PoolOwnerActionsThe Uniswap v3 pool contract from which protocol fees are being collected.
_recipientaddressThe address to which collected protocol fees will be transferred.
_amount0Requesteduint128The amount0Requested param to forward to the pool's collectProtocol method.
_amount1Requesteduint128The amount1Requested param to forward to the pool's collectProtocol method.

Returns

NameTypeDescription
<none>uint128_amount0 The amount0 fees collected, returned by the pool's collectProtocol method.
<none>uint128_amount1 The amount1 fees collected, returned by the pool's collectProtocol method.

_revertIfNotAdmin

Ensures the msg.sender is the contract admin and reverts otherwise.

Place inside external methods to make them admin-only.

function _revertIfNotAdmin() internal view;

Events

FeesClaimed

Emitted when a user pays the payout and claims the fees from a given v3 pool.

event FeesClaimed(
  address indexed pool,
  address indexed caller,
  address indexed recipient,
  uint256 amount0,
  uint256 amount1
);

Parameters

NameTypeDescription
pooladdressThe v3 pool from which protocol fees were claimed.
calleraddressThe address which executes the call to claim the fees.
recipientaddressThe address to which the claimed pool fees are sent.
amount0uint256The raw amount of token0 fees claimed from the pool.
amount1uint256The raw amount token1 fees claimed from the pool.

AdminSet

Emitted when the existing admin designates a new address as the admin.

event AdminSet(address indexed oldAmin, address indexed newAdmin);

PayoutAmountSet

Emitted when the admin updates the payout amount.

event PayoutAmountSet(uint256 indexed oldPayoutAmount, uint256 indexed newPayoutAmount);

Errors

V3FactoryOwner__Unauthorized

Thrown when an unauthorized account calls a privileged function.

error V3FactoryOwner__Unauthorized();

V3FactoryOwner__InvalidAddress

Thrown if the proposed admin is the zero address.

error V3FactoryOwner__InvalidAddress();

V3FactoryOwner__InvalidPayoutAmount

Thrown if the proposed payout amount is zero.

error V3FactoryOwner__InvalidPayoutAmount();

V3FactoryOwner__InsufficientFeesCollected

Thrown when the fees collected from a pool are less than the caller expects.

error V3FactoryOwner__InsufficientFeesCollected();