Skip to main content

Gate

GitHub: link

Gate is the main contract users interact with to mint/burn NegativeYieldToken and PerpetualYieldToken, as well as claim the yield earned by PYTs.

Gate is an abstract contract that should be inherited from in order to support a specific vault protocol (e.g. YearnGate supports YearnVault). Each Gate handles all vaults & associated NYTs/PYTs of a specific vault protocol. Vaults are yield-generating contracts used by Gate. Gate makes several assumptions about a vault: 1) A vault has a single associated underlying token that is immutable. 2) A vault gives depositors yield denominated in the underlying token. 3) A vault depositor owns shares in the vault, which represents their deposit. 4) Vaults have a notion of "price per share", which is the amount of underlying tokens each vault share can be redeemed for. 5) If vault shares are represented using an ERC20 token, then the ERC20 token contract must be the vault contract itself.

Errors

Error_InvalidInput

error Error_InvalidInput()

Error_VaultSharesNotERC20

error Error_VaultSharesNotERC20()

Error_TokenPairNotDeployed

error Error_TokenPairNotDeployed()

Error_EmergencyExitNotActivated

error Error_EmergencyExitNotActivated()

Error_SenderNotPerpetualYieldToken

error Error_SenderNotPerpetualYieldToken()

Error_EmergencyExitAlreadyActivated

error Error_EmergencyExitAlreadyActivated()

Events

EnterWithUnderlying

event EnterWithUnderlying(address sender, address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT, uint256 underlyingAmount)

EnterWithVaultShares

event EnterWithVaultShares(address sender, address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT, uint256 vaultSharesAmount)

ExitToUnderlying

event ExitToUnderlying(address sender, address recipient, address vault, contract IxPYT xPYT, uint256 underlyingAmount)

ExitToVaultShares

event ExitToVaultShares(address sender, address recipient, address vault, contract IxPYT xPYT, uint256 vaultSharesAmount)

ClaimYieldInUnderlying

event ClaimYieldInUnderlying(address sender, address recipient, address vault, uint256 underlyingAmount)

ClaimYieldInVaultShares

event ClaimYieldInVaultShares(address sender, address recipient, address vault, uint256 vaultSharesAmount)

ClaimYieldAndEnter

event ClaimYieldAndEnter(address sender, address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT, uint256 amount)

Structs

EmergencyExitStatus

struct EmergencyExitStatus {
bool activated;
uint96 pytPriceInUnderlying;
}

Constants

PRECISION_DECIMALS

uint256 PRECISION_DECIMALS

The decimals of precision used by yieldPerTokenStored and pricePerVaultShareStored

PRECISION

uint256 PRECISION

The precision used by yieldPerTokenStored and pricePerVaultShareStored

Immutable parameters

factory

contract Factory factory

State variables

pricePerVaultShareStored

mapping(address => uint256) pricePerVaultShareStored

The amount of underlying tokens each vault share is worth, at the time of the last update. Uses PRECISION.

vault => value

yieldPerTokenStored

mapping(address => uint256) yieldPerTokenStored

The amount of yield each PYT has accrued, at the time of the last update. Scaled by PRECISION.

vault => value

userYieldPerTokenStored

mapping(address => mapping(address => uint256)) userYieldPerTokenStored

The amount of yield each PYT has accrued, at the time when a user has last interacted with the gate/PYT. Shifted by 1, so e.g. 3 represents 2, 10 represents 9.

vault => user => value The value is shifted to use 0 for representing uninitialized users.

userAccruedYield

mapping(address => mapping(address => uint256)) userAccruedYield

The amount of yield a user has accrued, at the time when they last interacted with the gate/PYT (without calling claimYieldInUnderlying()). Shifted by 1, so e.g. 3 represents 2, 10 represents 9.

vault => user => value

emergencyExitStatusOfVault

mapping(address => struct Gate.EmergencyExitStatus) emergencyExitStatusOfVault

Stores info relevant to emergency exits of a vault.

vault => value

State-mutating functions

enterWithUnderlying

function enterWithUnderlying(address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT, uint256 underlyingAmount) external virtual returns (uint256 mintAmount)

Converts underlying tokens into NegativeYieldToken and PerpetualYieldToken. The amount of NYT and PYT minted will be equal to the underlying token amount.

The underlying tokens will be immediately deposited into the specified vault. If the NYT and PYT for the specified vault haven't been deployed yet, this call will deploy them before proceeding, which will increase the gas cost significantly.

