# Priceless Position Manager

Below, the **GCR** (“Global Collateralization Ratio”) is the ratio between the total amount of synthetic tokens in debt versus the total amount of collateral held in the contract. Note that this is only a ratio between token *amounts*, not token value; for example, a synthetic BTC with 1 sBTC of total synthetic debt and 1 USDC of collateral is actually 1.0, regardless of the price of Bitcoin.

## State Variables

Note: we omit variables whose comments in Solidity do a good enough job of explaining their job.\
\
`contractState` is an enum with three possibilities:<br>

* `Open`: “normal” pre-expiry operation. Users can start liquidations only when the EMP is in this state. Will advance when `expire()` function is called after `expirationTimestamp` (or when `emergencyShutdown` is called).
* `ExpiredPriceRequested`: The contract’s `expire()` function has been successfully called and we are waiting for a returned OptimisticOracle price. Will advance when `settle()` is called if there is a resolved price available for the OptimisticOracle.
* `ExpiredPriceReceived`: The OptimisticOracle price has resolved and `settle()` has been called at least once.

Keep in mind that the widely used `_onlyPreExpiration` and `_onlyPostExpiration` modifiers don’t look at this state directly; instead, they look at whether `expirationTimestamp` has passed yet or not.\
\
`positions` is a mapping containing a `PositionData` struct, one for each sponsor (note that it’s not possible for one sponsor to have two positions). These `PositionData` structs track the sponsor’s `outstandingTokens` (how much in synthetic assets they owe to the position), their `collateral` (how much collateral is deposited), and information regarding withdrawal and transfer requests.\
\
`tokenCurrency` is the synthetic asset token address that was newly created upon EMP construction. This is the token in which debts are tallied, and all `tokenCurreny` “out in the wild” correspond to some sponsor’s position with collateral, which initially minted them.\
\
`priceIdentifier`: This identifies what price the synthetic asset should follow. `PriceIdentifier` must be one of the approved identifiers for the UMA system. As one example, the `ETHUSD` price feed is an approved feed that dictates specifically how this price must be calculated. A special case is the price identifier `NUMERICAL`, which relies on `ancillaryData` described.\
\
`ancillaryData`: Carries additional information that might be necessary to calculate the price specified by `priceIdentifier`. In the case of NUMERICAL, the ancillary data must pose a question that can be answered numerically. For more information, see [Creating a Novel Synthetic Asset (using the NUMERICAL identifier)](https://quip.com/XpQcA36SBxoe).\
\
`withdrawalLiveness`: If a withdrawal would lower the GCR, it can’t be done instantly and must go through a waiting period. This variable defines how long that waiting period is. See the Solidity comments for more info.\
\
`minSponsorTokens`: If a user wants to become a sponsor, they must create a position that mints at least this many synthetic tokens, and can never go below this amount (except for paying it back in totality, thus removing it). This must be set to avoid any given position being so small that a liquidator is not incentivized to liquidate it (due to gas costs making it prohibitive).

* It should be a considerable amount such that there is an incentive for the liquidator to liquidate it.
* It should be easily mintable by a potential sponsor, i.e. it should not be a huge value.
* The minSponsorTokens should make sense in collateral amount i.e. USDC. So the value should be, let’s say, worth 100 USDC or 10 USDC and so forth. It cannot be equal to 0.0001 USDC etc.

\
`expiryPrice`: Only set while when `contractState == ExpiredPriceResolved`. Stores the price the OptimisticOracle returned.\
\
`ooReward`: The amount of collateral that is sent to the OptimisticOracle as a reward to the proposer. This is also the bond that a liquidator or disputer must submit. During expiration, this cost is socialized to all sponsors to pay for the OptimisticOracle price request.\
\
`financialProductLibrary`: Always set to the zero address, and thus has no bearing on contract behaviour.

## External/Public State-Changing Functions

`requestTransferPosition`, `transferPositionPassedRequest`, and `cancelTransferPosition` all allow a sponsor to transfer his position to another address. The new address must not already hold a position. These methods use the `withdrawalLiveness` value as a delay.\
\
`depositTo` and its wrapper `deposit` simply transfer `collateralAmount` collateral from the specified address to its sponsor position. This can be used to raise the CR of the position that is at risk of becoming undercollateralized.\
\
Conversely, `withdraw` allows a user to withdraw collateral from his position. In contrast to the below functions, this is instant, but can only be done if it does not result in the position having a lower CR than the GCR.\
\
`requestWithdrawal`, `withdrawPassedRequest`, and `cancelWithdrawal` behave similarly to the transferPosition function. One difference however is that a liquidation started on this position may essentially reset the countdown of the withdrawal. See `Liquidatable`’s `createLiquidation` function, near the end.

\
`create` is where new synthetic tokens are born! The user deposits `collateralAmount` collateral and mints `numTokens`new synthetic tokens. He can set both of these parameters, but if this results in a sponsor position whose collateralization ratio is below the GCR, the call will fail. This ensures that new sponsors don’t ever move the total position closer to default. It will also fail if the position ends up with less than the `minSponsorTokens` amount.\
\
If successful, the user has a position with collateral in the collateral currency (usually USDC) and a **debt** of synthetic tokens (`position.tokensOutstanding`); he also has newly-minted synthetic tokens equal to this debt in his wallet, which he may send away or do whatever he wants with.\
\
`repay` burns `numTokens` synthetic asset tokens from the sponsor’s wallet, and reduces his position’s `tokensOutstanding`value by the amount burned (unless this would result in a value of less than `minSponsorTokens`, in which case the call reverts). Like `deposit`, this can be used to increase the CR of the position, but this time by repaying some of the debt of the position.\
\
`redeem` also burns `numTokens` synthetic asset tokens from the sponsor’s wallet and reduces `tokensOutstanding`, but instead of lowering its CR, collateral is returned from the position to the sponsor’s wallet. This will also revert if it results in a position’s `tokensOutstanding` going below `minSponsorTokens` - unless the `tokensOutstanding` goes to zero (meaning `numTokens == tokensOutstanding`), in which case all collateral is returned and the position is deleted.\
\
`expire` can be called by anyone, and can only be called if `contractState == Open` but the `expirationTimestamp` has passed. This function requests a price from the optimistic oracle, socializes the cost of the request to the sponsors, and sets `contractState` to `ExpiredPriceRequested`.\
\
`emergencyShutdown` does essentially the same thing as `expire`, but it must be called by the `governor` and can be called before `expirationTimestamp` has passed.\
\
`settleExpired` does a few different things. First, it checks that `expire` has already been called and that the oracle’s price has now resolved. If these checks pass, the following effects take place:

* If this is the first time the function has been successfully called, it will store the price from the OptimisticOracle and move the `contractState` to `ExpiredPriceReceived`.
* If the caller has any synthetic tokens in his wallet, these are burned and the caller is sent an equivalent amount of underlying collateral, according to the price. In other words, any synthetic tokens are “cashed out” for underlying collateral at market price.
* If the caller has a sponsor position (and thus a debt of `position.tokensOutstanding` synthetic tokens), this debt is converted into a collateral amount and subtracted from the position’s collateral. Any leftover collateral is sent to the user.

## Internal State-Changing Functions

`_reduceSponsorPosition` is not called within `PricelessPositionManager` code directly, instead only used in `Liquidatable` which inherits it. This function reduces a given sponsor’s position values for any of the passed variables for `tokensToRemove` (here meaning synthetic token debt), `collateralToRemove`, and `withdrawalAmountToRemove`, which removes collateral from any pending slow withdrawal. This function will revert if this operation results in a position having less than `minSponsorTokens` for `tokensOutstanding`, except in the case where `tokensOutstanding` and `rawCollateral` would reach zero, in which case the position is deleted.\
\
`_incrementCollateralBalances` and `_decrementCollateralBalances` simply add or subtract both from some local `memory` argument and the global tracker `totalPositionCollateral`, ensuring consistency between individual and global variables.\
\
`_decrementCollateralBalancesCheckGCR` does the same as the previous decrement function, but will revert if the resulting position CR is lower than the GCR.\
\
`_requestOraclePrice_senderPays` does the same thing as the previous function, but is used by the `Liquidatable.dispute` function and gets `ooReward` from `msg.sender`, rather than socializing the cost to sponsors. In other words, while the previous function charges “the EMP itself” (and all its sponsors) for the cost, this function expects `msg.sender` to pay.\
\
`_getOraclePrice` gets a price that has been resolved, after either of the two above functions have requested a price. If the price has not yet resolved the function will revert.\
\
Both `_transformPrice` and `_transformPriceIdentifier` simply return the price or identifier respectively, since `financialContractLibrary` is the zero address for the EMP.<br>
