Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/events and natspec #278

Merged
merged 2 commits into from
Jan 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions contracts/PrimitiveEngine.sol
Original file line number Diff line number Diff line change
Expand Up @@ -185,15 +185,16 @@ contract PrimitiveEngine is IPrimitiveEngine {
if (delRisky == 0 || delStable == 0) revert CalibrationError(delRisky, delStable);

calibrations[poolId] = cal; // state update
liquidity[msg.sender][poolId] += delLiquidity - MIN_LIQUIDITY; // burn min liquidity, at cost of msg.sender
uint256 amount = delLiquidity - MIN_LIQUIDITY;
liquidity[msg.sender][poolId] += amount; // burn min liquidity, at cost of msg.sender
reserves[poolId].allocate(delRisky, delStable, delLiquidity, cal.lastTimestamp); // state update

(uint256 balRisky, uint256 balStable) = (balanceRisky(), balanceStable());
IPrimitiveCreateCallback(msg.sender).createCallback(delRisky, delStable, data);
checkRiskyBalance(balRisky + delRisky);
checkStableBalance(balStable + delStable);

emit Create(msg.sender, cal.strike, cal.sigma, cal.maturity, cal.gamma);
emit Create(msg.sender, cal.strike, cal.sigma, cal.maturity, cal.gamma, delRisky, delStable, amount);
}

// ===== Margin =====
Expand Down Expand Up @@ -250,7 +251,6 @@ contract PrimitiveEngine is IPrimitiveEngine {
uint256 liquidity0 = (delRisky * reserve.liquidity) / uint256(reserve.reserveRisky);
uint256 liquidity1 = (delStable * reserve.liquidity) / uint256(reserve.reserveStable);
delLiquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;

if (delLiquidity == 0) revert ZeroLiquidityError();

liquidity[recipient][poolId] += delLiquidity; // increase position liquidity
Expand All @@ -265,7 +265,7 @@ contract PrimitiveEngine is IPrimitiveEngine {
checkStableBalance(balStable + delStable);
}

emit Allocate(msg.sender, recipient, poolId, delRisky, delStable);
emit Allocate(msg.sender, recipient, poolId, delRisky, delStable, delLiquidity);
}

/// @inheritdoc IPrimitiveEngineActions
Expand All @@ -284,7 +284,7 @@ contract PrimitiveEngine is IPrimitiveEngine {
reserve.remove(delRisky, delStable, delLiquidity, _blockTimestamp());
margins[msg.sender].deposit(delRisky, delStable);

emit Remove(msg.sender, poolId, delRisky, delStable);
emit Remove(msg.sender, poolId, delRisky, delStable, delLiquidity);
}