NameTypeDescription
nytRecipientaddressThe recipient of the minted NYT
pytRecipientaddressThe recipient of the minted PYT
vaultaddressThe vault to mint NYT and PYT for
xPYTcontract IxPYTThe xPYT contract to deposit the minted PYT into. Set to 0 to receive raw PYT instead.
underlyingAmountuint256The amount of underlying tokens to use
NameTypeDescription
mintAmountuint256The amount of NYT and PYT minted (the amounts are equal)

enterWithVaultShares

function enterWithVaultShares(address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT, uint256 vaultSharesAmount) external virtual returns (uint256 mintAmount)

Converts vault share tokens into NegativeYieldToken and PerpetualYieldToken.

Only available if vault shares are transferrable ERC20 tokens. If the NYT and PYT for the specified vault haven't been deployed yet, this call will deploy them before proceeding, which will increase the gas cost significantly.

NameTypeDescription
nytRecipientaddressThe recipient of the minted NYT
pytRecipientaddressThe recipient of the minted PYT
vaultaddressThe vault to mint NYT and PYT for
xPYTcontract IxPYTThe xPYT contract to deposit the minted PYT into. Set to 0 to receive raw PYT instead.
vaultSharesAmountuint256The amount of vault share tokens to use
NameTypeDescription
mintAmountuint256The amount of NYT and PYT minted (the amounts are equal)

exitToUnderlying

function exitToUnderlying(address recipient, address vault, contract IxPYT xPYT, uint256 underlyingAmount) external virtual returns (uint256 burnAmount)

Converts NegativeYieldToken and PerpetualYieldToken to underlying tokens. The amount of NYT and PYT burned will be equal to the underlying token amount.

The underlying tokens will be immediately withdrawn from the specified vault. If the NYT and PYT for the specified vault haven't been deployed yet, this call will revert.

NameTypeDescription
recipientaddressThe recipient of the minted NYT and PYT
vaultaddressThe vault to mint NYT and PYT for
xPYTcontract IxPYTThe xPYT contract to use for burning PYT. Set to 0 to burn raw PYT instead.
underlyingAmountuint256The amount of underlying tokens requested
NameTypeDescription
burnAmountuint256The amount of NYT and PYT burned (the amounts are equal)

exitToVaultShares

function exitToVaultShares(address recipient, address vault, contract IxPYT xPYT, uint256 vaultSharesAmount) external virtual returns (uint256 burnAmount)

Converts NegativeYieldToken and PerpetualYieldToken to vault share tokens. The amount of NYT and PYT burned will be equal to the underlying token amount.

Only available if vault shares are transferrable ERC20 tokens. If the NYT and PYT for the specified vault haven't been deployed yet, this call will revert.

NameTypeDescription
recipientaddressThe recipient of the minted NYT and PYT
vaultaddressThe vault to mint NYT and PYT for
xPYTcontract IxPYTThe xPYT contract to use for burning PYT. Set to 0 to burn raw PYT instead.
vaultSharesAmountuint256The amount of vault share tokens requested
NameTypeDescription
burnAmountuint256The amount of NYT and PYT burned (the amounts are equal)

claimYieldInUnderlying

function claimYieldInUnderlying(address recipient, address vault) external virtual returns (uint256 yieldAmount)

Claims the yield earned by the PerpetualYieldToken balance of msg.sender, in the underlying token.

If the NYT and PYT for the specified vault haven't been deployed yet, this call will revert.

NameTypeDescription
recipientaddressThe recipient of the yield
vaultaddressThe vault to claim yield from
NameTypeDescription
yieldAmountuint256The amount of yield claimed, in underlying tokens

claimYieldInVaultShares

function claimYieldInVaultShares(address recipient, address vault) external virtual returns (uint256 yieldAmount)

Claims the yield earned by the PerpetualYieldToken balance of msg.sender, in vault shares.

Only available if vault shares are transferrable ERC20 tokens. If the NYT and PYT for the specified vault haven't been deployed yet, this call will revert.

NameTypeDescription
recipientaddressThe recipient of the yield
vaultaddressThe vault to claim yield from
NameTypeDescription
yieldAmountuint256The amount of yield claimed, in vault shares

claimYieldAndEnter

function claimYieldAndEnter(address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT) external virtual returns (uint256 yieldAmount)

Claims the yield earned by the PerpetualYieldToken balance of msg.sender, and immediately use the yield to mint NYT and PYT.

Introduced to save gas for xPYT compounding, since it avoids vault withdraws/transfers. If the NYT and PYT for the specified vault haven't been deployed yet, this call will revert.

NameTypeDescription
nytRecipientaddressThe recipient of the minted NYT
pytRecipientaddressThe recipient of the minted PYT
vaultaddressThe vault to claim yield from
xPYTcontract IxPYTThe xPYT contract to deposit the minted PYT into. Set to 0 to receive raw PYT instead.
NameTypeDescription
yieldAmountuint256The amount of yield claimed, in underlying tokens

