Skip to main content

JBBuybackDelegate

Git Source

Inherits: Ownable, ERC165, JBDelegateMetadataHelper, IJBFundingCycleDataSource3_1_1, IJBPayDelegate3_1_1, IUniswapV3SwapCallback

Datasource and delegate allowing pay beneficiary to get the highest amount of project tokens between minting using the project weigh and swapping in a given Uniswap V3 pool.

This only supports ETH terminal. The pool is fixed, if a new pool offers deeper liquidity, this delegate needs to be redeployed.

State Variables​

PROJECT_TOKEN_IS_TOKEN0​

Address project token < address terminal token ?

bool immutable PROJECT_TOKEN_IS_TOKEN0;

SLIPPAGE_DENOMINATOR​

The unit of the max slippage (expressed in 1/10000th)

uint256 constant SLIPPAGE_DENOMINATOR = 10000;

PROJECT_TOKEN​

The project token address

In this context, this is the tokenOut

IERC20 public immutable PROJECT_TOKEN;

POOL​

The uniswap pool corresponding to the project token-other token market (this should be carefully chosen liquidity wise)

IUniswapV3Pool public immutable POOL;

DIRECTORY​

The JB Directory

IJBDirectory public immutable DIRECTORY;

CONTROLLER​

The project controller

IJBController3_1 public immutable CONTROLLER;

WETH​

The WETH contract

IWETH9 public immutable WETH;

delegateId​

The 4bytes ID of this delegate, used for metadata parsing

bytes4 public immutable delegateId;

secondsAgo​

uint32 public secondsAgo;

twapDelta​

uint256 public twapDelta;

sweepBalanceOf​

mapping(address => uint256) public sweepBalanceOf;

sweepBalance​

uint256 public sweepBalance;

Functions​

constructor​

No other logic besides initializing the immutables

constructor(
IERC20 _projectToken,
IWETH9 _weth,
address _factory,
uint24 _fee,
uint32 _secondsAgo,
uint256 _twapDelta,
IJBDirectory _directory,
IJBController3_1 _controller,
bytes4 _delegateId
);

payParams​

The datasource implementation

function payParams(JBPayParamsData calldata _data)
external
view
override
returns (uint256 weight, string memory memo, JBPayDelegateAllocation3_1_1[] memory delegateAllocations);

Parameters

NameTypeDescription
_dataJBPayParamsDatathe data passed to the data source in terminal.pay(..). _data.metadata need to have the Uniswap quote this quote should be set as 0 if the user wants to use the vanilla minting path

Returns

NameTypeDescription
weightuint256the weight to use (the one passed if not max reserved rate, 0 if swapping or the one corresponding to the reserved token to mint if minting)
memostringthe original memo passed
delegateAllocationsJBPayDelegateAllocation3_1_1[]The amount to send to delegates instead of adding to the local balance.

didPay​

Delegate to either swap to the beneficiary or mint to the beneficiary

This delegate is called only if the quote for the swap is bigger than the lowest received when minting. If the swap reverts (slippage, liquidity, etc), the delegate will then mint the same amount of token as if the delegate was not used. If the beneficiary requests non claimed token, the swap is not used (as it is, per definition, claimed token)

function didPay(JBDidPayData3_1_1 calldata _data) external payable override;

Parameters

NameTypeDescription
_dataJBDidPayData3_1_1the delegate data passed by the terminal

uniswapV3SwapCallback​

The Uniswap V3 pool callback (where token transfer should happens)

Slippage controle is achieved here

function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external override;

redeemParams​

Generic redeem params, for interface completion

This is a passthrough of the redemption parameters

function redeemParams(JBRedeemParamsData calldata _data)
external
pure
override
returns (
uint256 reclaimAmount,
string memory memo,
JBRedemptionDelegateAllocation3_1_1[] memory delegateAllocations
);

Parameters

NameTypeDescription
_dataJBRedeemParamsDatathe redeem data passed by the terminal

increaseSecondsAgo​

Increase the period over which the twap is computed

function increaseSecondsAgo(uint32 _newSecondsAgo) external onlyOwner;

Parameters

NameTypeDescription
_newSecondsAgouint32the new period

setTwapDelta​

Set the maximum deviation allowed between amount received and twap

function setTwapDelta(uint256 _newDelta) external onlyOwner;

Parameters

NameTypeDescription
_newDeltauint256the new delta, in 10_000th

sweep​

Sweep the eth left-over in this contract

function sweep(address _beneficiary) external;

_getQuote​

Get a quote based on twap over a secondsAgo period, taking into account a twapDelta max deviation

function _getQuote(uint256 _amountIn) internal view returns (uint256 _amountOut);

Parameters

NameTypeDescription
_amountInuint256the amount to swap

Returns

NameTypeDescription
_amountOutuint256the minimum amount received according to the twap

_swap​

Swap the terminal token to receive the project token _beforeTransfer

  1. This delegate first receive the whole amount of project token,
  2. then send the non-reserved token to the beneficiary,
  3. then burn the rest of this delegate balance (ie the amount of reserved token),
  4. then mint the same amount as received (this will add the reserved token, following the fc rate)
  5. then burn the difference (ie this delegate balance)

-> End result is having the correct balances (beneficiary and reserve), according to the reserve rate

function _swap(JBDidPayData3_1_1 calldata _data, uint256 _minimumReceivedFromSwap)
internal
returns (uint256 _amountReceived);

Parameters

NameTypeDescription
_dataJBDidPayData3_1_1the didPayData passed by the terminal
_minimumReceivedFromSwapuint256the minimum amount received, to prevent slippage

_mint​

Mint the token out, sending back the token in the terminal

function _mint(JBDidPayData3_1_1 calldata _data, uint256 _amount) internal;

Parameters

NameTypeDescription
_dataJBDidPayData3_1_1the didPayData passed by the terminal
_amountuint256the amount of token out to mint

supportsInterface​

function supportsInterface(bytes4 _interfaceId) public view override(ERC165, IERC165) returns (bool);

Events​

BuybackDelegate_Swap​

event BuybackDelegate_Swap(uint256 projectId, uint256 amountEth, uint256 amountOut);

BuybackDelegate_Mint​

event BuybackDelegate_Mint(uint256 projectId);

BuybackDelegate_SecondsAgoIncrease​

event BuybackDelegate_SecondsAgoIncrease(uint256 oldSecondsAgo, uint256 newSecondsAgo);

BuybackDelegate_TwapDeltaChanged​

event BuybackDelegate_TwapDeltaChanged(uint256 oldTwapDelta, uint256 newTwapDelta);

BuybackDelegate_PendingSweep​

event BuybackDelegate_PendingSweep(address indexed beneficiary, uint256 amount);

Errors​

JuiceBuyback_Unauthorized​

error JuiceBuyback_Unauthorized();

JuiceBuyback_MaximumSlippage​

error JuiceBuyback_MaximumSlippage();

JuiceBuyback_NewSecondsAgoTooLow​

error JuiceBuyback_NewSecondsAgoTooLow();

JuiceBuyback_TransferFailed​

error JuiceBuyback_TransferFailed();