struct SwapDetails {
Expand Down
24 changes: 12 additions & 12 deletions contracts/interfaces/engine/IPrimitiveEngineActions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ interface IPrimitiveEngineActions {
// ===== Pool Updates =====

/// @notice Updates the time until expiry of the pool by setting its last timestamp value
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of engine address, strike, sigma, maturity, and gamma
/// @return lastTimestamp Timestamp loaded into the state of the pool's Calibration.lastTimestamp
function updateLastTimestamp(bytes32 poolId) external returns (uint32 lastTimestamp);

/// @notice Initializes a curve with parameters in the `settings` storage mapping in the Engine
/// @param strike Strike price of the pool to calibrate to, with the same decimals as the stable token
/// @param sigma Implied Volatility to calibrate to as an unsigned 32-bit integer w/ precision of 1e4, 10000 = 100%
/// @param maturity Maturity timestamp of the pool, in seconds
/// @param gamma Multiplied against swap in amounts to apply fee, equal to 1 - fee %, an unsigned 32-bit integer, w/ precision of 1e4, 10000 = 100%
/// @param riskyPerLp Risky reserve per liq. with risky decimals, = 1 - N(d1), d1 = (ln(S/K)+(r*sigma^2/2))/sigma*sqrt(tau)
/// @param delLiquidity Amount of liquidity to allocate to the curve, wei value with 18 decimals of precision
/// @notice Initializes a curve with parameters in the `calibrations` storage mapping in the Engine
/// @param strike Marginal price of the pool's risky token at maturity, with the same decimals as the stable token, valid [0, 2^128-1]
/// @param sigma AKA Implied Volatility in basis points, determines the price impact of swaps, valid for (1, 10_000_000)
/// @param maturity Timestamp which starts the BUFFER countdown until swaps will cease, in seconds, valid for (block.timestamp, 2^32-1]
/// @param gamma Multiplied against swap in amounts to apply fee, equal to 1 - fee % but units are in basis points, valid for (9_000, 10_000)
/// @param riskyPerLp Risky reserve per liq. with risky decimals, = 1 - N(d1), d1 = (ln(S/K)+(r*σ^2/2))/σ√τ, valid for [0, 1e^(risky token decimals))
/// @param delLiquidity Amount of liquidity units to allocate to the curve, wei value with 18 decimals of precision
/// @param data Arbitrary data that is passed to the createCallback function
/// @return poolId Pool Identifier
/// @return poolId Keccak256 hash of engine address, strike, sigma, maturity, and gamma
/// @return delRisky Total amount of risky tokens provided to reserves
/// @return delStable Total amount of stable tokens provided to reserves
function create(
Expand Down Expand Up @@ -65,7 +65,7 @@ interface IPrimitiveEngineActions {
// ===== Liquidity =====

/// @notice Allocates risky and stable tokens to a specific curve with `poolId`
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of engine address, strike, sigma, maturity, and gamma
/// @param recipient Address to give the allocated liquidity to
/// @param delRisky Amount of risky tokens to add
/// @param delStable Amount of stable tokens to add
Expand All @@ -82,7 +82,7 @@ interface IPrimitiveEngineActions {
) external returns (uint256 delLiquidity);

/// @notice Unallocates risky and stable tokens from a specific curve with `poolId`
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of engine address, strike, sigma, maturity, and gamma
/// @param delLiquidity Amount of liquidity to remove
/// @return delRisky Amount of risky tokens received from removed liquidity
/// @return delStable Amount of stable tokens received from removed liquidity
Expand All @@ -92,7 +92,7 @@ interface IPrimitiveEngineActions {

/// @notice Swaps between `risky` and `stable` tokens
/// @param recipient Address that receives output token `deltaOut` amount
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of engine address, strike, sigma, maturity, and gamma
/// @param riskyForStable If true, swap risky to stable, else swap stable to risky
/// @param deltaIn Amount of tokens to swap in
/// @param deltaOut Amount of tokens to swap out
Expand Down
13 changes: 8 additions & 5 deletions contracts/interfaces/engine/IPrimitiveEngineErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ pragma solidity >=0.8.4;

/// @title Errors for the Primitive Engine contract
/// @author Primitive
/// @notice Custom errors are encoded with their selector and arguments
/// @dev Peripheral smart contracts should try catch and check if data matches another custom error
interface IPrimitiveEngineErrors {
/// @notice Thrown when a callback function calls the engine __again__
/// @notice Thrown on attempted re-entrancy on a function with a re-entrancy guard
error LockedError();

/// @notice Thrown when the balanceOf function is not successful and does not return data
error BalanceError();

/// @notice Thrown when a pool with poolId already exists
/// @notice Thrown in create when a pool with computed poolId already exists
error PoolDuplicateError();

/// @notice Thrown when calling an expired pool, where block.timestamp > maturity, + BUFFER if swap
Expand All @@ -19,7 +21,7 @@ interface IPrimitiveEngineErrors {
/// @notice Thrown when liquidity is lower than or equal to the minimum amount of liquidity
error MinLiquidityError(uint256 value);

/// @notice Thrown when riskyPerLp is outside the range of acceptable values, 0 < riskyPerLp < 1eRiskyDecimals
/// @notice Thrown when riskyPerLp is outside the range of acceptable values, 0 < riskyPerLp <= 1eRiskyDecimals
error RiskyPerLpError(uint256 value);

/// @notice Thrown when sigma is outside the range of acceptable values, 1 <= sigma <= 1e7 with 4 precision
Expand All @@ -28,7 +30,7 @@ interface IPrimitiveEngineErrors {
/// @notice Thrown when strike is not valid, i.e. equal to 0 or greater than 2^128
error StrikeError(uint256 value);

/// @notice Thrown when gamma, equal to 1 - fee %, is outside its bounds: 9000 <= gamma <= 10000; 1000 = 10% fee
/// @notice Thrown when gamma, equal to 1 - fee %, is outside its bounds: 9_000 <= gamma <= 10_000; 1_000 = 10% fee
error GammaError(uint256 value);

/// @notice Thrown when the parameters of a new pool are invalid, causing initial reserves to be 0
Expand Down Expand Up @@ -60,7 +62,8 @@ interface IPrimitiveEngineErrors {
error DeltaOutError();

/// @notice Thrown when the invariant check fails
/// @dev Most important check as it verifies the validity of a desired swap
/// @param invariant Pre-swap invariant updated with new tau
/// @param nextInvariant Post-swap invariant
/// @param nextInvariant Post-swap invariant after the swap amounts are applied to reserves
error InvariantError(int128 invariant, int128 nextInvariant);
}
45 changes: 33 additions & 12 deletions contracts/interfaces/engine/IPrimitiveEngineEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,28 @@ pragma solidity >=0.5.0;
/// @author Primitive
interface IPrimitiveEngineEvents {
/// @notice Creates a pool with liquidity
/// @dev Keccak256 hash of the engine address and the parameters is the `poolId`
/// @dev Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @param from Calling `msg.sender` of the create function
/// @param strike Strike price of the pool, with precision of stable token
/// @param sigma Implied Volatility of the pool
/// @param maturity Maturity timestamp of the pool
/// @param gamma 1 - Fee % of the pool, as an integer with precision of 1e4
event Create(address indexed from, uint128 indexed strike, uint32 sigma, uint32 indexed maturity, uint32 gamma);
/// @param strike Marginal price of the pool's risky token at maturity, with the same decimals as the stable token, valid [0, 2^128-1]
/// @param sigma AKA Implied Volatility in basis points, determines the price impact of swaps, valid for (1, 10_000_000)
/// @param maturity Timestamp which starts the BUFFER countdown until swaps will cease, in seconds, valid for (block.timestamp, 2^32-1]
/// @param gamma Multiplied against swap in amounts to apply fee, equal to 1 - fee % but units are in basis points, valid for (9000, 10_000)
/// @param delRisky Amount of risky tokens deposited
/// @param delStable Amount of stable tokens deposited
/// @param delLiquidity Amount of liquidity granted to `recipient`
event Create(
address indexed from,
uint128 strike,
uint32 sigma,
uint32 indexed maturity,
uint32 indexed gamma,
uint256 delRisky,
uint256 delStable,
uint256 delLiquidity
);

/// @notice Updates the time until expiry of the pool with `poolId`
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
event UpdateLastTimestamp(bytes32 indexed poolId);

// ===== Margin ====
Expand All @@ -38,30 +50,39 @@ interface IPrimitiveEngineEvents {
/// @notice Adds liquidity of risky and stable tokens to a specified `poolId`
/// @param from Method caller `msg.sender`
/// @param recipient Address that receives liquidity
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @param delRisky Amount of risky tokens deposited
/// @param delStable Amount of stable tokens deposited
/// @param delLiquidity Amount of liquidity granted to `recipient`
event Allocate(
address indexed from,
address indexed recipient,
bytes32 indexed poolId,
uint256 delRisky,
uint256 delStable
uint256 delStable,
uint256 delLiquidity
);

/// @notice Adds liquidity of risky and stable tokens to a specified `poolId`
/// @param from Method caller `msg.sender`
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @param delRisky Amount of risky tokens deposited
/// @param delStable Amount of stable tokens deposited
event Remove(address indexed from, bytes32 indexed poolId, uint256 delRisky, uint256 delStable);
/// @param delLiquidity Amount of liquidity decreased from `from`
event Remove(
address indexed from,
bytes32 indexed poolId,
uint256 delRisky,
uint256 delStable,
uint256 delLiquidity
);

// ===== Swaps =====

/// @notice Swaps between `risky` and `stable` assets
/// @param from Method caller `msg.sender`
/// @param recipient Address that receives `deltaOut` amount of tokens
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @param riskyForStable If true, swaps risky to stable, else swaps stable to risky
/// @param deltaIn Amount of tokens added to reserves
/// @param deltaOut Amount of tokens removed from reserves
Expand Down
22 changes: 11 additions & 11 deletions contracts/interfaces/engine/IPrimitiveEngineView.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ pragma solidity >=0.5.0;
interface IPrimitiveEngineView {
// ===== View =====

/// @notice Fetches the current invariant based on risky and stable token reserves of pool with `poolId`
/// @param poolId Pool Identifier
/// @notice Fetches the current invariant, notation is usually `k`, based on risky and stable token reserves of pool with `poolId`
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @return invariant Signed fixed point 64.64 number, invariant of `poolId`
function invariantOf(bytes32 poolId) external view returns (int128 invariant);

Expand All @@ -27,10 +27,10 @@ interface IPrimitiveEngineView {
//// @return Factory address which deployed this engine contract
function factory() external view returns (address);

//// @return Risky token address
//// @return Risky token address, a more accurate name is the underlying token
function risky() external view returns (address);

/// @return Stable token address
/// @return Stable token address, a more accurate name is the quote token
function stable() external view returns (address);

/// @return Multiplier to scale amounts to/from, equal to 10^(18 - riskyDecimals)
Expand All @@ -42,7 +42,7 @@ interface IPrimitiveEngineView {
// ===== Pool State =====

/// @notice Fetches the global reserve state for a pool with `poolId`
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @return reserveRisky Risky token balance in the reserve
/// @return reserveStable Stable token balance in the reserve
/// @return liquidity Total supply of liquidity for the curve
Expand All @@ -64,12 +64,12 @@ interface IPrimitiveEngineView {
);

/// @notice Fetches `Calibration` pool parameters
/// @param poolId Pool Identifier
/// @return strike Strike price of the pool with stable token decimals
/// @return sigma Implied Volatility as an unsigned 32-bit integer constant w/ precision of 1e4, 10000 = 100%
/// @return maturity Timestamp of maturity in seconds
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @return strike Marginal price of the pool's risky token at maturity, with the same decimals as the stable token, valid [0, 2^128-1]
/// @return sigma AKA Implied Volatility in basis points, determines the price impact of swaps, valid for (1, 10_000_000)
/// @return maturity Timestamp which starts the BUFFER countdown until swaps will cease, in seconds, valid for (block.timestamp, 2^32-1]
/// @return lastTimestamp Last timestamp used to calculate time until expiry, aka "tau"
/// @return gamma = 1 - fee %, as an unsigned 32-bit integer constant w/ precision of 1e4, 10000 = 100%
/// @return gamma Multiplied against swap in amounts to apply fee, equal to 1 - fee % but units are in basis points, valid for (9_000, 10_000)
function calibrations(bytes32 poolId)
external
view
Expand All @@ -82,7 +82,7 @@ interface IPrimitiveEngineView {
);

/// @notice Fetches position liquidity an account address and poolId
/// @param poolId Pool Identifier
/// @param poolId Keccak256 hash of the engine address, strike, sigma, maturity, and gamma
/// @return liquidity Liquidity owned by `account` in `poolId`
function liquidity(address account, bytes32 poolId) external view returns (uint256 liquidity);

Expand Down