View functions

getNegativeYieldTokenForVault

function getNegativeYieldTokenForVault(address vault) public view virtual returns (contract NegativeYieldToken)

Returns the NegativeYieldToken associated with a vault.

Returns non-zero value even if the contract hasn't been deployed yet.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]contract NegativeYieldTokenThe NegativeYieldToken address

getPerpetualYieldTokenForVault

function getPerpetualYieldTokenForVault(address vault) public view virtual returns (contract PerpetualYieldToken)

Returns the PerpetualYieldToken associated with a vault.

Returns non-zero value even if the contract hasn't been deployed yet.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]contract PerpetualYieldTokenThe PerpetualYieldToken address

getClaimableYieldAmount

function getClaimableYieldAmount(address vault, address user) external view virtual returns (uint256 yieldAmount)

Returns the amount of yield claimable by a PerpetualYieldToken holder from a vault. Accounts for protocol fees.

NameTypeDescription
vaultaddressThe vault to query
useraddressThe PYT holder to query
NameTypeDescription
yieldAmountuint256The amount of yield claimable

computeYieldPerToken

function computeYieldPerToken(address vault) external view virtual returns (uint256)

Computes the latest yieldPerToken value for a vault.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]uint256The latest yieldPerToken value

getUnderlyingOfVault

function getUnderlyingOfVault(address vault) public view virtual returns (contract ERC20)

Returns the underlying token of a vault.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]contract ERC20The underlying token

getPricePerVaultShare

function getPricePerVaultShare(address vault) public view virtual returns (uint256)

Returns the amount of underlying tokens each share of a vault is worth.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]uint256The pricePerVaultShare value

getVaultShareBalance

function getVaultShareBalance(address vault) public view virtual returns (uint256)

Returns the amount of vault shares owned by the gate.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]uint256The gate's vault share balance

vaultSharesIsERC20

function vaultSharesIsERC20() public pure virtual returns (bool)
NameTypeDescription
[0]boolTrue if the vaults supported by this gate use transferrable ERC20 tokens to represent shares, false otherwise.

negativeYieldTokenName

function negativeYieldTokenName(address vault) external view virtual returns (string)

Computes the ERC20 name of the NegativeYieldToken of a vault.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]stringThe ERC20 name

negativeYieldTokenSymbol

function negativeYieldTokenSymbol(address vault) external view virtual returns (string)

Computes the ERC20 symbol of the NegativeYieldToken of a vault.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]stringThe ERC20 symbol

perpetualYieldTokenName

function perpetualYieldTokenName(address vault) external view virtual returns (string)

Computes the ERC20 name of the PerpetualYieldToken of a vault.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]stringThe ERC20 name

perpetualYieldTokenSymbol

function perpetualYieldTokenSymbol(address vault) external view virtual returns (string)

Computes the ERC20 symbol of the NegativeYieldToken of a vault.

NameTypeDescription
vaultaddressThe vault to query
NameTypeDescription
[0]stringThe ERC20 symbol

beforePerpetualYieldTokenTransfer

function beforePerpetualYieldTokenTransfer(address from, address to, uint256 amount, uint256 fromBalance, uint256 toBalance) external virtual

SHOULD NOT BE CALLED BY USERS, ONLY CALLED BY PERPETUAL YIELD TOKEN CONTRACTS

Called by PYT contracts deployed by this gate before each token transfer, in order to accrue the yield earned by the from & to accounts

NameTypeDescription
fromaddressThe token transfer from account
toaddressThe token transfer to account
amountuint256
fromBalanceuint256The token balance of the from account before the transfer
toBalanceuint256The token balance of the to account before the transfer

Emergency exit functions

ownerActivateEmergencyExitForVault

function ownerActivateEmergencyExitForVault(address vault, uint96 pytPriceInUnderlying) external virtual

Activates the emergency exit mode for a certain vault. Only callable by owner.

Activating emergency exit allows PYT/NYT holders to do single-sided burns to redeem the underlying collateral. This is to prevent cases where a large portion of PYT/NYT is locked up in a buggy/malicious contract and locks up the underlying collateral forever.

NameTypeDescription
vaultaddressThe vault to activate emergency exit for
pytPriceInUnderlyinguint96The amount of underlying asset burning each PYT can redeem. Scaled by PRECISION.

ownerDeactivateEmergencyExitForVault

function ownerDeactivateEmergencyExitForVault(address vault) external virtual

Deactivates the emergency exit mode for a certain vault. Only callable by owner.

NameTypeDescription
vaultaddressThe vault to deactivate emergency exit for

emergencyExitNegativeYieldToken

function emergencyExitNegativeYieldToken(address vault, uint256 amount, address recipient) external virtual returns (uint256 underlyingAmount)

Emergency exit NYTs into the underlying asset. Only callable when emergency exit has been activated for the vault.

NameTypeDescription
vaultaddressThe vault to exit NYT for
amountuint256The amount of NYT to exit
recipientaddressThe recipient of the underlying asset
NameTypeDescription
underlyingAmountuint256The amount of underlying asset exited

emergencyExitPerpetualYieldToken

function emergencyExitPerpetualYieldToken(address vault, contract IxPYT xPYT, uint256 amount, address recipient) external virtual returns (uint256 underlyingAmount)

Emergency exit PYTs into the underlying asset. Only callable when emergency exit has been activated for the vault.

NameTypeDescription
vaultaddressThe vault to exit PYT for
xPYTcontract IxPYTThe xPYT contract to use for burning PYT. Set to 0 to burn raw PYT instead.
amountuint256The amount of PYT to exit
recipientaddressThe recipient of the underlying asset
NameTypeDescription
underlyingAmountuint256The amount of underlying asset exited

Internal functions

_accrueYield

function _accrueYield(address vault, contract PerpetualYieldToken pyt, address user, uint256 updatedPricePerVaultShare) internal virtual

Updates the yield earned globally and for a particular user.

_enter

function _enter(address nytRecipient, address pytRecipient, address vault, contract IxPYT xPYT, uint256 underlyingAmount, uint256 updatedPricePerVaultShare) internal virtual

Mints PYTs and NYTs to the recipient given the amount of underlying deposited.

_exit

function _exit(address vault, contract IxPYT xPYT, uint256 underlyingAmount, uint256 updatedPricePerVaultShare) internal virtual

Burns PYTs and NYTs from msg.sender given the amount of underlying withdrawn.

_claimYield

function _claimYield(address vault, uint256 updatedPricePerVaultShare) internal virtual returns (uint256 yieldAmount)

Updates storage variables for when a PYT holder claims the accrued yield.

_getClaimableYieldAmount

function _getClaimableYieldAmount(address vault, address user, uint256 updatedYieldPerToken, uint256 userYieldPerTokenStored_, uint256 userPYTBalance) internal view virtual returns (uint256 yieldAmount)

Returns the amount of yield claimable by a PerpetualYieldToken holder from a vault. Assumes userYieldPerTokenStored != 0. Does not account for protocol fees._

_depositIntoVault

function _depositIntoVault(contract ERC20 underlying, uint256 underlyingAmount, address vault) internal virtual

Deposits underlying tokens into a vault

NameTypeDescription
underlyingcontract ERC20The underlying token to deposit
underlyingAmountuint256The amount of tokens to deposit
vaultaddressThe vault to deposit into

_withdrawFromVault

function _withdrawFromVault(address recipient, address vault, uint256 underlyingAmount, uint256 pricePerVaultShare, bool checkBalance) internal virtual returns (uint256 withdrawnUnderlyingAmount)

Withdraws underlying tokens from a vault

NameTypeDescription
recipientaddressThe recipient of the underlying tokens
vaultaddressThe vault to withdraw from
underlyingAmountuint256The amount of tokens to withdraw
pricePerVaultShareuint256The latest price per vault share value
checkBalanceboolSet to true to withdraw the entire balance if we're trying to withdraw more than the balance (due to rounding errors)
NameTypeDescription
withdrawnUnderlyingAmountuint256The amount of underlying tokens withdrawn

_vaultSharesAmountToUnderlyingAmount

function _vaultSharesAmountToUnderlyingAmount(address vault, uint256 vaultSharesAmount, uint256 pricePerVaultShare) internal view virtual returns (uint256)

Converts a vault share amount into an equivalent underlying asset amount

_vaultSharesAmountToUnderlyingAmountRoundingUp

function _vaultSharesAmountToUnderlyingAmountRoundingUp(address vault, uint256 vaultSharesAmount, uint256 pricePerVaultShare) internal view virtual returns (uint256)

Converts a vault share amount into an equivalent underlying asset amount, rounding up

_underlyingAmountToVaultSharesAmount

function _underlyingAmountToVaultSharesAmount(address vault, uint256 underlyingAmount, uint256 pricePerVaultShare) internal view virtual returns (uint256)

Converts an underlying asset amount into an equivalent vault shares amount

_computeYieldPerToken

function _computeYieldPerToken(address vault, contract PerpetualYieldToken pyt, uint256 updatedPricePerVaultShare) internal view virtual returns (uint256)

Computes the latest yieldPerToken value for a vault.