diff --git a/.solcover.js b/.solcover.js index a3d24622..8f63f25f 100644 --- a/.solcover.js +++ b/.solcover.js @@ -1,12 +1,5 @@ module.exports = { - skipFiles: [ - "./Primitives.sol", - "./interfaces", - "./tokens", - "./test", - "./PrimeExchange.sol", - "./PrimePool.sol", - ], + skipFiles: ["./Primitives.sol", "./interfaces", "./tokens", "./test"], providerOptions: { default_balance_ether: "1000", }, diff --git a/README.md b/README.md index f3a41a62..688e2efe 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ Primitive is a permissionless options protocol. Built on Ethereum. +## Risk + +The protocol and software is in an alpha stage. + ## Overview We overview the contracts and their functions as well as how to test them. diff --git a/buidler.config.js b/buidler.config.js index 8b896e45..73b5cc87 100644 --- a/buidler.config.js +++ b/buidler.config.js @@ -53,7 +53,7 @@ module.exports = { useColors: true, }, etherscan: { - url: "https://api.etherscan.io/api", + url: "https://api-rinkeby.etherscan.io/api", apiKey: ETHERSCAN_APY_KEY, }, gasReporter: { diff --git a/contracts/Factory.sol b/contracts/Factory.sol deleted file mode 100644 index a01dafa5..00000000 --- a/contracts/Factory.sol +++ /dev/null @@ -1,69 +0,0 @@ -pragma solidity ^0.6.2; - -/** - * @title Option Factory Contract - * @author Primitive - */ - -import "./PrimeOption.sol"; -import "./interfaces/IFactoryRedeem.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -contract Factory is Ownable, Pausable, ReentrancyGuard { - using SafeMath for uint256; - - address public admin; - address public feeReceiver; - address public factoryRedeem; - - mapping(bytes32 => address) public options; - - event Deploy(address indexed from, address indexed tokenP, bytes32 indexed id); - - constructor() public { - admin = msg.sender; - } - - function initialize(address _factoryRedeem) external onlyOwner { - factoryRedeem = _factoryRedeem; - } - - function deployOption( - address tokenU, - address tokenS, - uint256 base, - uint256 price, - uint256 expiry - ) - external - nonReentrant - whenNotPaused - returns (address prime) - { - prime = address(new PrimeOption(tokenU, tokenS, base, price, expiry)); - bytes32 id = keccak256(abi.encodePacked(tokenU, tokenS, base, price, expiry)); - options[id] = prime; - address redeem = IFactoryRedeem(factoryRedeem).deploy(prime, tokenS); - PrimeOption(prime).initTokenR(redeem); - //emit Deploy(msg.sender, prime, id); - } - - /* function kill(bytes32 id) external onlyOwner { - PrimeOption(options[id]).kill(); - } */ - - /* - function setFeeReceiver(address _feeReceiver) external onlyOwner { - feeReceiver = _feeReceiver; - }*/ - - function getId( - address tokenU, - address tokenS, - uint256 base, - uint256 price, - uint256 expiry - ) public pure returns (bytes32 id) { - id = keccak256(abi.encodePacked(tokenU, tokenS, base, price, expiry)); - } -} \ No newline at end of file diff --git a/contracts/README.md b/contracts/README.md index fa5f1691..c860657d 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -1,16 +1,21 @@ # Primitives ## Documentation + Documentation is also [here](https://docs.primitive.finance). ## Overview -We design smart tokens. These are tokens that inherit the ERC-20 standard and add extra functions to fulfill a specification. +We design base unit primitives, which we call smart tokens. These are tokens that inherit the ERC-20 standard and add extra functions to fulfill a specification. Smart tokens can be designed to fulfill the specifications of more complex financial instruments like options, synthetics, and stablecoins. We designed the first smart token with the options market of DeFi in mind. +## Directory Structure + +The folders are structured in a way to organize the three components of the protocol: primitives, extensions, and applications. We also have a registry folder which is the factory that deploys and tracks these contracts. + ## The Prime The Prime is a smart token with embedded optionality. @@ -19,29 +24,29 @@ This token gives the holder the ability to swap two assets at a fixed exchange r #### The vanilla option specification: -* Underlying asset. -* Strike Price denominated in $USD. -* Expiration date. -* Buy/Sell underlying asset for strike price. +- Underlying asset. +- Strike Price denominated in \$USD. +- Expiration date. +- Buy/Sell underlying asset for strike price. #### The Prime specification: -* Address of underlying token. -* Address of strike token. -* "Base" value \(amount of underlying tokens\). -* "Price" value \(strike price\). -* Expiration Date, a UNIX timestamp. +- Address of underlying token. +- Address of strike token. +- "Base" value \(amount of underlying tokens\). +- "Price" value \(strike price\). +- Expiration Date, a UNIX timestamp. #### Four Token Design The Prime contract accepts certain tokens as inputs and knows what tokens to output. There are four critical tokens that are in this system: -| Name | Function | Example | -| :--- | :--- | :--- | -| Prime | Vanilla Option | Right to sell ETH for DAI \(ETH Put\) | -| Redeem | Underwriter's receipt | Redeem for ETH | -| Underlying | Token that is purchasable | DAI | -| Strike | Token that is used to purchase underlying | ETH | +| Name | Function | Example | +| :--------- | :---------------------------------------- | :------------------------------------ | +| Prime | Vanilla Option | Right to sell ETH for DAI \(ETH Put\) | +| Redeem | Underwriter's receipt | Redeem for ETH | +| Underlying | Token that is purchasable | DAI | +| Strike | Token that is used to purchase underlying | ETH | The simplicity in the system comes from this four token design, which makes the input/output calculations simple accounting formulas. @@ -116,24 +121,24 @@ This is the full constructor of the Prime contract: The name, symbol, and marketId will be the identifiers for the option contract. There will be extension contracts which will track these identifiers in a global list of Prime options outstanding. -* `string memory name, <-----` -* `string memory symbol, <-----` -* `uint256 _marketId, <-----` -* `address tokenU,` -* `address tokenS,` -* `uint256 base,` -* `uint256 price,` -* `uint256 expiry` +- `string memory name, <-----` +- `string memory symbol, <-----` +- `uint256 _marketId, <-----` +- `address tokenU,` +- `address tokenS,` +- `uint256 base,` +- `uint256 price,` +- `uint256 expiry` #### Choosing the Assets We choose the underlying asset based on what the user wants to buy, WETH, and we give it a strike price based on the strike asset, which we choose to be stablecoin, like DAI. -* `address tokenU, <-----` -* `address tokenS, <-----` -* `uint256 base,` -* `uint256 price,` -* `uint256 expiry` +- `address tokenU, <-----` +- `address tokenS, <-----` +- `uint256 base,` +- `uint256 price,` +- `uint256 expiry` #### Choosing the ratio between the assets @@ -141,27 +146,27 @@ The user wants to buy the WETH at a rate of 1 WETH per 200 DAI. WETH is the unde The rate for this Prime is: -* `1 WETH / 200 DAI` -* `Base / Price` -* `Buy 200 DAI for 1 WETH per 1 Prime you own` +- `1 WETH / 200 DAI` +- `Base / Price` +- `Buy 200 DAI for 1 WETH per 1 Prime you own` You are changing these values: -* `address tokenU,` -* `address tokenS,` -* `uint256 base, <-----` -* `uint256 price, <-----` -* `uint256 expiry` +- `address tokenU,` +- `address tokenS,` +- `uint256 base, <-----` +- `uint256 price, <-----` +- `uint256 expiry` #### Choosing the expiration date Lets also make the Prime expire at some future point of time, say June of 2020. We can pass an _expiration_ date into the constructor's parameters. -* `address tokenU,` -* `address tokenS,` -* `uint256 base,` -* `uint256 price,` -* `uint256 expiry <-----` +- `address tokenU,` +- `address tokenS,` +- `uint256 base,` +- `uint256 price,` +- `uint256 expiry <-----` Now that we have all the ingredients, we can make a Prime and then use it. @@ -171,13 +176,13 @@ To mint Primes we need to send it the underlying assets. The contract knows how If we send 1 WETH to this contract, the amount of outputted Primes is equal to this input which is: -* `1 WETH Input = 1 Prime Output.` +- `1 WETH Input = 1 Prime Output.` The contract also outputs redeem tokens. The amount of Redeems to output is proportional to the input of WETH and the _rate_ of the Prime. -* `1 WETH (Input) / (1 WETH (Base) / 200 DAI (Price)) = 200 Redeems to Output.` -* `Rate = Base / Price.` -* `Input Underlying / Rate = Output Redeem.` +- `1 WETH (Input) / (1 WETH (Base) / 200 DAI (Price)) = 200 Redeems to Output.` +- `Rate = Base / Price.` +- `Input Underlying / Rate = Output Redeem.` #### Swapping, also called Exercising @@ -189,8 +194,8 @@ A Prime has the right to swap to the underlying asset at a 1:1 ratio. If underly The contract knows how to handle this. -* `200 DAI * (1 WETH / 200 DAI) = 1 WETH.` -* `Input Strike Tokens (DAI) * (Base (Quantity of WETH) / Price (Quantity of DAI)) = Output Underlying Tokens.` +- `200 DAI * (1 WETH / 200 DAI) = 1 WETH.` +- `Input Strike Tokens (DAI) * (Base (Quantity of WETH) / Price (Quantity of DAI)) = Output Underlying Tokens.` #### Redeeming @@ -198,7 +203,7 @@ Since we just bought the 1 WETH for 200 DAI, where does the DAI go and who gets The DAI goes to the Prime contract and it is redeemable at a 1:1 ratio using the Redeem token. -* `Input Redeem = Output Strike (DAI).` +- `Input Redeem = Output Strike (DAI).` #### Closing @@ -206,7 +211,7 @@ What about the case where we want to withdraw our underlying assets that we used If you minted 1 Prime and 200 Redeems in exchange for 1 WETH, you need to send the contract 1 Prime and 200 Redeems in order to withdraw 1 WETH. -* `Input Redeem Tokens * Rate & Prime Tokens = Output Underlying Tokens.` +- `Input Redeem Tokens * Rate & Prime Tokens = Output Underlying Tokens.` ### Expiration @@ -257,8 +262,6 @@ $$ \frac{Strike}{Market} \times ImpliedVol \times \sqrt{T} \times \frac{1}{SecondsInDay} $$ - - We use demand as a proxy for the Implied Volatility value. How do we get the demand for the option? ### Demand of the Primes diff --git a/contracts/PrimeAMM.sol b/contracts/applications/PrimeAMM.sol similarity index 59% rename from contracts/PrimeAMM.sol rename to contracts/applications/PrimeAMM.sol index e48bf57f..de61bcd8 100644 --- a/contracts/PrimeAMM.sol +++ b/contracts/applications/PrimeAMM.sol @@ -1,35 +1,34 @@ pragma solidity ^0.6.2; /** - * @title Vanilla Option Exchange + * @title Vanilla Option Automated Market Maker * @author Primitive */ -import "./extensions/PrimePoolV1.sol"; -import "./interfaces/IWETH.sol"; -import "./interfaces/IPrime.sol"; -import "./interfaces/IPrimePool.sol"; -import "./interfaces/IPrimeOracle.sol"; -import "./interfaces/IUniswapV2Factory.sol"; -import "./interfaces/IUniswapV2Router01.sol"; +import "../extensions/PrimePool.sol"; +import "../interfaces/IWETH.sol"; +import "../interfaces/IPrime.sol"; +import "../interfaces/IPrimePool.sol"; +import "../interfaces/IPrimeOracle.sol"; +import "../interfaces/IUniswapV2Factory.sol"; +import "../interfaces/IUniswapV2Router01.sol"; -contract PrimeAMM is PrimePoolV1 { +contract PrimeAMM is PrimePool { using SafeMath for uint; - uint public constant ONE_ETHER = 1 ether; - uint public constant MIN_VOLATILITY = 10**15; uint public constant MANTISSA = 10**36; + uint public constant SLIPPAGE = 10**10; + uint public constant ONE_ETHER = 1 ether; uint public constant DISCOUNT_RATE = 5; - + uint public constant MIN_VOLATILITY = 10**15; uint public volatility; - // Assume oracle is compound's price proxy oracle. address public oracle; - address public WETH; + address public weth; address public router; event Market(address tokenP); - event Buy(address indexed from, uint inTokenS, uint outTokenU, uint premium); + event Buy(address indexed from, uint outTokenU, uint premium); event Sell(address indexed from, uint inTokenP, uint premium); constructor( @@ -38,18 +37,17 @@ contract PrimeAMM is PrimePoolV1 { address _oracle, address _factory, address _router - ) + ) public - PrimePoolV1(_tokenP, _factory) + PrimePool(_tokenP, _factory) { - WETH = _weth; + weth = _weth; oracle = _oracle; router = _router; - volatility = 100; + volatility = 500; + IERC20(IPrime(_tokenP).tokenS()).approve(_router, 100000000 ether); } - receive() external payable {} - /** * @dev Accepts deposits of underlying tokens. * @param inTokenU Quantity of underlyings to deposit. @@ -60,10 +58,9 @@ contract PrimeAMM is PrimePoolV1 { address _tokenP = tokenP; address tokenU = IPrime(_tokenP).tokenU(); (uint totalBalance) = totalPoolBalance(_tokenP); - (outTokenPULP) = _addLiquidity(_tokenP, msg.sender, inTokenU, totalBalance); + (outTokenPULP) = _addLiquidity(msg.sender, inTokenU, totalBalance); require( - IERC20(tokenU).transferFrom(msg.sender, address(this), inTokenU) && - inTokenU >= MIN_LIQUIDITY, + IERC20(tokenU).transferFrom(msg.sender, address(this), inTokenU), "ERR_BAL_UNDERLYING" ); success = true; @@ -85,7 +82,7 @@ contract PrimeAMM is PrimePoolV1 { // If not enough available liquidity to draw, redeem and swap strike tokens. if(balanceU < outTokenU) { - (uint outTokenR) = _redeemAndSwapStrike(_tokenP, tokenU, tokenS, tokenR); + _redeemAndSwapStrike(_tokenP, tokenU, tokenS, tokenR); } require(balanceU >= outTokenU, "ERR_BAL_INSUFFICIENT"); return IERC20(tokenU).transfer(msg.sender, outTokenU); @@ -102,20 +99,23 @@ contract PrimeAMM is PrimePoolV1 { returns (uint outTokenR) { // Check how many tokenS can be pulled from PrimeOption.sol. - (uint maxDraw) = IPrime(_tokenP).maxDraw(); - - // Push tokenR to _tokenP so we can call redeem() and pull tokenS. - IERC20(tokenR).transfer(_tokenP, maxDraw); + uint balanceR = IERC20(tokenR).balanceOf(address(this)); + uint cacheS = IPrime(_tokenP).cacheS(); + uint maxDraw = balanceR > cacheS ? cacheS : balanceR; - // Call redeem function to pull tokenS. - outTokenR = IPrime(_tokenP).redeem(address(this)); + // Redeem tokens. + (outTokenR) = _redeem(address(this), maxDraw); assert(outTokenR == maxDraw); + + uint market = IPrimeOracle(oracle).marketPrice(); + uint minOut = tokenS == weth ? market : outTokenR.mul(ONE_ETHER).div(market); + address[] memory path = new address[](2); - path[0] = tokenU; - path[1] = tokenS; + path[0] = tokenS; + path[1] = tokenU; IUniswapV2Router01(router).swapExactTokensForTokens( outTokenR, - outTokenR, + minOut.sub(minOut.div(SLIPPAGE)), path, address(this), now + 3 minutes @@ -123,14 +123,12 @@ contract PrimeAMM is PrimePoolV1 { } /** - * @dev Purchase ETH Put. - * @notice An eth put is 200 DAI / 1 ETH. The right to swap 1 ETH (tokenS) for 200 Dai (tokenU). - * As a user, you want to cover ETH, so you pay in ETH. Every 1 Quantity of ETH covers 200 DAI. - * A user specifies the amount of ETH they want covered, i.e. the amount of ETH they can swap. - * @param inTokenS The quantity of tokenS (ETH) to 'cover' with an option. Denominated in tokenS (WETH). + * @dev Purchase option tokens from the pool. + * @notice The underlying token is what is purchasable using the strike token. + * @param outTokenP The quantity of options to buy, which allow the purchase of 1:1 tokenU. * @return bool True if the msg.sender receives tokenP. */ - function buy(uint inTokenS) external nonReentrant returns (bool) { + function buy(uint outTokenP) external nonReentrant returns (bool) { // Store in memory for gas savings. address _tokenP = tokenP; ( @@ -142,24 +140,11 @@ contract PrimeAMM is PrimePoolV1 { uint expiry ) = IPrime(_tokenP).prime(); - // Optimistically mint tokenP. + // Optimistically mint option tokens to the msg.sender. + (outTokenP) = _write(outTokenP); - // outTokenU = inTokenS * Quantity of tokenU (base) / Quantity of tokenS (price). - // Units = tokenS * tokenU / tokenS = tokenU. - uint outTokenU = inTokenS.mul(base).div(price); - - // Transfer tokenU (assume DAI) to option contract using Pool funds. - // We do this because the mint function in the Prime contract will check the balance, - // against its previously cached balance. The difference is the amount of tokens that were - // deposited, which determines how many Primes to mint. - require(IERC20(tokenU).balanceOf(address(this)) >= outTokenU, "ERR_BAL_UNDERLYING"); - (bool transferU) = IERC20(tokenU).transfer(_tokenP, outTokenU); - - // Mint Prime and Prime Redeem to this contract. - // If outTokenU is zero because the numerator is smaller than the denominator, - // or because the inTokenS is 0, the mint function will revert. This is because - // the mint function only works when tokens are sent into the Prime contract. - (uint inTokenP, ) = IPrime(_tokenP).mint(address(this)); + // Calculates and then updates the volatility global state variable. + volatility = calculateVolatilityProxy(_tokenP); // Calculate premium. Denominated in tokenU PER tokenS 'covered'. (uint premium) = IPrimeOracle(oracle).calculatePremium( @@ -171,25 +156,20 @@ contract PrimeAMM is PrimePoolV1 { expiry ); - // Calculate total premium to pay, total premium = premium per tokenS * inTokenS. - // Units = tokenS * (tokenU / tokenS) / 10^18 units = tokenU. - premium = inTokenS.mul(premium).div(ONE_ETHER); + // Calculate total premium to pay. Premium should be in underlying token units. + premium = outTokenP.mul(premium).div(ONE_ETHER); + if(tokenU == weth) premium = MANTISSA.div(premium); require(premium > 0, "ERR_PREMIUM_ZERO"); - // Updates the volatility global state variable. - volatility = calculateVolatilityProxy(_tokenP); - // Pulls payment in tokenU from msg.sender and then pushes tokenP (option). - // WARNING: Two calls to untrusted addresses. - require(IERC20(tokenU).balanceOf(msg.sender) >= premium, "ERR_BAL_UNDERLYING"); - require(IERC20(_tokenP).balanceOf(address(this)) >= inTokenP, "ERR_BAL_PRIME"); - emit Buy(msg.sender, inTokenS, outTokenU, premium); - (bool received) = IERC20(tokenU).transferFrom(msg.sender, address(this), premium); - return received && transferU && IERC20(_tokenP).transfer(msg.sender, inTokenP); + // WARNING: Call to untrusted address msg.sender. + emit Buy(msg.sender, outTokenP, premium); + IERC20(tokenU).transferFrom(msg.sender, address(this), premium); + return IERC20(_tokenP).transfer(msg.sender, outTokenP); } /** - * @dev Sell Prime options back to the pool. + * @dev Sell options to the pool. * @notice The pool buys options at a discounted rate based on the current premium price. * @param inTokenP The amount of Prime option tokens that are being sold. */ @@ -228,22 +208,18 @@ contract PrimeAMM is PrimePoolV1 { // Calculate total premium. // Units: tokenU * (tokenU / tokenS) / 10^18 units = total quantity tokenU price. premium = inTokenP.mul(premium).div(ONE_ETHER); + if(tokenU == weth) { premium = MANTISSA.div(premium); } // Check to see if pool has the premium to pay out. require(IERC20(tokenU).balanceOf(address(this)) >= premium, "ERR_BAL_UNDERLYING"); // Calculate amount of redeem needed to close position with inTokenU. - uint redeem = inTokenP.mul(price).div(base); - - // Transfer redeem to prime token optimistically. - IERC20(tokenR).transfer(tokenP, redeem); + uint outTokenR = inTokenP.mul(price).div(base); + require(IERC20(tokenR).balanceOf(address(this)) >= outTokenR, "ERR_BAL_REDEEM"); - // Transfer prime token to prime contract optimistically. - require(IERC20(_tokenP).transferFrom(msg.sender, tokenP, inTokenP), "ERR_TRANSFER_IN_PRIME"); - - // Call the close function to have the transferred prime and redeem tokens burned. - // Returns tokenU. - IPrime(_tokenP).close(address(this)); + // Call the close function to close the option position and receive underlyings. + (uint outTokenU) = _close(outTokenR, inTokenP); + assert(inTokenP >= outTokenU); // Pay out the total premium to the seller. emit Sell(msg.sender, inTokenP, premium); @@ -268,18 +244,17 @@ contract PrimeAMM is PrimePoolV1 { * @dev Calculates the amount of utilized tokenU assets outstanding. */ function totalUtilized(address _tokenP) public view returns (uint utilized) { - // Assume tokenR is proportional to tokenS (WETH) at a 1:1 ratio. + // Assume tokenR is proportional to tokenS (weth) at a 1:1 ratio. // TokenR is always minted proportionally to the ratio between tokenU and tokenS (strike price). // Assume a ratio of 200 DAI per 1 ETH. // If 200 tokenU is used to mint a Prime, it will return 1 tokenR. // 1 tokenR * 200 (base) / 1 (price) = 200 tokenU utilized. // The returned value for `utilized` should always be greater than 1. - // TokenR is redeemable to tokenS at a 1:1 ratio (1 tokenR can be redeemed for 1 WETH). + // TokenR is redeemable to tokenS at a 1:1 ratio (1 tokenR can be redeemed for 1 weth). // The utilized amount of tokenU is therefore this calculation: - // (tokenR = tokenS = WETH) * Quantity of tokenU (base) / Quantity of tokenS (price). - ( , , address tokenR, , uint price, ) = IPrime(_tokenP).prime(); - (uint oraclePrice) = marketRatio(_tokenP); - utilized = IERC20(tokenR).balanceOf(address(this)).mul(oraclePrice).div(price); + // (tokenR = tokenS = weth) * Quantity of tokenU (base) / Quantity of tokenS (price). + ( , , address tokenR, uint base, uint price, ) = IPrime(_tokenP).prime(); + utilized = IERC20(tokenR).balanceOf(address(this)).mul(base).div(price); } /** @@ -299,26 +274,6 @@ contract PrimeAMM is PrimePoolV1 { // Utilized assets are held in the Prime contract waiting to be exercised or expired. totalBalance = totalUnutilized(_tokenP).add(totalUtilized(_tokenP)); } - - /** - * @dev Utility function to get the market ratio of tokenS denominated in tokenU. - * @notice Assumes the getUnderlyingPrice function call from the oracle never returns - * a value greater than 1e36 (MANTISSA). - */ - function marketRatio(address _tokenP) public view returns(uint oraclePrice) { - address _tokenU = IPrime(_tokenP).tokenU(); - address token = _tokenU == WETH ? IPrime(_tokenP).tokenS() : _tokenU; - oraclePrice = MANTISSA.div(IPrimeOracle(oracle).marketPrice(token)); - } - - /** - * @dev Utility function to send ethers safely. - */ - function sendEther(address to, uint amount) private returns (bool) { - (bool success, ) = to.call.value(amount)(""); - require(success, "ERR_SEND_ETHER"); - return success; - } } \ No newline at end of file diff --git a/contracts/PrimePerpetual.sol b/contracts/applications/PrimePerpetual.sol similarity index 64% rename from contracts/PrimePerpetual.sol rename to contracts/applications/PrimePerpetual.sol index a22f6d5c..172b576c 100644 --- a/contracts/PrimePerpetual.sol +++ b/contracts/applications/PrimePerpetual.sol @@ -5,12 +5,12 @@ pragma solidity ^0.6.2; * @author Primitive */ -import "./extensions/PrimePoolV1.sol"; -import "./interfaces/IPrime.sol"; -import "./interfaces/ICToken.sol"; -import "./interfaces/IPrimePerpetual.sol"; +import "../extensions/PrimePool.sol"; +import "../interfaces/IPrime.sol"; +import "../interfaces/ICToken.sol"; +import "../interfaces/IPrimePerpetual.sol"; -contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { +contract PrimePerpetual is IPrimePerpetual, PrimePool { using SafeMath for uint; address public override cdai; @@ -24,7 +24,7 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { event Swap(address indexed from, uint inTokenP, uint outTokenS); constructor(address _cdai, address _cusdc, address _tokenP, address _factory) - public PrimePoolV1(_tokenP, _factory) + public PrimePool(_tokenP, _factory) { fee = 1e15; cdai = _cdai; @@ -36,10 +36,9 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { function deposit(uint inTokenU) external override whenNotPaused nonReentrant returns (uint outTokenPULP, bool success) { - address _tokenP = tokenP; address tokenU = ICToken(cusdc).underlying(); - (uint totalBalance) = totalBalance(); - (outTokenPULP) = _addLiquidity(_tokenP, msg.sender, inTokenU, totalBalance); + (uint poolBalance) = totalBalance(); + (outTokenPULP) = _addLiquidity(msg.sender, inTokenU, poolBalance); require( IERC20(tokenU).transferFrom(msg.sender, address(this), inTokenU) && inTokenU >= MIN_LIQUIDITY, @@ -50,13 +49,10 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { } function withdraw(uint inTokenPULP) external override whenNotPaused nonReentrant returns (bool) { - address _tokenP = tokenP; address tokenU = ICToken(cusdc).underlying(); - (uint totalBalance) = totalBalance(); - (uint outTokenU) = _removeLiquidity(msg.sender, inTokenPULP, totalBalance); + (uint poolBalance) = totalBalance(); + (uint outTokenU) = _removeLiquidity(msg.sender, inTokenPULP, poolBalance); swapFromInterestBearing(cusdc, outTokenU); - (uint balanceU,) = balances(); - require(balanceU >= outTokenU, "ERR_BAL_INSUFFICIENT"); return IERC20(tokenU).transfer(msg.sender, outTokenU); } @@ -67,8 +63,7 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { function mint(uint inTokenS) external override nonReentrant whenNotPaused returns (bool) { // Store in memory for gas savings. address _tokenP = tokenP; - (address tokenU, address tokenS, , uint base, uint price,) = IPrime(_tokenP).prime(); - + (, address tokenS, , uint base, uint price,) = IPrime(_tokenP).prime(); // outTokenU = inTokenS * Quantity of tokenU (base) / Quantity of tokenS (price). // Units = tokenS * tokenU / tokenS = tokenU. @@ -82,25 +77,14 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { // against its previously cached balance. The difference is the amount of tokens that were // deposited, which determines how many Primes to mint. swapFromInterestBearing(cusdc, outTokenU); - require(IERC20(tokenU).balanceOf(address(this)) >= outTokenU, "ERR_BAL_UNDERLYING"); - (bool transferU) = IERC20(tokenU).transfer(_tokenP, outTokenU); - - // Mint Prime and Prime Redeem to this contract. - // If outTokenU is zero because the numerator is smaller than the denominator, - // or because the inTokenS is 0, the mint function will revert. This is because - // the mint function only works when tokens are sent into the Prime contract. - (uint inTokenP, ) = IPrime(_tokenP).mint(address(this)); - - // Pulls payment in tokenS from msg.sender and then pushes tokenP (option). - // WARNING: Two calls to untrusted addresses. - assert(IERC20(_tokenP).balanceOf(address(this)) >= inTokenP); - emit Insure(msg.sender, inTokenS, outTokenU); + (uint outTokenP) = _write(outTokenU); // Pull tokenS. - (bool received) = IERC20(tokenS).transferFrom(msg.sender, address(this), payment); + IERC20(tokenS).transferFrom(msg.sender, address(this), payment); // Swap tokenS to interest bearing version. + emit Insure(msg.sender, inTokenS, outTokenU); swapToInterestBearing(cdai, payment); - return received && transferU && IERC20(_tokenP).transfer(msg.sender, inTokenP); + return IERC20(_tokenP).transfer(msg.sender, outTokenP); } /** @@ -108,7 +92,7 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { */ function redeem(uint inTokenP) external override nonReentrant returns (bool) { address _tokenP = tokenP; - (, address tokenS, address tokenR, uint base, uint price,) = IPrime(_tokenP).prime(); + (, address tokenS, , uint base, uint price,) = IPrime(_tokenP).prime(); require(IERC20(_tokenP).balanceOf(msg.sender) >= inTokenP, "ERR_BAL_PRIME"); // Calculate amount of tokenS to push out. @@ -117,39 +101,28 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { // Swap from interest bearing to push to msg.sender. swapFromInterestBearing(cdai, outTokenS); - // Assume this is DAI - assert(IERC20(tokenS).balanceOf(address(this)) >= outTokenS); - // Transfer redeemed amount to msg.sender and option tokens to prime option. IERC20(tokenS).transfer(msg.sender, outTokenS); - IERC20(_tokenP).transferFrom(msg.sender, _tokenP, inTokenP); - IERC20(tokenR).transfer(_tokenP, outTokenS); - // Close the position, allowing the tokenU to return to the pool. - IPrime(_tokenP).close(address(this)); + // Close the option position by burning prime and redeem tokens. + _close(outTokenS, inTokenP); emit Redemption(msg.sender, inTokenP, outTokenS); } function exercise(uint inTokenP) external override nonReentrant returns (bool) { address _tokenP = tokenP; - (, address tokenS, address tokenR, uint base, uint price,) = IPrime(_tokenP).prime(); + (, , , uint base, uint price,) = IPrime(_tokenP).prime(); require(IERC20(_tokenP).balanceOf(msg.sender) >= inTokenP, "ERR_BAL_PRIME"); // Calculate amount of tokenS to push out. - uint outTokenS = inTokenP.mul(price).div(base); + uint outTokenS = inTokenP.mul(price).div(base); + outTokenS = outTokenS.add(outTokenS.div(IPrime(_tokenP).FEE())); // Swap from interest bearing to push to msg.sender. swapFromInterestBearing(cdai, outTokenS); - // Assume this is DAI - assert(IERC20(tokenS).balanceOf(address(this)) >= outTokenS); - - // Transfer strike and option tokens to prime option in order to exercise. - IERC20(tokenS).transfer(_tokenP, outTokenS); - IERC20(_tokenP).transferFrom(msg.sender, _tokenP, inTokenP); - - // Close the position, allowing the tokenU to return to the pool. - IPrime(_tokenP).exercise(msg.sender, inTokenP, new bytes(0)); + // Exercise the options. + _exercise(msg.sender, outTokenS, inTokenP); emit Swap(msg.sender, inTokenP, outTokenS); } @@ -159,7 +132,7 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { * @param amount Quantity of token to convert to cToken. */ function swapToInterestBearing(address token, uint amount) internal returns (bool) { - (uint success ) = ICToken(token).mint(amount); + (uint success) = ICToken(token).mint(amount); require(success == 0, "ERR_CTOKEN_MINT"); return success == 0; } @@ -180,10 +153,10 @@ contract PrimePerpetual is IPrimePerpetual, PrimePoolV1 { balanceR = ICToken(cdai).balanceOfUnderlying(address(this)); } - function totalBalance() public override view returns (uint totalBalance) { + function totalBalance() public override view returns (uint poolBalance) { (uint balanceU,) = interestBalances(); (, , address tokenR, uint base, uint price,) = IPrime(tokenP).prime(); - totalBalance = balanceU.add(IERC20(tokenR).balanceOf(address(this)).mul(base).div(price)); + poolBalance = balanceU.add(IERC20(tokenR).balanceOf(address(this)).mul(base).div(price)); } } diff --git a/contracts/extensions/PrimeOracle.sol b/contracts/extensions/PrimeOracle.sol index 21f4792d..d023d234 100644 --- a/contracts/extensions/PrimeOracle.sol +++ b/contracts/extensions/PrimeOracle.sol @@ -5,44 +5,24 @@ pragma solidity ^0.6.2; * @author Primitive */ +import "../interfaces/IAggregator.sol"; import "../interfaces/IPrimeOracle.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; -interface PriceOracleProxy { - function getUnderlyingPrice(address cToken) external view returns (uint); -} - contract PrimeOracle is IPrimeOracle { - using SafeMath for uint256; + using SafeMath for uint; - /* address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; */ - address public constant MCD_DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F; - address public constant COMPOUND_DAI = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643; - address public constant COMPOUND_ETH = 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5; - address public constant COMPOUND_USDC = 0x39AA39c021dfbaE8faC545936693aC917d5E7563; - address public constant COMPOUND_USDT = 0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9; - address public constant COMPOUND_WBTC = 0xC11b1268C1A384e55C48c2391d8d480264A3A7F4; address public oracle; - address public WETH; - - uint256 public constant MIN_PREMIUM = 10**3; - uint256 public constant ONE_ETHER = 1 ether; - uint256 public constant SECONDS_IN_DAY = 86400; - uint256 public constant MANTISSA = 10**36; + address public weth; - mapping(address => address) public feeds; + uint public constant MANTISSA = 10**36; + uint public constant ONE_ETHER = 1 ether; + uint public constant MIN_PREMIUM = 10**3; + uint public constant SECONDS_IN_DAY = 86400; constructor(address _oracle, address _weth) public { oracle = _oracle; - WETH = _weth; - feeds[MCD_DAI] = COMPOUND_DAI; - } - - /** - * @dev Testing function to add non-mainnet oracle feeds. - */ - function addFeed(address feed) public { - feeds[feed] = feed; + weth = _weth; } /** @@ -60,36 +40,32 @@ contract PrimeOracle is IPrimeOracle { function calculatePremium( address tokenU, address tokenS, - uint256 volatility, - uint256 base, - uint256 price, - uint256 expiry + uint volatility, + uint base, + uint price, + uint expiry ) public view - override returns (uint256 premium) + override + returns (uint premium) { // Calculate the parts. - (uint256 intrinsic) = calculateIntrinsic(tokenU, tokenS, base, price); - (uint256 extrinsic) = calculateExtrinsic(tokenU, tokenS, volatility, base, price, expiry); + (uint intrinsic) = calculateIntrinsic(tokenU, tokenS, base, price); + (uint extrinsic) = calculateExtrinsic(tokenU, tokenS, volatility, base, price, expiry); // Sum the parts. premium = (extrinsic.add(intrinsic)); // If the premium is 0, return a minimum value. - premium = premium > 0 ? premium : MIN_PREMIUM; + premium = premium > MIN_PREMIUM ? premium : MIN_PREMIUM; } /** - * @dev Gets the market price of tokenU using compound's oracle, which uses the compound - * version of the token. + * @dev Gets the market price Ether. */ - function marketPrice(address token) public view override returns (uint256 market) { - // The compound wrapped cToken. e.g. cToken = DAI, feed = cDAI. - address feed = feeds[token]; - require(feed != address(0), "ERR_FEED_INVALID"); - // override Returns the price of cToken denominated in ethers. - market = PriceOracleProxy(oracle).getUnderlyingPrice(feed); + function marketPrice() public view override returns (uint market) { + market = uint(IAggregator(oracle).latestAnswer()); } /** @@ -101,28 +77,20 @@ contract PrimeOracle is IPrimeOracle { * @return intrinsic The difference between the price of tokenU denominated in S between the * strike price (price) and market price (market). */ - function calculateIntrinsic(address tokenU, address tokenS, uint256 base, uint256 price) + function calculateIntrinsic(address tokenU, address tokenS, uint base, uint price) public view - override returns (uint256 intrinsic) + override + returns (uint intrinsic) { - // Get the oracle market price. - uint256 market; - if(tokenU == WETH) { - // Market price of tokenU per tokenS. - (market) = marketPrice(tokenS); - // Convert tokenU per tokenS to tokenS per tokenU. Assumes oracle never returns a value > 1e36. - market = MANTISSA.div(market); - } else { - // Market price of tokenS per tokenU. - (market) = marketPrice(tokenU); - } - // Strike price of tokenU per tokenS. Scaled to 10^18 units. - uint256 strike = price.mul(ONE_ETHER).div(base); - // Intrinsic value denominated in tokenS per tokenU. - intrinsic = market > strike ? market.sub(strike) : 0; - // Convert units back to tokenU per tokenS. - intrinsic = intrinsic.mul(base).div(market); + // Currently only supports WETH options with an assumed stablecoin strike. + require(tokenU == weth || tokenS == weth, "ERR_ONLY_WETH_SUPPORT"); + // Get the oracle market price of ether. + // If the underlying is WETH, the option is a call. Intrinsic = (S - K). + // Else if the strike is WETH, the option is a put. Intrinsic = (K - S). + (uint market) = marketPrice(); + if(tokenU == weth) { intrinsic = market > price ? market.sub(price) : uint(0); } + else intrinsic = base > market ? base.sub(market) : uint(0); } /** @@ -139,55 +107,49 @@ contract PrimeOracle is IPrimeOracle { function calculateExtrinsic( address tokenU, address tokenS, - uint256 volatility, - uint256 base, - uint256 price, - uint256 expiry + uint volatility, + uint base, + uint price, + uint expiry ) public view - override returns (uint256 extrinsic) + override + returns (uint extrinsic) { - // Get the oracle market price. - uint256 market; - if(tokenU == WETH) { - // Market price of tokenU per tokenS. - (market) = marketPrice(tokenS); - // Convert tokenU per tokenS to tokenS per tokenU. Assumes oracle never returns a value > 1e36. - market = MANTISSA.div(market); - } else { - // Market price of tokenS per tokenU. - (market) = marketPrice(tokenU); - } - + // Get the oracle market price of ether. + (uint market) = marketPrice(); // Time left in seconds. - uint256 timeRemainder = (expiry.sub(block.timestamp)); + uint timeRemainder = (expiry.sub(block.timestamp)); // Strike price is the price of tokenU denominated in tokenS. - uint256 strike = price.mul(ONE_ETHER).div(base); + uint strike = tokenU == weth ? + price.mul(ONE_ETHER).div(base) : + base.mul(ONE_ETHER).div(price); // Strike / Market scaled to 1e18. Denominated in ethers. - /* uint256 moneyness = strike.mul(ONE_ETHER).div(market); */ - uint256 moneyness = market.mul(ONE_ETHER).div(strike); + uint moneyness = market.mul(ONE_ETHER).div(strike); // Extrinsic value denominted in tokenU. + (extrinsic) = _extrinsic(moneyness, volatility, timeRemainder); + } + + function _extrinsic(uint moneyness, uint volatility, uint timeRemainder) + public + pure + returns (uint extrinsic) + { extrinsic = moneyness - .mul(ONE_ETHER) - .mul(volatility) - .mul(sqrt(timeRemainder)) - .div(ONE_ETHER) - .div(SECONDS_IN_DAY); - if(tokenU == WETH) { - // Convert units back to tokenU per tokenS. - // Extrinsic calculation is always in DAI per ETH, but if tokenU is ETH - // we want the price in ETH per DAI. - extrinsic = extrinsic.mul(base).div(market); - } + .mul(ONE_ETHER) + .mul(volatility) + .mul(sqrt(timeRemainder)) + .div(ONE_ETHER) + .div(SECONDS_IN_DAY); } /** * @dev Utility function to calculate the square root of an integer. Used in calculating premium. */ - function sqrt(uint256 y) private pure returns (uint256 z) { + function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { - uint256 x = (y + 1) / 2; + uint x = (y + 1) / 2; z = y; while (x < z) { z = x; diff --git a/contracts/extensions/PrimePool.sol b/contracts/extensions/PrimePool.sol index 96fa7d4a..535d47ae 100644 --- a/contracts/extensions/PrimePool.sol +++ b/contracts/extensions/PrimePool.sol @@ -1,587 +1,125 @@ pragma solidity ^0.6.2; /** - * @title Primitive's Pool for Writing Short Ether Puts + * @title Vanilla Option Pool * @author Primitive */ - import "../interfaces/IPrime.sol"; import "../interfaces/IPrimePool.sol"; -import "../interfaces/IPrimeOracle.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; - -interface UniswapFactoryInterface { - // Get Exchange and Token Info - function getExchange(address token) external view returns (address exchange); -} - -interface UniswapExchangeInterface { - // Get Prices - function getEthToTokenInputPrice(uint256 eth_sold) external view returns (uint256 tokens_bought); - // Trade ERC20 to ETH - function tokenToEthSwapInput(uint256 tokens_sold, uint256 min_eth, uint256 deadline) external returns (uint256 eth_bought); - // Trade ETH to ERC20 - function ethToTokenSwapInput(uint256 min_tokens, uint256 deadline) external payable returns (uint256 tokens_bought); -} - -interface IWETH { - function deposit() external payable; - function withdraw(uint wad) external; -} +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; contract PrimePool is IPrimePool, Ownable, Pausable, ReentrancyGuard, ERC20 { - using SafeMath for uint256; - - address public constant COMPOUND_DAI = 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643; - /* address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2; */ - - uint256 public constant SECONDS_IN_DAY = 86400; - uint256 public constant MAX_SLIPPAGE = 95; - uint256 public constant MIN_VOLATILITY = 10**15; - uint256 public constant MIN_PREMIUM = 100; - uint256 public constant MIN_LIQUIDITY = 10**4; - uint256 public constant ONE_ETHER = 1 ether; - uint256 public constant MANTISSA = 10**36; - uint256 public constant DISCOUNT_RATE = 5; + using SafeMath for uint; - uint256 public volatility; + uint public constant MIN_LIQUIDITY = 10**4; - // Assume oracle is compound's price proxy oracle. - address public oracle; address public override factory; address public override tokenP; - address public WETH; - event Market(address tokenP); - event Deposit(address indexed from, uint256 inTokenU, uint256 outTokenPULP); - event Withdraw(address indexed from, uint256 inTokenPULP, uint256 outTokenU); - event Buy(address indexed from, uint256 inTokenS, uint256 outTokenU, uint256 premium); - event Sell(address indexed from, uint256 inTokenP, uint256 premium); + event Deposit(address indexed from, uint inTokenU, uint outTokenPULP); + event Withdraw(address indexed from, uint inTokenPULP, uint outTokenU); - constructor ( - address _weth, - address _tokenP, - address _oracle, - address _factory, - string memory name, - string memory symbol - ) + constructor(address _tokenP, address _factory) public - ERC20(name, symbol) + ERC20("Primitive V1 Pool", "PULP") { - WETH = _weth; tokenP = _tokenP; - oracle = _oracle; factory = _factory; - volatility = 100; } - function kill() public override onlyOwner returns (bool) { - if(paused()) { - _unpause(); - } else { - _pause(); - } - return true; - } - - receive() external payable {} - - /* =========== MAKER FUNCTIONS =========== */ - - - /** - * @dev Adds liquidity by depositing tokenU. Receives tokenPULP. - * @param inTokenU The quantity of tokenU to deposit. - */ - function deposit( - uint256 inTokenU - ) - external - whenNotPaused - nonReentrant - returns (uint256 outTokenPULP, bool success) - { - // Store locally for gas savings. - address _tokenP = tokenP; - address tokenU = IPrime(_tokenP).tokenU(); - - // Require inTokenUs greater than 0 and the msg.sender to have the inTokenU in the params. - require( - IERC20(tokenU).balanceOf(msg.sender) >= inTokenU && - inTokenU >= MIN_LIQUIDITY, - "ERR_BAL_UNDERLYING" - ); - - // Add liquidity to pool and push tokenPULP to depositor. - (outTokenPULP) = _addLiquidity(_tokenP, msg.sender, inTokenU); - - // Assume we hold the tokenU asset until it is utilized in minting a Prime. - (success) = IERC20(tokenU).transferFrom(msg.sender, address(this), inTokenU); - } - - /** - * @dev Adds liquidity by depositing ETH. Receives tokenPULP. - * @notice Requires tokenU to be WETH. - * msg.value is The quantity of tokenU to deposit. - */ - function depositEth() - external - payable - whenNotPaused - nonReentrant - returns (uint256 outTokenPULP, bool success) - { - // Save in memory for gas savings. - address _tokenP = tokenP; - address tokenU = IPrime(_tokenP).tokenU(); - require( - msg.value >= MIN_LIQUIDITY, - "ERR_BAL_UNDERLYING" - ); - - // To deposit ETH, tokenU needs to be WETH. - require(tokenU == WETH, "ERR_NOT_WETH"); - - // Add liquidity to pool and push tokenPULP to depositor. - (outTokenPULP) = _addLiquidity(_tokenP, msg.sender, msg.value); - - // Assume we hold the tokenU asset until it is utilized in minting a Prime. - IWETH(WETH).deposit.value(msg.value)(); - success = true; - } + function kill() public override onlyOwner returns (bool) { paused() ? _unpause() : _pause(); } /** * @dev Private function to mint tokenPULP to depositor. */ - function _addLiquidity(address _tokenP, address to, uint256 inTokenU) - private - returns (uint256 outTokenPULP) + function _addLiquidity(address to, uint inTokenU, uint poolBalance) + internal + returns (uint outTokenPULP) { // Mint LP tokens proportional to the Total LP Supply and Total Pool Balance. - uint256 _totalSupply = totalSupply(); - (uint256 totalBalance) = totalPoolBalance(_tokenP); - - // If liquidity is not intiialized, mint the initial liquidity and lock it by - // minting it to this contract. + uint _totalSupply = totalSupply(); + + // If liquidity is not intiialized, mint the initial liquidity. if(_totalSupply == 0) { outTokenPULP = inTokenU; } else { - outTokenPULP = inTokenU.mul(_totalSupply).div(totalBalance); - require(outTokenPULP > 0, "ERR_ZERO_LIQUIDITY"); + outTokenPULP = inTokenU.mul(_totalSupply).div(poolBalance); } + + require(outTokenPULP > uint(0) && outTokenPULP >= MIN_LIQUIDITY, "ERR_ZERO_LIQUIDITY"); _mint(to, outTokenPULP); emit Deposit(to, inTokenU, outTokenPULP); } - /** - * @dev liquidity Provider burns their tokenPULP for proportional amount of tokenU + tokenS. - * @notice outTokenU = inTokenPULP * balanceU / Total Supply tokenPULP, - * outTokenS = inTokenPULP * balanceR / Total Supply tokenPULP, - * If the pool is fully utilized and there are no strike assets to redeem, - * the LPs will have to wait for options to be exercised or become expired. - * @param inTokenPULP The quantity of liquidity tokens to burn. - */ - function withdraw( - uint256 inTokenPULP - ) - external - nonReentrant - returns (bool) + function _removeLiquidity(address to, uint inTokenPULP, uint poolBalance) + internal + returns (uint outTokenU) { - // Check tokenPULP balance. - require( - balanceOf(msg.sender) >= inTokenPULP && - inTokenPULP > 0, - "ERR_BAL_PULP" - ); - - // Store for gas savings. - address _tokenP = tokenP; - - // Store Total Supply before we burn - uint256 _totalSupply = totalSupply(); - - // Get the actual balance of tokenU in the pool. - (uint256 balanceU) = totalUnutilized(_tokenP); - - // Calculate total pool balance. Oustanding underwrites + balance. - (uint256 totalBalance) = totalPoolBalance(_tokenP); + require(balanceOf(to) >= inTokenPULP && inTokenPULP > 0, "ERR_BAL_PULP"); + uint _totalSupply = totalSupply(); - // outTokenU = inTokenPULP * Balance of tokenU / Total Supply of tokenPULP. - // Checks to make sure numerator >= denominator. - // Will revert in cases that inTokenPULP * total balance < total supply of tokenPULP. - uint256 outTokenU = inTokenPULP.mul(totalBalance).div(_totalSupply); - if(balanceU >= outTokenU) { - require(outTokenU > 0, "ERR_BAL_UNDERLYING"); - // Burn tokenPULP. - _burn(msg.sender, inTokenPULP); - - // Push outTokenU to msg.sender. - emit Withdraw(msg.sender, inTokenPULP, outTokenU); - return _withdraw(IPrime(_tokenP).tokenU(), msg.sender, outTokenU); - } else { - // Get tokenU balances. - (balanceU, totalBalance) = _removeLiquidity(_tokenP, inTokenPULP); - outTokenU = inTokenPULP.mul(totalBalance).div(_totalSupply); - - // Push outTokenU to msg.sender. - emit Withdraw(msg.sender, inTokenPULP, outTokenU); - return _withdraw(IPrime(_tokenP).tokenU(), msg.sender, outTokenU); - } - } - - /** - * @dev Private function to burn tokenPULP, pull tokenS, swap tokenS to tokenU, and push tokenU. - * @notice This is a large function. It pulls tokenU from the option contract (tokenP). - * It also swaps tokenS to tokenU using a uniswap pool. - * @param _tokenP The option contract address. - */ - function _removeLiquidity(address _tokenP, uint256 inTokenPULP) - private - returns (uint256 balanceU, uint256 totalBalance) - { + // Calculate output amounts. + outTokenU = inTokenPULP.mul(poolBalance).div(_totalSupply); + require(outTokenU > uint(0), "ERR_ZERO"); // Burn tokenPULP. - _burn(msg.sender, inTokenPULP); - - // Pull tokenS into this contract. - assert(_redeem(_tokenP) > 0); - - // Push tokenS to uniswap pool and pull tokenU. - assert(_exchange(_tokenP) > 0); - - // Get the actual balance of tokenU in the pool. - (balanceU) = totalUnutilized(_tokenP); - - // Calculate total pool balance. Oustanding underwrites + balance. - (totalBalance) = totalPoolBalance(_tokenP); - } - - /** - * @dev Private function to push tokenR to option contract then pull tokenS. - * @notice Should only be called when Pool cannot fill withdraw request. - * Will revert if maxDraw is 0. - * @param _tokenP Address of Prime option contract. - */ - function _redeem(address _tokenP) - private - returns (uint256 outTokenR) - { - // Check how many tokenS can be pulled from PrimeOption.sol. - (uint256 maxDraw) = IPrime(_tokenP).maxDraw(); - - // Push tokenR to _tokenP so we can call redeem() and pull tokenS. - IERC20(IPrime(_tokenP).tokenR()).transfer(_tokenP, maxDraw); - - // Call redeem function to pull tokenS. - outTokenR = IPrime(_tokenP).redeem(address(this)); - assert(outTokenR == maxDraw); - } - - /** - * @dev Swaps tokenS to tokenU through uniswap. - * @notice Assumes tokenU is DAI and tokenS is WETH. - * In future versions this can be made more modular. - * It should be able to swap any tokenS into any tokenU. - * This will be made possible when UniswapV2 is released. - */ - function _exchange(address _tokenP) - private - returns (uint256 inTokenU) - { - // Get addresses for gas savings. - address tokenS = IPrime(_tokenP).tokenS(); - address tokenU = IPrime(_tokenP).tokenU(); - address exchange; - if(tokenU == WETH) { - exchange = tokenS; - } else exchange = tokenU; - exchange = UniswapFactoryInterface(factory).getExchange(exchange); - // Get price of 1 ETH denominated in tokenU from compound oracle. 1 ETH = 1e36 / oracle's price. - // Assumes oracle never returns a value greater than 1e36. - (uint256 oraclePrice) = marketRatio(_tokenP); - // Get price of 1 ETH denominated in tokenU from uniswap pool. - uint256 uniPrice = UniswapExchangeInterface(exchange).getEthToTokenInputPrice(ONE_ETHER); - // Calculate the max slippage price. Assumes oracle price is never < 100 wei. - uint256 slippage = oraclePrice.div(MAX_SLIPPAGE); - // Subtract max slippage amount from uniswap price to get min received tokenU per tokenS. - uint256 minReceived = uniPrice.sub(slippage); - // Initialize outTokenS variable. - uint256 outTokenS; - if(tokenU == WETH) { - // Get current balance of tokenS to send to uniswap pool. - outTokenS = IERC20(tokenS).balanceOf(address(this)); - // Get the minimum amount of ETH received by selling outTokenS at the current price. - minReceived = outTokenS.mul(ONE_ETHER).div(minReceived); - // Swaps tokenS to ETH. - // Min tokenU Received: Amount ETH * minRecieved / 10^18 - // Deadline = now + 3 minutes. - IERC20(tokenS).approve(exchange, outTokenS); - inTokenU = UniswapExchangeInterface(exchange) - .tokenToEthSwapInput(outTokenS, minReceived, now + 3 minutes); - - // Wrap WETH. - IWETH(WETH).deposit.value(address(this).balance)(); - } else { - assert(tokenS == WETH); - // Unwrap WETH. - IWETH(WETH).withdraw(IERC20(tokenS).balanceOf(address(this))); - // Get balance to send to uniswap pool. - outTokenS = address(this).balance; - // Swaps ETH to tokenU. - // Amount ETH swapped = msg.value sent. - // Min tokenU Received: Amount ETH * minRecieved / 10^18 - // Deadline = now + 3 minutes. - inTokenU = UniswapExchangeInterface(exchange) - .ethToTokenSwapInput - .value(outTokenS)(outTokenS.mul(minReceived).div(ONE_ETHER), now + 3 minutes); - } + _burn(to, inTokenPULP); + emit Withdraw(to, inTokenPULP, outTokenU); } - /** - * @dev Private function to push assets to msg.sender. Will push ethers or tokens depending - * on the address passed in the parameter. - */ - function _withdraw(address token, address to, uint256 amount) private returns (bool) { - if(token == WETH) { - IWETH(WETH).withdraw(amount); - return sendEther(to, amount); - } else { - return IERC20(token).transfer(to, amount); - } - } - - - /* =========== TAKER FUNCTIONS =========== */ - - - /** - * @dev Purchase ETH Put. - * @notice An eth put is 200 DAI / 1 ETH. The right to swap 1 ETH (tokenS) for 200 Dai (tokenU). - * As a user, you want to cover ETH, so you pay in ETH. Every 1 Quantity of ETH covers 200 DAI. - * A user specifies the amount of ETH they want covered, i.e. the amount of ETH they can swap. - * @param inTokenS The quantity of tokenS (ETH) to 'cover' with an option. Denominated in tokenS (WETH). - * @return bool True if the msg.sender receives tokenP. - */ - function buy( - uint256 inTokenS - ) - external - nonReentrant - returns (bool) - { - // Store in memory for gas savings. + function _write(uint outTokenU) internal returns (uint outTokenP) { address _tokenP = tokenP; - ( - address tokenU, // Assume DAI. - address tokenS, // Assume ETH. - , // Assume tokenR and we don't need it in this function. - uint256 base, - uint256 price, - uint256 expiry - ) = IPrime(_tokenP).prime(); - - // Optimistically mint tokenP. - - // outTokenU = inTokenS * Quantity of tokenU (base) / Quantity of tokenS (price). - // Units = tokenS * tokenU / tokenS = tokenU. - uint256 outTokenU = inTokenS.mul(base).div(price); - - // Transfer tokenU (assume DAI) to option contract using Pool funds. - // We do this because the mint function in the Prime contract will check the balance, - // against its previously cached balance. The difference is the amount of tokens that were - // deposited, which determines how many Primes to mint. + address tokenU = IPrime(_tokenP).tokenU(); require(IERC20(tokenU).balanceOf(address(this)) >= outTokenU, "ERR_BAL_UNDERLYING"); - (bool transferU) = IERC20(tokenU).transfer(_tokenP, outTokenU); - - // Mint Prime and Prime Redeem to this contract. - // If outTokenU is zero because the numerator is smaller than the denominator, - // or because the inTokenS is 0, the mint function will revert. This is because - // the mint function only works when tokens are sent into the Prime contract. - (uint256 inTokenP, ) = IPrime(_tokenP).mint(address(this)); - - // Calculate premium. Denominated in tokenU PER tokenS 'covered'. - (uint256 premium) = IPrimeOracle(oracle).calculatePremium( - tokenU, - tokenS, - volatility, - base, - price, - expiry - ); - - // Calculate total premium to pay, total premium = premium per tokenS * inTokenS. - // Units = tokenS * (tokenU / tokenS) / 10^18 units = tokenU. - premium = inTokenS.mul(premium).div(ONE_ETHER); - require(premium > 0, "ERR_PREMIUM_ZERO"); + // Transfer underlying tokens to option contract. + IERC20(tokenU).transfer(_tokenP, outTokenU); - // Updates the volatility global state variable. - volatility = calculateVolatilityProxy(_tokenP); - - // Pulls payment in tokenU from msg.sender and then pushes tokenP (option). - // WARNING: Two calls to untrusted addresses. - require(IERC20(tokenU).balanceOf(msg.sender) >= premium, "ERR_BAL_UNDERLYING"); - require(IERC20(_tokenP).balanceOf(address(this)) >= inTokenP, "ERR_BAL_PRIME"); - emit Buy(msg.sender, inTokenS, outTokenU, premium); - (bool received) = IERC20(tokenU).transferFrom(msg.sender, address(this), premium); - return received && transferU && IERC20(_tokenP).transfer(msg.sender, inTokenP); + // Mint Prime and Prime Redeem to the receiver. + (outTokenP, ) = IPrime(_tokenP).mint(address(this)); } - /** - * @dev Sell Prime options back to the pool. - * @notice The pool buys options at a discounted rate based on the current premium price. - * @param inTokenP The amount of Prime option tokens that are being sold. - */ - function sell( - uint256 inTokenP - ) - external - nonReentrant - returns (bool) + function _exercise(address receiver, uint outTokenS, uint inTokenP) + internal + returns (uint outTokenU) { - // Store in memory for gas savings. address _tokenP = tokenP; - ( - address tokenU, // Assume DAI. - address tokenS, // Assume ETH. - address tokenR, // Assume tokenR. - uint256 base, - uint256 price, - uint256 expiry - ) = IPrime(_tokenP).prime(); - - // Check tokenP balance. - require( - IERC20(_tokenP).balanceOf(msg.sender) >= inTokenP && - inTokenP > 0, - "ERR_BAL_PRIME" - ); - - // Calculate the current premium price. - (uint256 premium) = IPrimeOracle(oracle).calculatePremium( - tokenU, - tokenS, - volatility, - base, - price, - expiry - ); - - // Calculate discounted premium. This is the value of tokenU per tokenS covered. - premium = premium.sub(premium.div(DISCOUNT_RATE)); - - // Calculate total premium. - // Units: tokenU * (tokenU / tokenS) / 10^18 units = total quantity tokenU price. - premium = inTokenP.mul(premium).div(ONE_ETHER); - - // Check to see if pool has the premium to pay out. - require(IERC20(tokenU).balanceOf(address(this)) >= premium, "ERR_BAL_UNDERLYING"); - - // Calculate amount of redeem needed to close position with inTokenU. - uint256 redeem = inTokenP.mul(price).div(base); - - // Transfer redeem to prime token optimistically. - IERC20(tokenR).transfer(tokenP, redeem); + // Transfer strike token to option contract. + IERC20(IPrime(_tokenP).tokenS()).transfer(_tokenP, outTokenS); - // Transfer prime token to prime contract optimistically. - require(IERC20(_tokenP).transferFrom(msg.sender, tokenP, inTokenP), "ERR_TRANSFER_IN_PRIME"); + // Transfer prime token to option contract. + IERC20(_tokenP).transferFrom(msg.sender, _tokenP, inTokenP); - // Call the close function to have the transferred prime and redeem tokens burned. - // Returns tokenU. - IPrime(_tokenP).close(address(this)); - - // Pay out the total premium to the seller. - emit Sell(msg.sender, inTokenP, premium); - return IERC20(tokenU).transfer(msg.sender, premium); + // Call the exercise function to receive underlying tokens. + (, outTokenU) = IPrime(_tokenP).exercise(receiver, inTokenP, new bytes(0)); } - /** - * @dev Calculates the Pool's Utilization to use as a proxy for volatility. - * @notice If Pool is not utilized at all, the default volatility is 250. - */ - function calculateVolatilityProxy(address _tokenP) - public - view - returns (uint256 _volatility) - { - (uint256 utilized) = totalUtilized(_tokenP); - uint256 totalBalance = totalPoolBalance(_tokenP); - if(totalBalance > 0) _volatility = utilized.mul(ONE_ETHER).div(totalBalance); // Volatility with 1e18 decimals. - if(_volatility < MIN_VOLATILITY) { - _volatility = 1000; - } else _volatility = _volatility.div(MIN_VOLATILITY).add(1000); - - } - - /** - * @dev Calculates the amount of utilized tokenU assets outstanding. - */ - function totalUtilized(address _tokenP) - public - view - returns (uint256 utilized) - { - // Assume tokenR is proportional to tokenS (WETH) at a 1:1 ratio. - // TokenR is always minted proportionally to the ratio between tokenU and tokenS (strike price). - // Assume a ratio of 200 DAI per 1 ETH. - // If 200 tokenU is used to mint a Prime, it will return 1 tokenR. - // 1 tokenR * 200 (base) / 1 (price) = 200 tokenU utilized. - // The returned value for `utilized` should always be greater than 1. - // TokenR is redeemable to tokenS at a 1:1 ratio (1 tokenR can be redeemed for 1 WETH). - // The utilized amount of tokenU is therefore this calculation: - // (tokenR = tokenS = WETH) * Quantity of tokenU (base) / Quantity of tokenS (price). - ( , , address tokenR, , uint256 price, ) = IPrime(_tokenP).prime(); - (uint256 oraclePrice) = marketRatio(_tokenP); - utilized = IERC20(tokenR).balanceOf(address(this)).mul(oraclePrice).div(price); - } - - /** - * @dev Returns the contract balance of tokenU. - */ - function totalUnutilized(address _tokenP) public view returns (uint256 balanceU) { - // The unutilized balance is equal to the balance of tokenU held by the pool. - balanceU = IERC20(IPrime(_tokenP).tokenU()).balanceOf(address(this)); - } - - /** - * @dev Returns to total balance of tokenU that the contract has accross accounts. - * @notice Total Balance = utilized + unutilized. Utilized = underwritten tokenU. - */ - function totalPoolBalance(address _tokenP) public view returns (uint256 totalBalance) { - // Unutilized is the balance of tokenU in the contract. Utilized is outstanding tokenU. - // Utilized assets are held in the Prime contract waiting to be exercised or expired. - totalBalance = totalUnutilized(_tokenP).add(totalUtilized(_tokenP)); + function _redeem(address receiver, uint outTokenR) internal returns (uint inTokenS) { + address _tokenP = tokenP; + // Push tokenR to _tokenP so we can call redeem() and pull tokenS. + IERC20(IPrime(_tokenP).tokenR()).transfer(_tokenP, outTokenR); + // Call redeem function to pull tokenS. + inTokenS = IPrime(_tokenP).redeem(receiver); } - /** - * @dev Utility function to get the market ratio of tokenS denominated in tokenU. - * @notice Assumes the getUnderlyingPrice function call from the oracle never returns - * a value greater than 1e36 (MANTISSA). - */ - function marketRatio(address _tokenP) public view returns(uint256 oraclePrice) { - address _tokenU = IPrime(_tokenP).tokenU(); - address token = _tokenU == WETH ? IPrime(_tokenP).tokenS() : _tokenU; - oraclePrice = MANTISSA.div(IPrimeOracle(oracle).marketPrice(token)); - } + function _close(uint outTokenR, uint inTokenP) internal returns (uint outTokenU) { + address _tokenP = tokenP; + // Transfer redeem to the option contract. + IERC20(IPrime(_tokenP).tokenR()).transfer(_tokenP, outTokenR); - /** - * @dev Utility function to send ethers safely. - */ - function sendEther(address to, uint256 amount) private returns (bool) { - (bool success, ) = to.call.value(amount)(""); - require(success, "ERR_SEND_ETHER"); - return success; + // Transfer prime token to prime contract. + IERC20(_tokenP).transferFrom(msg.sender, _tokenP, inTokenP); + + // Call the close function to have the receive underlying tokens. + (,,outTokenU) = IPrime(_tokenP).close(address(this)); } - function balances() public override view returns(uint balanceU, uint balanceR) { - balanceU = IERC20(IPrime(tokenP).tokenU()).balanceOf(address(this)); - balanceR = IERC20(IPrime(tokenP).tokenR()).balanceOf(address(this)); + function balances() public override view returns (uint balanceU, uint balanceR) { + (address tokenU, , address tokenR) = IPrime(tokenP).getTokens(); + balanceU = IERC20(tokenU).balanceOf(address(this)); + balanceR = IERC20(tokenR).balanceOf(address(this)); } -} - - \ No newline at end of file +} \ No newline at end of file diff --git a/contracts/extensions/PrimePoolV1.sol b/contracts/extensions/PrimePoolV1.sol deleted file mode 100644 index 3d302232..00000000 --- a/contracts/extensions/PrimePoolV1.sol +++ /dev/null @@ -1,85 +0,0 @@ -pragma solidity ^0.6.2; - -/** - * @title Vanilla Option Pool - * @author Primitive - */ - -import "../interfaces/IPrime.sol"; -import "../interfaces/IPrimePool.sol"; -import "@openzeppelin/contracts/math/SafeMath.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/Pausable.sol"; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; - -contract PrimePoolV1 is IPrimePool, Ownable, Pausable, ReentrancyGuard, ERC20 { - using SafeMath for uint; - - uint public constant MIN_LIQUIDITY = 10**4; - - address public override factory; - address public override tokenP; - - event Deposit(address indexed from, uint inTokenU, uint outTokenPULP); - event Withdraw(address indexed from, uint inTokenPULP, uint outTokenU); - - constructor(address _tokenP, address _factory) - public - ERC20("Primitive V1 Pool", "PULP") - { - tokenP = _tokenP; - factory = _factory; - } - - function kill() public override onlyOwner returns (bool) { paused() ? _unpause() : _pause(); } - - /** - * @dev Private function to mint tokenPULP to depositor. - */ - function _addLiquidity(address _tokenP, address to, uint inTokenU, uint totalBalance) - internal - returns (uint outTokenPULP) - { - // Mint LP tokens proportional to the Total LP Supply and Total Pool Balance. - uint _totalSupply = totalSupply(); - uint base = IPrime(_tokenP).base(); - uint price = IPrime(_tokenP).price(); - - // If liquidity is not intiialized, mint the initial liquidity. - if(_totalSupply == 0) { - outTokenPULP = inTokenU.mul(IPrime(_tokenP).price()).div(1 ether); - } else { - outTokenPULP = inTokenU.mul(_totalSupply).div(totalBalance); - } - - require(outTokenPULP > 0, "ERR_ZERO_LIQUIDITY"); - _mint(to, outTokenPULP); - emit Deposit(to, inTokenU, outTokenPULP); - } - - function _removeLiquidity(address to, uint inTokenPULP, uint totalBalance) - internal - returns (uint outTokenU) - { - // Check tokenPULP balance. - require(balanceOf(to) >= inTokenPULP && inTokenPULP > 0, "ERR_BAL_PULP"); - - // Store for gas savings. - uint _totalSupply = totalSupply(); - - // Calculate output amounts. - outTokenU = inTokenPULP.mul(totalBalance).div(_totalSupply); - require(outTokenU > 0, "ERR_ZERO"); - // Burn tokenPULP. - _burn(to, inTokenPULP); - // Push outTokenU to `to` address. - emit Withdraw(to, inTokenPULP, outTokenU); - } - - function balances() public override view returns (uint balanceU, uint balanceR) { - (address tokenU, , address tokenR) = IPrime(tokenP).getTokens(); - balanceU = IERC20(tokenU).balanceOf(address(this)); - balanceR = IERC20(tokenR).balanceOf(address(this)); - } -} \ No newline at end of file diff --git a/contracts/extensions/PrimeTrader.sol b/contracts/extensions/PrimeTrader.sol index e79a0071..19d951de 100644 --- a/contracts/extensions/PrimeTrader.sol +++ b/contracts/extensions/PrimeTrader.sol @@ -1,8 +1,8 @@ pragma solidity ^0.6.2; /** - * @title Primitive's Trader Contract - * @notice Safely interacts with the Prime Vanilla Option Primitive + * @title Trader + * @notice Abstracts the interfacing with the protocol for ease-of-use. * @author Primitive */ @@ -13,7 +13,7 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; contract PrimeTrader is IPrimeTrader, ReentrancyGuard { - using SafeMath for uint256; + using SafeMath for uint; address payable public weth; @@ -22,144 +22,90 @@ contract PrimeTrader is IPrimeTrader, ReentrancyGuard { event Redeem(address indexed from, uint256 inTokenR); event Close(address indexed from, uint256 inTokenP); - constructor (address payable _weth) public { - weth = _weth; - } + constructor (address payable _weth) public { weth = _weth; } /** * @dev Mint Primes by depositing tokenU. * @notice Also mints Prime Redeem tokens. Calls msg.sender with transferFrom. - * @param tokenP The address of the Prime Option to trade with. + * @param tokenP The address of the Prime Option contract. * @param amount Quantity of Prime options to mint and tokenU to deposit. * @param receiver The newly minted tokens are sent to the receiver address. */ - function safeMint(IPrime tokenP, uint256 amount, address receiver) + function safeMint(IPrime tokenP, uint amount, address receiver) external - nonReentrant override - returns (uint256 inTokenU, uint256 outTokenR) + nonReentrant + returns (uint inTokenU, uint outTokenR) { require(amount > 0, "ERR_ZERO"); - address tokenU = tokenP.tokenU(); - verifyBalance( - IERC20(tokenU).balanceOf(msg.sender), - amount, - "ERR_BAL_UNDERLYING" - ); - require( - IERC20(tokenU).transferFrom(msg.sender, address(tokenP), amount), - "ERR_TRANSFER_IN_FAIL" - ); + IERC20(tokenP.tokenU()).transferFrom(msg.sender, address(tokenP), amount); (inTokenU, outTokenR) = tokenP.mint(receiver); emit Mint(msg.sender, inTokenU, outTokenR); } /** - * @dev Swaps tokenS to tokenU using ratio as the exchange rate. + * @dev Swaps tokenS to tokenU using the strike ratio as the exchange rate. * @notice Burns Prime, contract receives tokenS, user receives tokenU. - * Calls msg.sender with transferFrom. - * @param amount Quantity of Primes to use to swap. + * @param tokenP The address of the Prime Option contract. + * @param amount Quantity of Prime options to exercise. + * @param receiver The underlying tokens are sent to the receiver address. */ - function safeExercise( - IPrime tokenP, - uint256 amount, - address receiver - ) + function safeExercise(IPrime tokenP, uint amount, address receiver) external + override nonReentrant - override returns (uint256 inTokenS, uint256 inTokenP, uint256 outTokenU) + returns (uint inTokenS, uint inTokenP) { require(amount > 0, "ERR_ZERO"); - address tokenS = tokenP.tokenS(); - verifyBalance( - IERC20(address(tokenP)).balanceOf(msg.sender), - amount, - "ERR_BAL_PRIME" - ); - - inTokenS = amount.mul(tokenP.price()).div(tokenP.base()); - verifyBalance( - IERC20(tokenS).balanceOf(msg.sender), - inTokenS, - "ERR_BAL_STRIKE" - ); - (bool inTransferS) = IERC20(tokenS).transferFrom(msg.sender, address(tokenP), inTokenS); - (bool inTransferP) = IERC20(address(tokenP)).transferFrom(msg.sender, address(tokenP), amount); - require(inTransferS && inTransferP, "ERR_TRANSFER_IN_FAIL"); + require(IERC20(address(tokenP)).balanceOf(msg.sender) >= amount, "ERR_BAL_PRIME"); + inTokenS = amount.add(amount.div(1000)).mul(tokenP.price()).div(tokenP.base()); + //uint fee = inTokenS.div(1000); + require(IERC20(tokenP.tokenS()).balanceOf(msg.sender) >= inTokenS, "ERR_BAL_STRIKE"); + IERC20(tokenP.tokenS()).transferFrom(msg.sender, address(tokenP), inTokenS); + IERC20(address(tokenP)).transferFrom(msg.sender, address(tokenP), amount); (inTokenS, inTokenP) = tokenP.exercise(receiver, amount, new bytes(0)); } /** * @dev Burns Prime Redeem tokens to withdraw available tokenS. - * @notice inTokenR = outTokenS - * @param amount Quantity of Prime Redeem to spend. + * @notice inTokenR = outTokenS. + * @param tokenP The address of the Prime Option contract. + * @param amount Quantity of Redeems to burn. + * @param receiver The strike tokens are sent to the receiver address. */ - function safeRedeem( - IPrime tokenP, - uint256 amount, - address receiver - ) + function safeRedeem(IPrime tokenP, uint amount, address receiver) external + override nonReentrant - override returns (uint256 inTokenR) + returns (uint inTokenR) { require(amount > 0, "ERR_ZERO"); - address tokenS = tokenP.tokenS(); - address tokenR = tokenP.tokenR(); - - verifyBalance( - IERC20(tokenR).balanceOf(msg.sender), - amount, - "ERR_BAL_REDEEM" - ); - - // There can be the case there is no available tokenS to redeem. - // This is the first verification of a tokenS balance to draw from. - // There is a second verification in the redeem() function. - verifyBalance( - IERC20(tokenS).balanceOf(address(tokenP)), - amount, - "ERR_BAL_STRIKE" - ); - IERC20(tokenR).transferFrom(msg.sender, address(tokenP), amount); + require(IERC20(tokenP.tokenR()).balanceOf(msg.sender) >= amount, "ERR_BAL_REDEEM"); + // There can be the case there is no available tokenS to redeem, causing a revert. + IERC20(tokenP.tokenR()).transferFrom(msg.sender, address(tokenP), amount); (inTokenR) = tokenP.redeem(receiver); emit Redeem(msg.sender, inTokenR); } /** * @dev Burn Prime and Prime Redeem tokens to withdraw tokenU. - * @notice Takes paramter for quantity of Primes to burn. - * The Prime Redeems to burn is equal to the Primes * ratio. + * @notice The Prime Redeems to burn is equal to the Primes * strike ratio. * inTokenP = inTokenR / strike ratio = outTokenU + * @param tokenP The address of the Prime Option contract. * @param amount Quantity of Primes to burn. + * @param receiver The underlying tokens are sent to the receiver address. */ - function safeClose( - IPrime tokenP, - uint256 amount, - address receiver - ) + function safeClose(IPrime tokenP, uint amount, address receiver) external + override nonReentrant - override returns (uint256 inTokenR, uint256 inTokenP, uint256 outTokenU) + returns (uint inTokenR, uint inTokenP, uint outTokenU) { require(amount > 0, "ERR_ZERO"); - address tokenR = tokenP.tokenR(); - + require(IERC20(address(tokenP)).balanceOf(msg.sender) >= amount, "ERR_BAL_PRIME"); inTokenR = amount.mul(tokenP.price()).div(tokenP.base()); - - verifyBalance( - IERC20(tokenR).balanceOf(msg.sender), - inTokenR, - "ERR_BAL_REDEEM" - ); - - verifyBalance( - IERC20(address(tokenP)).balanceOf(msg.sender), - amount, - "ERR_BAL_PRIME" - ); - - IERC20(tokenR).transferFrom(msg.sender, address(tokenP), inTokenR); + require(IERC20(tokenP.tokenR()).balanceOf(msg.sender) >= inTokenR, "ERR_BAL_REDEEM"); + IERC20(tokenP.tokenR()).transferFrom(msg.sender, address(tokenP), inTokenR); IERC20(address(tokenP)).transferFrom(msg.sender, address(tokenP), amount); (inTokenR, inTokenP, outTokenU) = tokenP.close(receiver); emit Close(msg.sender, inTokenP); @@ -167,43 +113,22 @@ contract PrimeTrader is IPrimeTrader, ReentrancyGuard { /** * @dev Burn Prime Redeem tokens to withdraw tokenU and tokenS from expired options. - * @notice Takes paramter for quantity of Primes to burn. - * The Prime Redeems to burn is equal to the Primes * ratio. - * @param amount Quantity of tokenU to withdraw. + * @param tokenP The address of the Prime Option contract. + * @param amount Quantity of Redeems to burn. + * @param receiver The underlying tokens are sent to the receiver address. */ - function safeUnwind( - IPrime tokenP, - uint256 amount, - address receiver - ) + function safeUnwind(IPrime tokenP, uint amount, address receiver) external + override nonReentrant - override returns (uint256 inTokenR, uint256 inTokenP, uint256 outTokenU) + returns (uint inTokenR, uint inTokenP, uint outTokenU) { require(amount > 0, "ERR_ZERO"); require(tokenP.expiry() < block.timestamp, "ERR_NOT_EXPIRED"); - address tokenR = tokenP.tokenR(); - inTokenR = amount.mul(tokenP.price()).div(tokenP.base()); - - verifyBalance( - IERC20(tokenR).balanceOf(msg.sender), - inTokenR, - "ERR_BAL_REDEEM" - ); - - IERC20(tokenR).transferFrom(msg.sender, address(tokenP), inTokenR); + require(IERC20(tokenP.tokenR()).balanceOf(msg.sender) >= inTokenR, "ERR_BAL_REDEEM"); + IERC20(tokenP.tokenR()).transferFrom(msg.sender, address(tokenP), inTokenR); (inTokenR, inTokenP, outTokenU) = tokenP.close(receiver); emit Close(msg.sender, inTokenP); } - - function verifyBalance( - uint256 balance, - uint256 minBalance, - string memory errorCode - ) internal pure { - minBalance == 0 ? - require(balance > minBalance, errorCode) : - require(balance >= minBalance, errorCode); - } } \ No newline at end of file diff --git a/contracts/interfaces/IAggregator.sol b/contracts/interfaces/IAggregator.sol new file mode 100644 index 00000000..ab42913f --- /dev/null +++ b/contracts/interfaces/IAggregator.sol @@ -0,0 +1,9 @@ +pragma solidity ^0.6.2; + +interface IAggregator { + function latestAnswer() external view returns (int256); + function latestTimestamp() external view returns (uint256); + function latestRound() external view returns (uint256); + function getAnswer(uint256 roundId) external view returns (int256); + function getTimestamp(uint256 roundId) external view returns (uint256); +} \ No newline at end of file diff --git a/contracts/interfaces/IFactory.sol b/contracts/interfaces/IFactory.sol new file mode 100644 index 00000000..49c184ac --- /dev/null +++ b/contracts/interfaces/IFactory.sol @@ -0,0 +1,8 @@ +pragma solidity ^0.6.2; + +interface IFactory { + function deploy(address tokenU, address tokenS, uint base, uint price, uint expiry) + external returns (address); + function kill(address prime) external; + function initialize(address prime, address redeem) external; +} \ No newline at end of file diff --git a/contracts/interfaces/IPrime.sol b/contracts/interfaces/IPrime.sol index 660d39d9..32b38b98 100644 --- a/contracts/interfaces/IPrime.sol +++ b/contracts/interfaces/IPrime.sol @@ -27,7 +27,6 @@ interface IPrime { function cacheU() external view returns (uint); function cacheS() external view returns (uint); function factory() external view returns (address); - function maxDraw() external view returns (uint draw); function getCaches() external view returns (uint _cacheU, uint _cacheS); function getTokens() external view returns (address _tokenU, address _tokenS, address _tokenR); function prime() external view returns ( @@ -38,4 +37,6 @@ interface IPrime { uint _price, uint _expiry ); + function initTokenR(address _tokenR) external; + function FEE() external view returns (uint); } \ No newline at end of file diff --git a/contracts/interfaces/IPrimeOracle.sol b/contracts/interfaces/IPrimeOracle.sol index 63b5b326..d6b8d1bc 100644 --- a/contracts/interfaces/IPrimeOracle.sol +++ b/contracts/interfaces/IPrimeOracle.sol @@ -1,6 +1,6 @@ pragma solidity ^0.6.2; interface IPrimeOracle { - function marketPrice(address tokenU) external view returns (uint256 market); + function marketPrice() external view returns (uint256 market); function calculateIntrinsic( address tokenU, address tokenS, diff --git a/contracts/interfaces/IPrimePerpetual.sol b/contracts/interfaces/IPrimePerpetual.sol index b2aba0c7..492ac343 100644 --- a/contracts/interfaces/IPrimePerpetual.sol +++ b/contracts/interfaces/IPrimePerpetual.sol @@ -7,7 +7,7 @@ interface IPrimePerpetual { function redeem(uint inTokenP) external returns (bool); function exercise(uint inTokenP) external returns (bool); function interestBalances() external view returns (uint balanceU, uint balanceR); - function totalBalance() external view returns (uint totalBalance); + function totalBalance() external view returns (uint poolBalance); function fee() external view returns (uint); function cusdc() external view returns (address); function cdai() external view returns (address); diff --git a/contracts/interfaces/IPrimeTrader.sol b/contracts/interfaces/IPrimeTrader.sol index cc277075..091e39de 100644 --- a/contracts/interfaces/IPrimeTrader.sol +++ b/contracts/interfaces/IPrimeTrader.sol @@ -3,26 +3,25 @@ pragma solidity ^0.6.2; import "./IPrime.sol"; interface IPrimeTrader { - function safeMint(IPrime tokenP, uint256 amount, address receiver) external returns ( - uint256 inTokenU, - uint256 outTokenR + function safeMint(IPrime tokenP, uint amount, address receiver) external returns ( + uint inTokenU, + uint outTokenR ); - function safeExercise(IPrime tokenP, uint256 amount, address receiver) external returns ( - uint256 inTokenS, - uint256 inTokenP, - uint256 outTokenU + function safeExercise(IPrime tokenP, uint amount, address receiver) external returns ( + uint inTokenS, + uint inTokenP ); - function safeRedeem(IPrime tokenP, uint256 amount, address receiver) external returns ( - uint256 inTokenR + function safeRedeem(IPrime tokenP, uint amount, address receiver) external returns ( + uint inTokenR ); - function safeClose(IPrime tokenP, uint256 amount, address receiver) external returns ( - uint256 inTokenR, - uint256 inTokenP, - uint256 outTokenU + function safeClose(IPrime tokenP, uint amount, address receiver) external returns ( + uint inTokenR, + uint inTokenP, + uint outTokenU ); - function safeUnwind(IPrime tokenP, uint256 amount, address receiver) external returns ( - uint256 inTokenR, - uint256 inTokenP, - uint256 outTokenU + function safeUnwind(IPrime tokenP, uint amount, address receiver) external returns ( + uint inTokenR, + uint inTokenP, + uint outTokenU ); } \ No newline at end of file diff --git a/contracts/interfaces/IRegistry.sol b/contracts/interfaces/IRegistry.sol new file mode 100644 index 00000000..fe4106be --- /dev/null +++ b/contracts/interfaces/IRegistry.sol @@ -0,0 +1,10 @@ +pragma solidity ^0.6.2; + +interface IRegistry { + function deployOption(address tokenU, address tokenS, uint base, uint price, uint expiry) + external returns (address); + function kill(address prime) external; + function initialize(address _factory, address _factoryRedeem) external; + function optionsLength() external view returns (uint len); + function setFeeReceiver(address _feeReceiver) external; +} \ No newline at end of file diff --git a/contracts/PrimeOption.sol b/contracts/primitives/PrimeOption.sol similarity index 71% rename from contracts/PrimeOption.sol rename to contracts/primitives/PrimeOption.sol index a2fd7352..2b087060 100644 --- a/contracts/PrimeOption.sol +++ b/contracts/primitives/PrimeOption.sol @@ -5,10 +5,10 @@ pragma solidity ^0.6.2; * @author Primitive */ -import "./Primitives.sol"; -import "./interfaces/IPrime.sol"; -import "./interfaces/IPrimeRedeem.sol"; -import "./interfaces/IPrimeFlash.sol"; +import "../Primitives.sol"; +import "../interfaces/IPrime.sol"; +import "../interfaces/IPrimeRedeem.sol"; +import "../interfaces/IPrimeFlash.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; @@ -19,11 +19,11 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { Primitives.Option public option; + uint public override constant FEE = 1000; uint public override cacheU; uint public override cacheS; address public override tokenR; address public override factory; - uint public constant FEE = 1000; event Mint(address indexed from, uint outTokenP, uint outTokenR); event Exercise(address indexed from, uint outTokenU, uint inTokenS); @@ -56,16 +56,15 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { _; } - // Called by factory on deployment once. - function initTokenR(address _tokenR) public { + function initTokenR(address _tokenR) external override { require(msg.sender == factory, "ERR_NOT_OWNER"); tokenR = _tokenR; } - /* function kill() public { + function kill() external { require(msg.sender == factory, "ERR_NOT_OWNER"); paused() ? _unpause() : _pause(); - } */ + } /* === ACCOUNTING === */ @@ -111,12 +110,8 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { /* === FUNCTIONS === */ /** - * @dev Core function to mint new Prime ERC-20 Options. - * @notice inTokenU = outTokenP, inTokenU * ratio = outTokenR - * Checks the balance of the contract against the token's 'cache', - * The difference is the amount of tokenU sent into the contract. - * The difference determines how many Primes and Redeems to mint. - * Only callable when the option is not expired. + * @dev Mints options at a 1:1 ratio to underlying token deposits. + * @notice inTokenU = outTokenP, inTokenU / strike ratio = outTokenR. * @param receiver The newly minted tokens are sent to the receiver address. */ function mint(address receiver) @@ -134,12 +129,8 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { // Mint inTokenU equal to the difference between current and cached balance of tokenU. inTokenU = balanceU.sub(cacheU); - - // Make sure outToken is not 0. - require(inTokenU.mul(price) >= base, "ERR_ZERO"); - - // Mint outTokenR equal to tokenU * ratio FIX - FURTHER CHECKS outTokenR = inTokenU.mul(price).div(base); + require(outTokenR > 0, "ERR_ZERO"); // Mint the tokens. IPrimeRedeem(tokenR).mint(receiver, outTokenR); @@ -151,13 +142,11 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { } /** - * @dev Swap tokenS to tokenU at a rate of tokenS / ratio = tokenU. - * @notice inTokenS / ratio = outTokenU && inTokenP >= outTokenU - * Checks the balance against the previously cached balance. - * The difference is the amount of tokenS sent into the contract. - * The difference determines how much tokenU to send out. - * Only callable when the option is not expired. + * @dev Sends out underlying tokens then checks to make sure they are returned or paid for. + * @notice If the underlying tokens are returned, only the fee has to be paid. * @param receiver The outTokenU is sent to the receiver address. + * @param outTokenU Quantity of underlyings to transfer to receiver optimistically. + * @param data Passing in any abritrary data will trigger the flash callback function. */ function exercise(address receiver, uint outTokenU, bytes calldata data) external @@ -173,15 +162,10 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { // Require outTokenU > 0, and cacheU > outTokenU. require(outTokenU > 0, "ERR_ZERO"); - require(_cacheU >= outTokenU, "ERR_BAL_UNDERLYING"); - - // Take fee out of outTokenU. - uint _fee = outTokenU.div(FEE); - outTokenU = outTokenU.sub(_fee); + require(IERC20(_tokenU).balanceOf(address(this)) >= outTokenU, "ERR_BAL_UNDERLYING"); // Optimistically transfer out tokenU. IERC20(_tokenU).transfer(receiver, outTokenU); - IERC20(_tokenU).transfer(factory, _fee); if (data.length > 0) IPrimeFlash(receiver).primitiveFlash(receiver, outTokenU, data); // Store in memory for gas savings. @@ -190,22 +174,25 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { // Calculate the Differences. inTokenS = balanceS.sub(_cacheS); - uint inTokenU = balanceU.sub(_cacheU.sub(outTokenU.add(_fee))); - - // Require inTokenS to be greater than zero to at least pay the fee. + uint inTokenU = balanceU.sub(_cacheU.sub(outTokenU)); // will be > 0 if tokenU returned. require(inTokenS > 0 || inTokenU > 0, "ERR_ZERO"); - // Calculate the net amount of tokenU sent out of the contract. - uint netOutTokenU = inTokenU > outTokenU ? 0 : outTokenU.sub(inTokenU); + // Add the fee to the total required payment. + //outTokenU = outTokenU.add(outTokenU.div(FEE)); + + uint feeToPay = outTokenU.div(FEE); + + // Calculate the remaining amount of tokenU that needs to be paid for. + uint remainder = inTokenU > outTokenU ? 0 : outTokenU.sub(inTokenU); // Calculate the expected payment of tokenS. - uint payment = netOutTokenU.mul(option.price).div(option.base); + uint payment = remainder.add(feeToPay).mul(option.price).div(option.base); // Assumes the cached tokenP balance is 0. inTokenP = balanceOf(address(this)); // Enforce the invariants. - require(inTokenS >= payment && inTokenP >= netOutTokenU, "ERR_BAL_INPUT"); + require(inTokenS >= payment && inTokenP >= remainder, "ERR_BAL_INPUT"); // Burn the Prime options at a 1:1 ratio to outTokenU. _burn(address(this), inTokenP); @@ -217,12 +204,7 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { /** * @dev Burns tokenR to withdraw tokenS at a ratio of 1:1. - * @notice inTokenR = outTokenS - * Should only be called by a contract that checks the balances to be sent correctly. - * Checks the tokenR balance against the previously cached tokenR balance. - * The difference is the amount of tokenR sent into the contract. - * The difference is equal to the amount of tokenS sent out. - * Callable even when expired. + * @notice inTokenR = outTokenS. Only callable when strike tokens are in the contract. * @param receiver The inTokenR quantity of tokenS is sent to the receiver address. */ function redeem(address receiver) @@ -233,8 +215,6 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { { address _tokenS = option.tokenS; address _tokenR = tokenR; - - // Current balances. uint balanceS = IERC20(_tokenS).balanceOf(address(this)); uint balanceR = IERC20(_tokenR).balanceOf(address(this)); @@ -260,14 +240,8 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { } /** - * @dev Burn Prime and Prime Redeem tokens to withdraw tokenU. - * @notice inTokenR / ratio = outTokenU && inTokenP >= outTokenU - * Checks the balances against the previously cached balances. - * The difference between the tokenR balance and cache is the inTokenR. - * The balance of tokenP is equal to the inTokenP. - * The outTokenU is equal to the inTokenR / ratio. - * The contract requires the inTokenP >= outTokenU and the balanceU >= outTokenU. - * The contract burns the inTokenR and inTokenP amounts. + * @dev Burn Prime and Prime Redeem tokens to withdraw underlying tokens. + * @notice inTokenR / ratio = outTokenU && inTokenP >= outTokenU. * @param receiver The outTokenU is sent to the receiver address. */ function close(address receiver) @@ -276,11 +250,9 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { nonReentrant returns (uint inTokenR, uint inTokenP, uint outTokenU) { - // Stores addresses locally for gas savings. + // Stores addresses and balances locally for gas savings. address _tokenU = option.tokenU; address _tokenR = tokenR; - - // Current balances. uint balanceU = IERC20(_tokenU).balanceOf(address(this)); uint balanceR = IERC20(_tokenR).balanceOf(address(this)); uint balanceP = balanceOf(address(this)); @@ -289,35 +261,29 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { inTokenR = balanceR; // The quantity of tokenU to send out it still determined by the amount of inTokenR. + // inTokenR is in units of strike tokens, which is converted to underlying tokens + // by multiplying inTokenR by the strike ratio: base / price. // This outTokenU amount is checked against inTokenP. // inTokenP must be greater than or equal to outTokenU. // balanceP must be greater than or equal to outTokenU. // Neither inTokenR or inTokenP can be zero. outTokenU = inTokenR.mul(option.base).div(option.price); - // Assumes the cached balance is 0. - // This is because the close function burns the Primes received. - // Only external transfers will be able to send Primes to this contract. - // Close() and swap() are the only function that check for the Primes balance. + // Assumes the cached balance is 0 so inTokenP = balance of tokenP. // If option is expired, tokenP does not need to be sent in. Only tokenR. inTokenP = option.expiry > block.timestamp ? balanceP : outTokenU; - require(inTokenR > 0 && inTokenP > 0, "ERR_ZERO"); require(inTokenP >= outTokenU && balanceU >= outTokenU, "ERR_BAL_UNDERLYING"); - // Burn inTokenR and inTokenP. + // Burn Prime tokens. Prime tokens are only sent into contract when not expired. if(option.expiry > block.timestamp) { _burn(address(this), inTokenP); } - // Send outTokenU to user. + // Send underlying tokens to user. + // Burn tokenR held in the contract. // User does not receive extra tokenU if there was extra tokenP in the contract. // User receives outTokenU proportional to inTokenR. - // Amount of inTokenP must be greater than outTokenU. - // If tokenP was sent to the contract from an external call, - // a user could send only tokenR and receive the proportional amount of tokenU, - // as long as the amount of outTokenU is less than or equal to - // the balance of tokenU and tokenP. IPrimeRedeem(_tokenR).burn(address(this), inTokenR); require( IERC20(_tokenU).transfer(receiver, outTokenU), @@ -370,12 +336,4 @@ contract PrimeOption is IPrime, ERC20, ReentrancyGuard, Pausable { _price = _prime.price; _expiry = _prime.expiry; } - - /** - * @dev Utility function to get the max withdrawable tokenS amount of msg.sender. - */ - function maxDraw() public view override returns (uint draw) { - uint balanceR = IERC20(tokenR).balanceOf(msg.sender); - draw = cacheS > balanceR ? balanceR : cacheS; - } } \ No newline at end of file diff --git a/contracts/PrimeRedeem.sol b/contracts/primitives/PrimeRedeem.sol similarity index 91% rename from contracts/PrimeRedeem.sol rename to contracts/primitives/PrimeRedeem.sol index 34cb52e8..cb273a3f 100644 --- a/contracts/PrimeRedeem.sol +++ b/contracts/primitives/PrimeRedeem.sol @@ -5,8 +5,8 @@ pragma solidity ^0.6.2; * @author Primitive */ -import "./interfaces/IPrimeRedeem.sol"; -import "./interfaces/IPrimitiveFactory.sol"; +import "../interfaces/IPrimeRedeem.sol"; +import "../interfaces/IPrimitiveFactory.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; diff --git a/contracts/registry/Factory.sol b/contracts/registry/Factory.sol new file mode 100644 index 00000000..c4757606 --- /dev/null +++ b/contracts/registry/Factory.sol @@ -0,0 +1,27 @@ +pragma solidity ^0.6.2; + +/** + * @title Protocol Factory Contract for Options + * @author Primitive + */ + +import "../primitives/PrimeOption.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +contract Factory is Ownable { + using SafeMath for uint; + + constructor(address registry) public { transferOwnership(registry); } + + function deploy(address tokenU, address tokenS, uint base, uint price, uint expiry) + external + onlyOwner + returns (address prime) + { prime = address(new PrimeOption(tokenU, tokenS, base, price, expiry)); } + + function kill(address prime) external onlyOwner { PrimeOption(prime).kill(); } + + function initialize(address prime, address redeem) external onlyOwner { + PrimeOption(prime).initTokenR(redeem); + } +} \ No newline at end of file diff --git a/contracts/FactoryRedeem.sol b/contracts/registry/FactoryRedeem.sol similarity index 61% rename from contracts/FactoryRedeem.sol rename to contracts/registry/FactoryRedeem.sol index d8c6366a..3158ddcd 100644 --- a/contracts/FactoryRedeem.sol +++ b/contracts/registry/FactoryRedeem.sol @@ -1,19 +1,19 @@ pragma solidity ^0.6.2; /** - * @title Redeem Factory Contract + * @title Protocol Factory Contract for Redeems * @author Primitive */ -import "./PrimeRedeem.sol"; +import "../primitives/PrimeRedeem.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract FactoryRedeem is Ownable { using SafeMath for uint256; - constructor(address _factory) public { transferOwnership(_factory); } + constructor(address registry) public { transferOwnership(registry); } - function deploy(address tokenP, address underlying) external returns (address redeem) { + function deploy(address tokenP, address underlying) external onlyOwner returns (address redeem) { redeem = address(new PrimeRedeem(owner(), tokenP, underlying)); } } \ No newline at end of file diff --git a/contracts/registry/Registry.sol b/contracts/registry/Registry.sol new file mode 100644 index 00000000..4a0ead81 --- /dev/null +++ b/contracts/registry/Registry.sol @@ -0,0 +1,81 @@ +pragma solidity ^0.6.2; + +/** + * @title Protocol Registry Contract for Deployed Options + * @author Primitive + */ + +import "../interfaces/IPrime.sol"; +import "../interfaces/IRegistry.sol"; +import "../interfaces/IFactory.sol"; +import "../interfaces/IFactoryRedeem.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; +import "@openzeppelin/contracts/utils/Pausable.sol"; +import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; + +contract Registry is IRegistry, Ownable, Pausable, ReentrancyGuard { + using SafeMath for uint; + + uint public constant WEEK_SECONDS = 604800; + + address public feeReceiver; + address public factory; + address public factoryRedeem; + address[] public activeOptions; + + mapping(bytes32 => address) public options; + + event Deploy(address indexed from, address indexed tokenP, bytes32 indexed id); + constructor() public { transferOwnership(msg.sender); } + + function initialize(address _factory, address _factoryRedeem) external override onlyOwner { + factory = _factory; + factoryRedeem = _factoryRedeem; + } + + function deployOption(address tokenU, address tokenS, uint base, uint price, uint expiry) + external + override + nonReentrant + whenNotPaused + returns (address prime) + { + // Do appropriate checks and calculate the expiry timestamp. + require(tokenU != tokenS && tokenU != address(0) && tokenS != address(0), "ERR_ADDRESS"); + /* uint expiry = week == uint8(0) ? uint(-1) : now.add(uint(week).mul(WEEK_SECONDS)); */ + bytes32 id = getId(tokenU, tokenS, base, price, expiry); + /* require(options[id] == address(0), "ERR_OPTION_DEPLOYED"); */ + + // Deploy option and redeem. + prime = IFactory(factory).deploy(tokenU, tokenS, base, price, expiry); + options[id] = prime; + activeOptions.push(prime); + address redeem = IFactoryRedeem(factoryRedeem).deploy(prime, tokenS); + + IFactory(factory).initialize(prime, redeem); + emit Deploy(msg.sender, prime, id); + } + + function kill(address prime) external override onlyOwner { + IFactory(factory).kill(prime); + } + + function setFeeReceiver(address _feeReceiver) external override onlyOwner { + feeReceiver = _feeReceiver; + } + + function optionsLength() public view override returns (uint len) { + len = activeOptions.length; + } + + function getId(address tokenU, address tokenS, uint base, uint price, uint expiry) + public pure returns (bytes32 id) { + id = keccak256(abi.encodePacked(tokenU, tokenS, base, price, expiry)); + } + + function getOption(address tokenU, address tokenS, uint base, uint price, uint expiry) + public view returns (address option) { + option = options[getId(tokenU, tokenS, base, price, expiry)]; + } +} \ No newline at end of file diff --git a/contracts/test/OracleLike.sol b/contracts/test/OracleLike.sol index 73097444..e1b522a3 100644 --- a/contracts/test/OracleLike.sol +++ b/contracts/test/OracleLike.sol @@ -16,6 +16,10 @@ contract OracleLike is IOracleLike { price = _price; } + function latestAnswer() external view returns (int256) { + return int(price); + } + function getUnderlyingPrice(address token) external view override returns (uint256 _price) { _price = price; } diff --git a/contracts/test/PrimeFlash.sol b/contracts/test/PrimeFlash.sol index 379f0284..c35f65ae 100644 --- a/contracts/test/PrimeFlash.sol +++ b/contracts/test/PrimeFlash.sol @@ -30,10 +30,12 @@ contract PrimeFlash is IPrimeFlash { bytes calldata data ) external override{ // just return the tokenU to the prime contract - address tokenU = IPrime(tokenP).tokenU(); + (address tokenU, address tokenS, , uint base, uint price,) = IPrime(tokenP).prime(); + uint payment = outTokenU.div(1000).mul(price).div(base); bool good = keccak256(abi.encodePacked(data)) == keccak256(abi.encodePacked(new bytes(1))); if(good) { IERC20(tokenU).transfer(tokenP, outTokenU); + IERC20(tokenS).transfer(tokenP, payment); } } } \ No newline at end of file diff --git a/contracts/test/PrimeOptionTest.sol b/contracts/test/PrimeOptionTest.sol index 6f7be0e4..bbb312e9 100644 --- a/contracts/test/PrimeOptionTest.sol +++ b/contracts/test/PrimeOptionTest.sol @@ -6,7 +6,7 @@ pragma solidity ^0.6.2; */ -import "../PrimeOption.sol"; +import "../primitives/PrimeOption.sol"; contract PrimeOptionTest is PrimeOption { @@ -25,12 +25,16 @@ contract PrimeOptionTest is PrimeOption { price, expiry ) - {} + { } function setExpiry(uint256 expiry) public { option.expiry = expiry; } + function setTokenR(address redeem) public { + tokenR = redeem; + } + } \ No newline at end of file diff --git a/contracts/test/PrimeOracleTest.sol b/contracts/test/PrimeOracleTest.sol new file mode 100644 index 00000000..ad4c7a9f --- /dev/null +++ b/contracts/test/PrimeOracleTest.sol @@ -0,0 +1,13 @@ +pragma solidity ^0.6.2; + +import "../extensions/PrimeOracle.sol"; + +contract PrimeOracleTest is PrimeOracle { + using SafeMath for uint; + + constructor(address _oracle, address _weth) public PrimeOracle(_oracle, _weth) {} + + function testSqrt(uint y) public view returns (uint z) { + z = sqrt(y); + } +} \ No newline at end of file diff --git a/contracts/test/PrimePoolTest.sol b/contracts/test/PrimePoolTest.sol index 17f298ed..df1a9454 100644 --- a/contracts/test/PrimePoolTest.sol +++ b/contracts/test/PrimePoolTest.sol @@ -17,16 +17,7 @@ contract PrimePoolTest is PrimePool { address _factory, string memory name, string memory symbol - ) - public - PrimePool( - _weth, - _tokenP, - _oracle, - _factory, - name, - symbol - ) {} + ) public PrimePool(_factory, _tokenP) {} } \ No newline at end of file diff --git a/contracts/test/UniRouter.sol b/contracts/test/UniRouter.sol new file mode 100644 index 00000000..a972157d --- /dev/null +++ b/contracts/test/UniRouter.sol @@ -0,0 +1,36 @@ +pragma solidity ^0.6.2; + +import "../interfaces/IPrimeOracle.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract UniRouter { + using SafeMath for uint; + + IERC20 public tokenA; + IERC20 public weth; + address public oracle; + + constructor(IERC20 _tokenA, IERC20 _weth, address _oracle) public { + tokenA = _tokenA; + weth = _weth; + oracle = _oracle; + } + + function swapExactTokensForTokens( + uint amountIn, + uint amountOutMin, + address[] calldata path, + address to, + uint deadline + ) external returns (uint[] memory amounts) { + uint market = IPrimeOracle(oracle).marketPrice(); + uint amountOut = path[0] == address(weth) ? market : amountIn.mul(1 ether).div(market); + require(amountOut >= amountOutMin, "INSUFFICIENT_AMOUNT_OUT"); + IERC20(path[0]).transferFrom(msg.sender, address(this), amountIn); + IERC20(path[1]).transfer(msg.sender, amountOut); + amounts = new uint[](path.length); + amounts[0] = amountIn; + amounts[path.length - 1] = amountOut; + } +} \ No newline at end of file diff --git a/coverage.json b/coverage.json index edc1bd7b..dd390cc9 100644 --- a/coverage.json +++ b/coverage.json @@ -1 +1 @@ -{"contracts\\extensions\\PrimeOracle.sol":{"l":{"36":4,"37":4,"38":4,"45":6,"73":45,"74":45,"77":45,"80":45,"89":366,"90":366,"92":365,"110":83,"111":83,"113":47,"115":47,"118":36,"121":83,"123":83,"125":83,"152":79,"153":79,"155":45,"157":45,"160":34,"164":79,"166":79,"169":79,"171":79,"177":79,"181":45,"189":79,"190":79,"191":79,"192":79,"193":1160,"194":1160,"197":0},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimeOracle.sol","s":{"1":4,"2":4,"3":4,"4":6,"5":45,"6":45,"7":45,"8":45,"9":366,"10":366,"11":365,"12":83,"13":83,"14":47,"15":47,"16":36,"17":83,"18":83,"19":83,"20":79,"21":79,"22":45,"23":45,"24":34,"25":79,"26":79,"27":79,"28":79,"29":79,"30":45,"31":79,"32":79,"33":79,"34":79,"35":1160,"36":1160,"37":0,"38":0},"b":{"1":[365,1],"2":[47,36],"3":[45,34],"4":[45,34],"5":[79,0],"6":[0,0]},"f":{"1":4,"2":6,"3":45,"4":366,"5":83,"6":79,"7":79},"fnMap":{"1":{"name":"constructor","line":35,"loc":{"start":{"line":35,"column":4},"end":{"line":35,"column":52}}},"2":{"name":"addFeed","line":44,"loc":{"start":{"line":44,"column":4},"end":{"line":44,"column":39}}},"3":{"name":"calculatePremium","line":60,"loc":{"start":{"line":60,"column":4},"end":{"line":71,"column":5}}},"4":{"name":"marketPrice","line":87,"loc":{"start":{"line":87,"column":4},"end":{"line":87,"column":83}}},"5":{"name":"calculateIntrinsic","line":104,"loc":{"start":{"line":104,"column":4},"end":{"line":108,"column":5}}},"6":{"name":"calculateExtrinsic","line":139,"loc":{"start":{"line":139,"column":4},"end":{"line":150,"column":5}}},"7":{"name":"sqrt","line":188,"loc":{"start":{"line":188,"column":4},"end":{"line":188,"column":59}}}},"statementMap":{"1":{"start":{"line":36,"column":8},"end":{"line":36,"column":23}},"2":{"start":{"line":37,"column":8},"end":{"line":37,"column":19}},"3":{"start":{"line":38,"column":8},"end":{"line":38,"column":36}},"4":{"start":{"line":45,"column":8},"end":{"line":45,"column":25}},"5":{"start":{"line":73,"column":8},"end":{"line":73,"column":77}},"6":{"start":{"line":74,"column":8},"end":{"line":74,"column":97}},"7":{"start":{"line":77,"column":8},"end":{"line":77,"column":43}},"8":{"start":{"line":80,"column":8},"end":{"line":80,"column":52}},"9":{"start":{"line":89,"column":8},"end":{"line":89,"column":35}},"10":{"start":{"line":90,"column":8},"end":{"line":90,"column":54}},"11":{"start":{"line":92,"column":8},"end":{"line":92,"column":65}},"12":{"start":{"line":110,"column":8},"end":{"line":110,"column":22}},"13":{"start":{"line":111,"column":8},"end":{"line":111,"column":4481}},"14":{"start":{"line":113,"column":12},"end":{"line":113,"column":41}},"15":{"start":{"line":115,"column":12},"end":{"line":115,"column":40}},"16":{"start":{"line":118,"column":12},"end":{"line":118,"column":41}},"17":{"start":{"line":121,"column":8},"end":{"line":121,"column":55}},"18":{"start":{"line":123,"column":8},"end":{"line":123,"column":59}},"19":{"start":{"line":125,"column":8},"end":{"line":125,"column":50}},"20":{"start":{"line":152,"column":8},"end":{"line":152,"column":22}},"21":{"start":{"line":153,"column":8},"end":{"line":153,"column":6369}},"22":{"start":{"line":155,"column":12},"end":{"line":155,"column":41}},"23":{"start":{"line":157,"column":12},"end":{"line":157,"column":40}},"24":{"start":{"line":160,"column":12},"end":{"line":160,"column":41}},"25":{"start":{"line":164,"column":8},"end":{"line":164,"column":61}},"26":{"start":{"line":166,"column":8},"end":{"line":166,"column":55}},"27":{"start":{"line":169,"column":8},"end":{"line":169,"column":61}},"28":{"start":{"line":171,"column":8},"end":{"line":171,"column":7286}},"29":{"start":{"line":177,"column":8},"end":{"line":177,"column":7518}},"30":{"start":{"line":181,"column":12},"end":{"line":181,"column":54}},"31":{"start":{"line":189,"column":8},"end":{"line":189,"column":7992}},"32":{"start":{"line":190,"column":12},"end":{"line":190,"column":35}},"33":{"start":{"line":191,"column":12},"end":{"line":191,"column":16}},"34":{"start":{"line":192,"column":12},"end":{"line":192,"column":8077}},"35":{"start":{"line":193,"column":16},"end":{"line":193,"column":20}},"36":{"start":{"line":194,"column":16},"end":{"line":194,"column":34}},"37":{"start":{"line":196,"column":15},"end":{"line":196,"column":8178}},"38":{"start":{"line":197,"column":12},"end":{"line":197,"column":16}}},"branchMap":{"1":{"line":90,"type":"if","locations":[{"start":{"line":90,"column":8},"end":{"line":90,"column":8}},{"start":{"line":90,"column":8},"end":{"line":90,"column":8}}]},"2":{"line":111,"type":"if","locations":[{"start":{"line":111,"column":8},"end":{"line":111,"column":8}},{"start":{"line":111,"column":8},"end":{"line":111,"column":8}}]},"3":{"line":153,"type":"if","locations":[{"start":{"line":153,"column":8},"end":{"line":153,"column":8}},{"start":{"line":153,"column":8},"end":{"line":153,"column":8}}]},"4":{"line":177,"type":"if","locations":[{"start":{"line":177,"column":8},"end":{"line":177,"column":8}},{"start":{"line":177,"column":8},"end":{"line":177,"column":8}}]},"5":{"line":189,"type":"if","locations":[{"start":{"line":189,"column":8},"end":{"line":189,"column":8}},{"start":{"line":189,"column":8},"end":{"line":189,"column":8}}]},"6":{"line":196,"type":"if","locations":[{"start":{"line":196,"column":15},"end":{"line":196,"column":15}},{"start":{"line":196,"column":15},"end":{"line":196,"column":15}}]}}},"contracts\\extensions\\PrimePool.sol":{"l":{"77":2,"78":2,"79":2,"80":2,"81":2,"85":2,"86":1,"88":1,"90":2,"111":7,"112":7,"115":7,"122":3,"125":3,"141":5,"142":5,"143":5,"149":3,"152":3,"155":1,"156":1,"167":6,"168":6,"172":6,"173":2,"175":4,"176":4,"178":4,"179":4,"198":10,"205":2,"208":2,"211":2,"214":2,"219":2,"220":2,"221":2,"223":2,"226":2,"227":2,"230":0,"231":0,"234":0,"235":0,"250":0,"253":0,"256":0,"259":0,"262":0,"276":0,"279":0,"282":0,"283":0,"298":0,"299":0,"300":0,"301":0,"302":0,"304":0,"307":0,"309":0,"311":0,"313":0,"315":0,"316":0,"318":0,"320":0,"324":0,"325":0,"329":0,"331":0,"333":0,"335":0,"340":0,"351":2,"352":2,"353":2,"355":0,"379":7,"380":7,"393":7,"399":7,"400":5,"406":5,"409":3,"420":3,"421":3,"424":3,"428":3,"429":3,"430":3,"431":3,"432":3,"448":4,"449":4,"459":4,"466":0,"476":0,"480":0,"483":0,"486":0,"489":0,"492":0,"496":0,"499":0,"500":0,"512":24,"513":24,"514":24,"515":24,"516":7,"538":125,"539":125,"540":125,"548":103,"558":75,"567":125,"568":125,"569":125,"576":2,"577":2,"578":2,"582":0,"583":0},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimePool.sol","s":{"1":2,"2":2,"3":2,"4":2,"5":2,"6":2,"7":1,"8":1,"9":2,"10":7,"11":7,"12":7,"13":3,"14":3,"15":5,"16":5,"17":5,"18":3,"19":3,"20":1,"21":1,"22":6,"23":6,"24":6,"25":2,"26":4,"27":4,"28":4,"29":4,"30":10,"31":2,"32":2,"33":2,"34":2,"35":2,"36":2,"37":2,"38":2,"39":2,"40":2,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0,"74":0,"75":0,"76":2,"77":2,"78":2,"79":0,"80":7,"81":7,"82":7,"83":7,"84":5,"85":5,"86":3,"87":3,"88":3,"89":3,"90":3,"91":3,"92":3,"93":3,"94":3,"95":4,"96":4,"97":4,"98":0,"99":0,"100":0,"101":0,"102":0,"103":0,"104":0,"105":0,"106":0,"107":0,"108":24,"109":24,"110":24,"111":20,"112":24,"113":7,"114":17,"115":125,"116":125,"117":125,"118":103,"119":75,"120":125,"121":125,"122":125,"123":2,"124":2,"125":2,"126":0,"127":0},"b":{"1":[1,1],"2":[3,4],"3":[3,2],"4":[3,0],"5":[2,4],"6":[2,2],"7":[2,8],"8":[2,0],"9":[2,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0],"15":[0,0],"16":[2,0],"17":[5,2],"18":[3,0],"19":[3,0],"20":[3,0],"21":[0,4],"22":[0,0],"23":[0,0],"24":[20,4],"25":[7,17],"26":[2,0]},"f":{"1":2,"2":2,"3":2,"4":7,"5":5,"6":6,"7":10,"8":0,"9":0,"10":0,"11":2,"12":7,"13":4,"14":24,"15":125,"16":103,"17":75,"18":125,"19":2,"20":0},"fnMap":{"1":{"name":"constructor","line":75,"loc":{"start":{"line":75,"column":26},"end":{"line":76,"column":5}}},"2":{"name":"kill","line":84,"loc":{"start":{"line":84,"column":44},"end":{"line":84,"column":18}}},"3":{"name":null,"line":93,"loc":{"start":{"line":93,"column":4},"end":{"line":93,"column":28}}},"4":{"name":"deposit","line":107,"loc":{"start":{"line":107,"column":19},"end":{"line":109,"column":5}}},"5":{"name":"depositEth","line":137,"loc":{"start":{"line":137,"column":19},"end":{"line":139,"column":5}}},"6":{"name":"_addLiquidity","line":162,"loc":{"start":{"line":162,"column":4},"end":{"line":165,"column":5}}},"7":{"name":"withdraw","line":194,"loc":{"start":{"line":194,"column":19},"end":{"line":196,"column":5}}},"8":{"name":"_removeLiquidity","line":245,"loc":{"start":{"line":245,"column":4},"end":{"line":248,"column":5}}},"9":{"name":"_redeem","line":271,"loc":{"start":{"line":271,"column":4},"end":{"line":274,"column":5}}},"10":{"name":"_exchange","line":293,"loc":{"start":{"line":293,"column":4},"end":{"line":296,"column":5}}},"11":{"name":"_withdraw","line":350,"loc":{"start":{"line":350,"column":4},"end":{"line":350,"column":86}}},"12":{"name":"buy","line":375,"loc":{"start":{"line":375,"column":19},"end":{"line":377,"column":5}}},"13":{"name":"sell","line":444,"loc":{"start":{"line":444,"column":19},"end":{"line":446,"column":5}}},"14":{"name":"calculateVolatilityProxy","line":507,"loc":{"start":{"line":507,"column":4},"end":{"line":511,"column":5}}},"15":{"name":"totalUtilized","line":524,"loc":{"start":{"line":524,"column":4},"end":{"line":528,"column":5}}},"16":{"name":"totalUnutilized","line":546,"loc":{"start":{"line":546,"column":4},"end":{"line":546,"column":82}}},"17":{"name":"totalPoolBalance","line":555,"loc":{"start":{"line":555,"column":4},"end":{"line":555,"column":87}}},"18":{"name":"marketRatio","line":566,"loc":{"start":{"line":566,"column":4},"end":{"line":566,"column":80}}},"19":{"name":"sendEther","line":575,"loc":{"start":{"line":575,"column":4},"end":{"line":575,"column":71}}},"20":{"name":"balances","line":581,"loc":{"start":{"line":581,"column":4},"end":{"line":581,"column":80}}}},"statementMap":{"1":{"start":{"line":77,"column":8},"end":{"line":77,"column":19}},"2":{"start":{"line":78,"column":8},"end":{"line":78,"column":23}},"3":{"start":{"line":79,"column":8},"end":{"line":79,"column":23}},"4":{"start":{"line":80,"column":8},"end":{"line":80,"column":25}},"5":{"start":{"line":81,"column":8},"end":{"line":81,"column":23}},"6":{"start":{"line":85,"column":8},"end":{"line":85,"column":3019}},"7":{"start":{"line":86,"column":12},"end":{"line":86,"column":21}},"8":{"start":{"line":88,"column":12},"end":{"line":88,"column":19}},"9":{"start":{"line":90,"column":8},"end":{"line":90,"column":19}},"10":{"start":{"line":111,"column":8},"end":{"line":111,"column":32}},"11":{"start":{"line":112,"column":8},"end":{"line":112,"column":49}},"12":{"start":{"line":115,"column":8},"end":{"line":115,"column":3802}},"13":{"start":{"line":122,"column":8},"end":{"line":122,"column":68}},"14":{"start":{"line":125,"column":8},"end":{"line":125,"column":83}},"15":{"start":{"line":141,"column":8},"end":{"line":141,"column":32}},"16":{"start":{"line":142,"column":8},"end":{"line":142,"column":49}},"17":{"start":{"line":143,"column":8},"end":{"line":143,"column":4779}},"18":{"start":{"line":149,"column":8},"end":{"line":149,"column":46}},"19":{"start":{"line":152,"column":8},"end":{"line":152,"column":69}},"20":{"start":{"line":155,"column":8},"end":{"line":155,"column":43}},"21":{"start":{"line":156,"column":8},"end":{"line":156,"column":21}},"22":{"start":{"line":167,"column":8},"end":{"line":167,"column":44}},"23":{"start":{"line":168,"column":8},"end":{"line":168,"column":58}},"24":{"start":{"line":172,"column":8},"end":{"line":172,"column":5854}},"25":{"start":{"line":173,"column":12},"end":{"line":173,"column":34}},"26":{"start":{"line":175,"column":12},"end":{"line":175,"column":70}},"27":{"start":{"line":176,"column":12},"end":{"line":176,"column":58}},"28":{"start":{"line":178,"column":8},"end":{"line":178,"column":30}},"29":{"start":{"line":179,"column":8},"end":{"line":179,"column":48}},"30":{"start":{"line":198,"column":8},"end":{"line":198,"column":6874}},"31":{"start":{"line":205,"column":8},"end":{"line":205,"column":32}},"32":{"start":{"line":208,"column":8},"end":{"line":208,"column":44}},"33":{"start":{"line":211,"column":8},"end":{"line":211,"column":53}},"34":{"start":{"line":214,"column":8},"end":{"line":214,"column":58}},"35":{"start":{"line":219,"column":8},"end":{"line":219,"column":75}},"36":{"start":{"line":220,"column":8},"end":{"line":220,"column":7763}},"37":{"start":{"line":221,"column":12},"end":{"line":221,"column":55}},"38":{"start":{"line":223,"column":12},"end":{"line":223,"column":41}},"39":{"start":{"line":226,"column":12},"end":{"line":226,"column":61}},"40":{"start":{"line":227,"column":12},"end":{"line":227,"column":77}},"41":{"start":{"line":230,"column":12},"end":{"line":230,"column":76}},"42":{"start":{"line":231,"column":12},"end":{"line":231,"column":70}},"43":{"start":{"line":234,"column":12},"end":{"line":234,"column":61}},"44":{"start":{"line":235,"column":12},"end":{"line":235,"column":77}},"45":{"start":{"line":250,"column":8},"end":{"line":250,"column":37}},"46":{"start":{"line":253,"column":8},"end":{"line":253,"column":35}},"47":{"start":{"line":256,"column":8},"end":{"line":256,"column":37}},"48":{"start":{"line":259,"column":8},"end":{"line":259,"column":44}},"49":{"start":{"line":262,"column":8},"end":{"line":262,"column":49}},"50":{"start":{"line":276,"column":8},"end":{"line":276,"column":53}},"51":{"start":{"line":279,"column":8},"end":{"line":279,"column":66}},"52":{"start":{"line":282,"column":8},"end":{"line":282,"column":56}},"53":{"start":{"line":283,"column":8},"end":{"line":283,"column":35}},"54":{"start":{"line":298,"column":8},"end":{"line":298,"column":49}},"55":{"start":{"line":299,"column":8},"end":{"line":299,"column":49}},"56":{"start":{"line":300,"column":8},"end":{"line":300,"column":24}},"57":{"start":{"line":301,"column":8},"end":{"line":301,"column":10956}},"58":{"start":{"line":302,"column":12},"end":{"line":302,"column":28}},"59":{"start":{"line":303,"column":15},"end":{"line":303,"column":31}},"60":{"start":{"line":304,"column":8},"end":{"line":304,"column":72}},"61":{"start":{"line":307,"column":8},"end":{"line":307,"column":52}},"62":{"start":{"line":309,"column":8},"end":{"line":309,"column":96}},"63":{"start":{"line":311,"column":8},"end":{"line":311,"column":56}},"64":{"start":{"line":313,"column":8},"end":{"line":313,"column":52}},"65":{"start":{"line":315,"column":8},"end":{"line":315,"column":25}},"66":{"start":{"line":316,"column":8},"end":{"line":316,"column":11876}},"67":{"start":{"line":318,"column":12},"end":{"line":318,"column":62}},"68":{"start":{"line":320,"column":12},"end":{"line":320,"column":66}},"69":{"start":{"line":324,"column":12},"end":{"line":324,"column":54}},"70":{"start":{"line":325,"column":12},"end":{"line":325,"column":12504}},"71":{"start":{"line":329,"column":12},"end":{"line":329,"column":59}},"72":{"start":{"line":331,"column":12},"end":{"line":331,"column":33}},"73":{"start":{"line":333,"column":12},"end":{"line":333,"column":72}},"74":{"start":{"line":335,"column":12},"end":{"line":335,"column":44}},"75":{"start":{"line":340,"column":12},"end":{"line":340,"column":13230}},"76":{"start":{"line":351,"column":8},"end":{"line":351,"column":13622}},"77":{"start":{"line":352,"column":12},"end":{"line":352,"column":39}},"78":{"start":{"line":353,"column":12},"end":{"line":353,"column":40}},"79":{"start":{"line":355,"column":12},"end":{"line":355,"column":53}},"80":{"start":{"line":379,"column":8},"end":{"line":379,"column":32}},"81":{"start":{"line":380,"column":8},"end":{"line":380,"column":14642}},"82":{"start":{"line":393,"column":8},"end":{"line":393,"column":57}},"83":{"start":{"line":399,"column":8},"end":{"line":399,"column":90}},"84":{"start":{"line":400,"column":8},"end":{"line":400,"column":70}},"85":{"start":{"line":406,"column":8},"end":{"line":406,"column":66}},"86":{"start":{"line":409,"column":8},"end":{"line":409,"column":16144}},"87":{"start":{"line":420,"column":8},"end":{"line":420,"column":53}},"88":{"start":{"line":421,"column":8},"end":{"line":421,"column":47}},"89":{"start":{"line":424,"column":8},"end":{"line":424,"column":53}},"90":{"start":{"line":428,"column":8},"end":{"line":428,"column":85}},"91":{"start":{"line":429,"column":8},"end":{"line":429,"column":85}},"92":{"start":{"line":430,"column":8},"end":{"line":430,"column":58}},"93":{"start":{"line":431,"column":8},"end":{"line":431,"column":89}},"94":{"start":{"line":432,"column":8},"end":{"line":432,"column":86}},"95":{"start":{"line":448,"column":8},"end":{"line":448,"column":32}},"96":{"start":{"line":449,"column":8},"end":{"line":449,"column":17790}},"97":{"start":{"line":459,"column":8},"end":{"line":459,"column":18066}},"98":{"start":{"line":466,"column":8},"end":{"line":466,"column":18270}},"99":{"start":{"line":476,"column":8},"end":{"line":476,"column":56}},"100":{"start":{"line":480,"column":8},"end":{"line":480,"column":53}},"101":{"start":{"line":483,"column":8},"end":{"line":483,"column":88}},"102":{"start":{"line":486,"column":8},"end":{"line":486,"column":54}},"103":{"start":{"line":489,"column":8},"end":{"line":489,"column":46}},"104":{"start":{"line":492,"column":8},"end":{"line":492,"column":99}},"105":{"start":{"line":496,"column":8},"end":{"line":496,"column":43}},"106":{"start":{"line":499,"column":8},"end":{"line":499,"column":48}},"107":{"start":{"line":500,"column":8},"end":{"line":500,"column":59}},"108":{"start":{"line":512,"column":8},"end":{"line":512,"column":51}},"109":{"start":{"line":513,"column":8},"end":{"line":513,"column":56}},"110":{"start":{"line":514,"column":8},"end":{"line":514,"column":84}},"111":{"start":{"line":514,"column":29},"end":{"line":514,"column":83}},"112":{"start":{"line":515,"column":8},"end":{"line":515,"column":20358}},"113":{"start":{"line":516,"column":12},"end":{"line":516,"column":29}},"114":{"start":{"line":517,"column":15},"end":{"line":517,"column":69}},"115":{"start":{"line":538,"column":8},"end":{"line":538,"column":74}},"116":{"start":{"line":539,"column":8},"end":{"line":539,"column":52}},"117":{"start":{"line":540,"column":8},"end":{"line":540,"column":85}},"118":{"start":{"line":548,"column":8},"end":{"line":548,"column":75}},"119":{"start":{"line":558,"column":8},"end":{"line":558,"column":74}},"120":{"start":{"line":567,"column":8},"end":{"line":567,"column":50}},"121":{"start":{"line":568,"column":8},"end":{"line":568,"column":76}},"122":{"start":{"line":569,"column":8},"end":{"line":569,"column":74}},"123":{"start":{"line":576,"column":8},"end":{"line":576,"column":52}},"124":{"start":{"line":577,"column":8},"end":{"line":577,"column":41}},"125":{"start":{"line":578,"column":8},"end":{"line":578,"column":22}},"126":{"start":{"line":582,"column":8},"end":{"line":582,"column":74}},"127":{"start":{"line":583,"column":8},"end":{"line":583,"column":74}}},"branchMap":{"1":{"line":85,"type":"if","locations":[{"start":{"line":85,"column":8},"end":{"line":85,"column":8}},{"start":{"line":85,"column":8},"end":{"line":85,"column":8}}]},"2":{"line":115,"type":"if","locations":[{"start":{"line":115,"column":8},"end":{"line":115,"column":8}},{"start":{"line":115,"column":8},"end":{"line":115,"column":8}}]},"3":{"line":143,"type":"if","locations":[{"start":{"line":143,"column":8},"end":{"line":143,"column":8}},{"start":{"line":143,"column":8},"end":{"line":143,"column":8}}]},"4":{"line":149,"type":"if","locations":[{"start":{"line":149,"column":8},"end":{"line":149,"column":8}},{"start":{"line":149,"column":8},"end":{"line":149,"column":8}}]},"5":{"line":172,"type":"if","locations":[{"start":{"line":172,"column":8},"end":{"line":172,"column":8}},{"start":{"line":172,"column":8},"end":{"line":172,"column":8}}]},"6":{"line":176,"type":"if","locations":[{"start":{"line":176,"column":12},"end":{"line":176,"column":12}},{"start":{"line":176,"column":12},"end":{"line":176,"column":12}}]},"7":{"line":198,"type":"if","locations":[{"start":{"line":198,"column":8},"end":{"line":198,"column":8}},{"start":{"line":198,"column":8},"end":{"line":198,"column":8}}]},"8":{"line":220,"type":"if","locations":[{"start":{"line":220,"column":8},"end":{"line":220,"column":8}},{"start":{"line":220,"column":8},"end":{"line":220,"column":8}}]},"9":{"line":221,"type":"if","locations":[{"start":{"line":221,"column":12},"end":{"line":221,"column":12}},{"start":{"line":221,"column":12},"end":{"line":221,"column":12}}]},"10":{"line":253,"type":"if","locations":[{"start":{"line":253,"column":8},"end":{"line":253,"column":8}},{"start":{"line":253,"column":8},"end":{"line":253,"column":8}}]},"11":{"line":256,"type":"if","locations":[{"start":{"line":256,"column":8},"end":{"line":256,"column":8}},{"start":{"line":256,"column":8},"end":{"line":256,"column":8}}]},"12":{"line":283,"type":"if","locations":[{"start":{"line":283,"column":8},"end":{"line":283,"column":8}},{"start":{"line":283,"column":8},"end":{"line":283,"column":8}}]},"13":{"line":301,"type":"if","locations":[{"start":{"line":301,"column":8},"end":{"line":301,"column":8}},{"start":{"line":301,"column":8},"end":{"line":301,"column":8}}]},"14":{"line":316,"type":"if","locations":[{"start":{"line":316,"column":8},"end":{"line":316,"column":8}},{"start":{"line":316,"column":8},"end":{"line":316,"column":8}}]},"15":{"line":331,"type":"if","locations":[{"start":{"line":331,"column":12},"end":{"line":331,"column":12}},{"start":{"line":331,"column":12},"end":{"line":331,"column":12}}]},"16":{"line":351,"type":"if","locations":[{"start":{"line":351,"column":8},"end":{"line":351,"column":8}},{"start":{"line":351,"column":8},"end":{"line":351,"column":8}}]},"17":{"line":399,"type":"if","locations":[{"start":{"line":399,"column":8},"end":{"line":399,"column":8}},{"start":{"line":399,"column":8},"end":{"line":399,"column":8}}]},"18":{"line":421,"type":"if","locations":[{"start":{"line":421,"column":8},"end":{"line":421,"column":8}},{"start":{"line":421,"column":8},"end":{"line":421,"column":8}}]},"19":{"line":428,"type":"if","locations":[{"start":{"line":428,"column":8},"end":{"line":428,"column":8}},{"start":{"line":428,"column":8},"end":{"line":428,"column":8}}]},"20":{"line":429,"type":"if","locations":[{"start":{"line":429,"column":8},"end":{"line":429,"column":8}},{"start":{"line":429,"column":8},"end":{"line":429,"column":8}}]},"21":{"line":459,"type":"if","locations":[{"start":{"line":459,"column":8},"end":{"line":459,"column":8}},{"start":{"line":459,"column":8},"end":{"line":459,"column":8}}]},"22":{"line":483,"type":"if","locations":[{"start":{"line":483,"column":8},"end":{"line":483,"column":8}},{"start":{"line":483,"column":8},"end":{"line":483,"column":8}}]},"23":{"line":492,"type":"if","locations":[{"start":{"line":492,"column":8},"end":{"line":492,"column":8}},{"start":{"line":492,"column":8},"end":{"line":492,"column":8}}]},"24":{"line":514,"type":"if","locations":[{"start":{"line":514,"column":8},"end":{"line":514,"column":8}},{"start":{"line":514,"column":8},"end":{"line":514,"column":8}}]},"25":{"line":515,"type":"if","locations":[{"start":{"line":515,"column":8},"end":{"line":515,"column":8}},{"start":{"line":515,"column":8},"end":{"line":515,"column":8}}]},"26":{"line":577,"type":"if","locations":[{"start":{"line":577,"column":8},"end":{"line":577,"column":8}},{"start":{"line":577,"column":8},"end":{"line":577,"column":8}}]}}},"contracts\\extensions\\PrimePoolV1.sol":{"l":{"31":7,"32":7,"45":28,"46":28,"47":28,"50":28,"51":10,"53":18,"56":28,"57":28,"58":28,"66":10,"69":8,"72":8,"73":8,"75":8,"77":8,"81":8,"82":8,"83":8},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimePoolV1.sol","s":{"1":7,"2":7,"3":0,"4":28,"5":28,"6":28,"7":28,"8":10,"9":18,"10":28,"11":28,"12":28,"13":10,"14":8,"15":8,"16":8,"17":8,"18":8,"19":8,"20":8,"21":8},"b":{"1":[10,18],"2":[28,0],"3":[8,2],"4":[8,0]},"f":{"1":7,"2":0,"3":28,"4":10,"5":8},"fnMap":{"1":{"name":"constructor","line":29,"loc":{"start":{"line":29,"column":41},"end":{"line":30,"column":5}}},"2":{"name":"kill","line":35,"loc":{"start":{"line":35,"column":44},"end":{"line":35,"column":18}}},"3":{"name":"_addLiquidity","line":40,"loc":{"start":{"line":40,"column":4},"end":{"line":43,"column":5}}},"4":{"name":"_removeLiquidity","line":61,"loc":{"start":{"line":61,"column":4},"end":{"line":64,"column":5}}},"5":{"name":"balances","line":80,"loc":{"start":{"line":80,"column":4},"end":{"line":80,"column":81}}}},"statementMap":{"1":{"start":{"line":31,"column":8},"end":{"line":31,"column":23}},"2":{"start":{"line":32,"column":8},"end":{"line":32,"column":25}},"3":{"start":{"line":35,"column":63},"end":{"line":35,"column":94}},"4":{"start":{"line":45,"column":8},"end":{"line":45,"column":41}},"5":{"start":{"line":46,"column":8},"end":{"line":46,"column":42}},"6":{"start":{"line":47,"column":8},"end":{"line":47,"column":44}},"7":{"start":{"line":50,"column":8},"end":{"line":50,"column":1682}},"8":{"start":{"line":51,"column":12},"end":{"line":51,"column":76}},"9":{"start":{"line":53,"column":12},"end":{"line":53,"column":70}},"10":{"start":{"line":56,"column":8},"end":{"line":56,"column":54}},"11":{"start":{"line":57,"column":8},"end":{"line":57,"column":30}},"12":{"start":{"line":58,"column":8},"end":{"line":58,"column":48}},"13":{"start":{"line":66,"column":8},"end":{"line":66,"column":79}},"14":{"start":{"line":69,"column":8},"end":{"line":69,"column":41}},"15":{"start":{"line":72,"column":8},"end":{"line":72,"column":66}},"16":{"start":{"line":73,"column":8},"end":{"line":73,"column":41}},"17":{"start":{"line":75,"column":8},"end":{"line":75,"column":29}},"18":{"start":{"line":77,"column":8},"end":{"line":77,"column":49}},"19":{"start":{"line":81,"column":8},"end":{"line":81,"column":71}},"20":{"start":{"line":82,"column":8},"end":{"line":82,"column":57}},"21":{"start":{"line":83,"column":8},"end":{"line":83,"column":57}}},"branchMap":{"1":{"line":50,"type":"if","locations":[{"start":{"line":50,"column":8},"end":{"line":50,"column":8}},{"start":{"line":50,"column":8},"end":{"line":50,"column":8}}]},"2":{"line":56,"type":"if","locations":[{"start":{"line":56,"column":8},"end":{"line":56,"column":8}},{"start":{"line":56,"column":8},"end":{"line":56,"column":8}}]},"3":{"line":66,"type":"if","locations":[{"start":{"line":66,"column":8},"end":{"line":66,"column":8}},{"start":{"line":66,"column":8},"end":{"line":66,"column":8}}]},"4":{"line":73,"type":"if","locations":[{"start":{"line":73,"column":8},"end":{"line":73,"column":8}},{"start":{"line":73,"column":8},"end":{"line":73,"column":8}}]}}},"contracts\\extensions\\PrimeTrader.sol":{"l":{"26":23,"42":31,"43":29,"44":27,"49":25,"53":25,"54":25,"72":17,"73":15,"74":15,"80":13,"81":13,"86":11,"87":11,"88":11,"89":11,"106":15,"107":13,"108":13,"110":13,"119":11,"124":9,"125":9,"126":9,"145":13,"146":11,"148":11,"150":11,"156":9,"162":7,"163":7,"164":7,"165":7,"183":2,"184":2,"185":0,"187":0,"189":0,"195":0,"196":0,"197":0,"205":99},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimeTrader.sol","s":{"1":23,"2":31,"3":29,"4":27,"5":25,"6":25,"7":25,"8":17,"9":15,"10":15,"11":13,"12":13,"13":11,"14":11,"15":11,"16":11,"17":15,"18":13,"19":13,"20":13,"21":11,"22":9,"23":9,"24":9,"25":13,"26":11,"27":11,"28":11,"29":9,"30":7,"31":7,"32":7,"33":7,"34":2,"35":2,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":99},"b":{"1":[29,2],"2":[25,0],"3":[15,2],"4":[11,0],"5":[13,2],"6":[11,2],"7":[2,0],"8":[0,2]},"f":{"1":23,"2":31,"3":17,"4":15,"5":13,"6":2,"7":99},"fnMap":{"1":{"name":"constructor","line":25,"loc":{"start":{"line":25,"column":4},"end":{"line":25,"column":44}}},"2":{"name":"safeMint","line":38,"loc":{"start":{"line":38,"column":19},"end":{"line":41,"column":5}}},"3":{"name":"safeExercise","line":69,"loc":{"start":{"line":69,"column":19},"end":{"line":71,"column":5}}},"4":{"name":"safeRedeem","line":103,"loc":{"start":{"line":103,"column":19},"end":{"line":105,"column":5}}},"5":{"name":"safeClose","line":142,"loc":{"start":{"line":142,"column":19},"end":{"line":144,"column":5}}},"6":{"name":"safeUnwind","line":180,"loc":{"start":{"line":180,"column":19},"end":{"line":182,"column":5}}},"7":{"name":"verifyBalance","line":200,"loc":{"start":{"line":200,"column":4},"end":{"line":204,"column":21}}}},"statementMap":{"1":{"start":{"line":26,"column":8},"end":{"line":26,"column":19}},"2":{"start":{"line":42,"column":8},"end":{"line":42,"column":38}},"3":{"start":{"line":43,"column":8},"end":{"line":43,"column":40}},"4":{"start":{"line":44,"column":8},"end":{"line":44,"column":1540}},"5":{"start":{"line":49,"column":8},"end":{"line":49,"column":1677}},"6":{"start":{"line":53,"column":8},"end":{"line":53,"column":52}},"7":{"start":{"line":54,"column":8},"end":{"line":54,"column":50}},"8":{"start":{"line":72,"column":8},"end":{"line":72,"column":38}},"9":{"start":{"line":73,"column":8},"end":{"line":73,"column":40}},"10":{"start":{"line":74,"column":8},"end":{"line":74,"column":2505}},"11":{"start":{"line":80,"column":8},"end":{"line":80,"column":63}},"12":{"start":{"line":81,"column":8},"end":{"line":81,"column":2713}},"13":{"start":{"line":86,"column":8},"end":{"line":86,"column":95}},"14":{"start":{"line":87,"column":8},"end":{"line":87,"column":102}},"15":{"start":{"line":88,"column":8},"end":{"line":88,"column":66}},"16":{"start":{"line":89,"column":8},"end":{"line":89,"column":77}},"17":{"start":{"line":106,"column":8},"end":{"line":106,"column":38}},"18":{"start":{"line":107,"column":8},"end":{"line":107,"column":40}},"19":{"start":{"line":108,"column":8},"end":{"line":108,"column":40}},"20":{"start":{"line":110,"column":8},"end":{"line":110,"column":3698}},"21":{"start":{"line":119,"column":8},"end":{"line":119,"column":4049}},"22":{"start":{"line":124,"column":8},"end":{"line":124,"column":71}},"23":{"start":{"line":125,"column":8},"end":{"line":125,"column":43}},"24":{"start":{"line":126,"column":8},"end":{"line":126,"column":41}},"25":{"start":{"line":145,"column":8},"end":{"line":145,"column":38}},"26":{"start":{"line":146,"column":8},"end":{"line":146,"column":40}},"27":{"start":{"line":148,"column":8},"end":{"line":148,"column":63}},"28":{"start":{"line":150,"column":8},"end":{"line":150,"column":5048}},"29":{"start":{"line":156,"column":8},"end":{"line":156,"column":5184}},"30":{"start":{"line":162,"column":8},"end":{"line":162,"column":73}},"31":{"start":{"line":163,"column":8},"end":{"line":163,"column":80}},"32":{"start":{"line":164,"column":8},"end":{"line":164,"column":63}},"33":{"start":{"line":165,"column":8},"end":{"line":165,"column":40}},"34":{"start":{"line":183,"column":8},"end":{"line":183,"column":38}},"35":{"start":{"line":184,"column":8},"end":{"line":184,"column":68}},"36":{"start":{"line":185,"column":8},"end":{"line":185,"column":40}},"37":{"start":{"line":187,"column":8},"end":{"line":187,"column":63}},"38":{"start":{"line":189,"column":8},"end":{"line":189,"column":6335}},"39":{"start":{"line":195,"column":8},"end":{"line":195,"column":73}},"40":{"start":{"line":196,"column":8},"end":{"line":196,"column":63}},"41":{"start":{"line":197,"column":8},"end":{"line":197,"column":40}},"42":{"start":{"line":205,"column":8},"end":{"line":205,"column":6841}}},"branchMap":{"1":{"line":42,"type":"if","locations":[{"start":{"line":42,"column":8},"end":{"line":42,"column":8}},{"start":{"line":42,"column":8},"end":{"line":42,"column":8}}]},"2":{"line":49,"type":"if","locations":[{"start":{"line":49,"column":8},"end":{"line":49,"column":8}},{"start":{"line":49,"column":8},"end":{"line":49,"column":8}}]},"3":{"line":72,"type":"if","locations":[{"start":{"line":72,"column":8},"end":{"line":72,"column":8}},{"start":{"line":72,"column":8},"end":{"line":72,"column":8}}]},"4":{"line":88,"type":"if","locations":[{"start":{"line":88,"column":8},"end":{"line":88,"column":8}},{"start":{"line":88,"column":8},"end":{"line":88,"column":8}}]},"5":{"line":106,"type":"if","locations":[{"start":{"line":106,"column":8},"end":{"line":106,"column":8}},{"start":{"line":106,"column":8},"end":{"line":106,"column":8}}]},"6":{"line":145,"type":"if","locations":[{"start":{"line":145,"column":8},"end":{"line":145,"column":8}},{"start":{"line":145,"column":8},"end":{"line":145,"column":8}}]},"7":{"line":183,"type":"if","locations":[{"start":{"line":183,"column":8},"end":{"line":183,"column":8}},{"start":{"line":183,"column":8},"end":{"line":183,"column":8}}]},"8":{"line":184,"type":"if","locations":[{"start":{"line":184,"column":8},"end":{"line":184,"column":8}},{"start":{"line":184,"column":8},"end":{"line":184,"column":8}}]}}},"contracts\\Factory.sol":{"l":{"24":5,"28":5,"43":29,"44":29,"45":29,"46":29,"47":29,"67":29},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\Factory.sol","s":{"1":5,"2":5,"3":29,"4":29,"5":29,"6":29,"7":29,"8":29},"b":{},"f":{"1":5,"2":5,"3":29,"4":29},"fnMap":{"1":{"name":"constructor","line":23,"loc":{"start":{"line":23,"column":4},"end":{"line":23,"column":22}}},"2":{"name":"initialize","line":27,"loc":{"start":{"line":27,"column":65},"end":{"line":27,"column":3}}},"3":{"name":"deployOption","line":40,"loc":{"start":{"line":40,"column":20},"end":{"line":42,"column":5}}},"4":{"name":"getId","line":60,"loc":{"start":{"line":60,"column":4},"end":{"line":66,"column":40}}}},"statementMap":{"1":{"start":{"line":24,"column":8},"end":{"line":24,"column":25}},"2":{"start":{"line":28,"column":8},"end":{"line":28,"column":37}},"3":{"start":{"line":43,"column":12},"end":{"line":43,"column":80}},"4":{"start":{"line":44,"column":12},"end":{"line":44,"column":89}},"5":{"start":{"line":45,"column":12},"end":{"line":45,"column":30}},"6":{"start":{"line":46,"column":12},"end":{"line":46,"column":80}},"7":{"start":{"line":47,"column":12},"end":{"line":47,"column":48}},"8":{"start":{"line":67,"column":8},"end":{"line":67,"column":76}}},"branchMap":{}},"contracts\\FactoryRedeem.sol":{"l":{"17":29},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\FactoryRedeem.sol","s":{"1":5,"2":29},"b":{},"f":{"1":5,"2":29},"fnMap":{"1":{"name":"constructor","line":14,"loc":{"start":{"line":14,"column":4},"end":{"line":14,"column":38}}},"2":{"name":"deploy","line":16,"loc":{"start":{"line":16,"column":4},"end":{"line":16,"column":87}}}},"statementMap":{"1":{"start":{"line":14,"column":43},"end":{"line":14,"column":69}},"2":{"start":{"line":17,"column":8},"end":{"line":17,"column":69}}},"branchMap":{}},"contracts\\PrimeAMM.sol":{"l":{"45":0,"46":0,"47":0,"48":0,"60":0,"61":0,"62":0,"63":0,"64":0,"69":0,"78":0,"79":0,"80":0,"81":0,"84":0,"87":0,"88":0,"90":0,"91":0,"105":0,"108":0,"111":0,"112":0,"113":0,"114":0,"115":0,"116":0,"135":0,"136":0,"149":0,"155":0,"156":0,"162":0,"165":0,"176":0,"177":0,"180":0,"184":0,"185":0,"186":0,"187":0,"188":0,"198":0,"199":0,"209":0,"216":0,"226":0,"230":0,"233":0,"236":0,"239":0,"242":0,"246":0,"249":0,"250":0,"258":0,"259":0,"260":0,"261":0,"262":0,"280":0,"281":0,"282":0,"290":0,"300":0,"309":0,"310":0,"311":0,"318":0,"319":0,"320":0},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\PrimeAMM.sol","s":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"24":0,"25":0,"26":0,"27":0,"28":0,"29":0,"30":0,"31":0,"32":0,"33":0,"34":0,"35":0,"36":0,"37":0,"38":0,"39":0,"40":0,"41":0,"42":0,"43":0,"44":0,"45":0,"46":0,"47":0,"48":0,"49":0,"50":0,"51":0,"52":0,"53":0,"54":0,"55":0,"56":0,"57":0,"58":0,"59":0,"60":0,"61":0,"62":0,"63":0,"64":0,"65":0,"66":0,"67":0,"68":0,"69":0,"70":0,"71":0,"72":0,"73":0},"b":{"1":[0,0],"2":[0,0],"3":[0,0],"4":[0,0],"5":[0,0],"6":[0,0],"7":[0,0],"8":[0,0],"9":[0,0],"10":[0,0],"11":[0,0],"12":[0,0],"13":[0,0],"14":[0,0]},"f":{"1":0,"2":0,"3":0,"4":0,"5":0,"6":0,"7":0,"8":0,"9":0,"10":0,"11":0,"12":0,"13":0},"fnMap":{"1":{"name":"constructor","line":43,"loc":{"start":{"line":43,"column":37},"end":{"line":44,"column":5}}},"2":{"name":null,"line":51,"loc":{"start":{"line":51,"column":4},"end":{"line":51,"column":28}}},"3":{"name":"deposit","line":57,"loc":{"start":{"line":57,"column":70},"end":{"line":59,"column":5}}},"4":{"name":"withdraw","line":76,"loc":{"start":{"line":76,"column":74},"end":{"line":76,"column":18}}},"5":{"name":"_redeemAndSwapStrike","line":100,"loc":{"start":{"line":100,"column":4},"end":{"line":103,"column":5}}},"6":{"name":"buy","line":133,"loc":{"start":{"line":133,"column":52},"end":{"line":133,"column":18}}},"7":{"name":"sell","line":196,"loc":{"start":{"line":196,"column":53},"end":{"line":196,"column":18}}},"8":{"name":"calculateVolatilityProxy","line":257,"loc":{"start":{"line":257,"column":4},"end":{"line":257,"column":91}}},"9":{"name":"totalUtilized","line":270,"loc":{"start":{"line":270,"column":4},"end":{"line":270,"column":77}}},"10":{"name":"totalUnutilized","line":288,"loc":{"start":{"line":288,"column":4},"end":{"line":288,"column":79}}},"11":{"name":"totalPoolBalance","line":297,"loc":{"start":{"line":297,"column":4},"end":{"line":297,"column":84}}},"12":{"name":"marketRatio","line":308,"loc":{"start":{"line":308,"column":4},"end":{"line":308,"column":77}}},"13":{"name":"sendEther","line":317,"loc":{"start":{"line":317,"column":4},"end":{"line":317,"column":68}}}},"statementMap":{"1":{"start":{"line":45,"column":8},"end":{"line":45,"column":19}},"2":{"start":{"line":46,"column":8},"end":{"line":46,"column":23}},"3":{"start":{"line":47,"column":8},"end":{"line":47,"column":23}},"4":{"start":{"line":48,"column":8},"end":{"line":48,"column":23}},"5":{"start":{"line":60,"column":8},"end":{"line":60,"column":32}},"6":{"start":{"line":61,"column":8},"end":{"line":61,"column":49}},"7":{"start":{"line":62,"column":8},"end":{"line":62,"column":55}},"8":{"start":{"line":63,"column":8},"end":{"line":63,"column":82}},"9":{"start":{"line":64,"column":8},"end":{"line":64,"column":1876}},"10":{"start":{"line":69,"column":8},"end":{"line":69,"column":21}},"11":{"start":{"line":78,"column":8},"end":{"line":78,"column":32}},"12":{"start":{"line":79,"column":8},"end":{"line":79,"column":87}},"13":{"start":{"line":80,"column":8},"end":{"line":80,"column":55}},"14":{"start":{"line":81,"column":8},"end":{"line":81,"column":37}},"15":{"start":{"line":84,"column":8},"end":{"line":84,"column":82}},"16":{"start":{"line":87,"column":8},"end":{"line":87,"column":2816}},"17":{"start":{"line":88,"column":12},"end":{"line":88,"column":84}},"18":{"start":{"line":90,"column":8},"end":{"line":90,"column":61}},"19":{"start":{"line":91,"column":8},"end":{"line":91,"column":61}},"20":{"start":{"line":105,"column":8},"end":{"line":105,"column":50}},"21":{"start":{"line":108,"column":8},"end":{"line":108,"column":48}},"22":{"start":{"line":111,"column":8},"end":{"line":111,"column":56}},"23":{"start":{"line":112,"column":8},"end":{"line":112,"column":35}},"24":{"start":{"line":113,"column":8},"end":{"line":113,"column":48}},"25":{"start":{"line":114,"column":8},"end":{"line":114,"column":23}},"26":{"start":{"line":115,"column":8},"end":{"line":115,"column":23}},"27":{"start":{"line":116,"column":8},"end":{"line":116,"column":4026}},"28":{"start":{"line":135,"column":8},"end":{"line":135,"column":32}},"29":{"start":{"line":136,"column":8},"end":{"line":136,"column":4935}},"30":{"start":{"line":149,"column":8},"end":{"line":149,"column":54}},"31":{"start":{"line":155,"column":8},"end":{"line":155,"column":90}},"32":{"start":{"line":156,"column":8},"end":{"line":156,"column":70}},"33":{"start":{"line":162,"column":8},"end":{"line":162,"column":63}},"34":{"start":{"line":165,"column":8},"end":{"line":165,"column":6422}},"35":{"start":{"line":176,"column":8},"end":{"line":176,"column":53}},"36":{"start":{"line":177,"column":8},"end":{"line":177,"column":47}},"37":{"start":{"line":180,"column":8},"end":{"line":180,"column":53}},"38":{"start":{"line":184,"column":8},"end":{"line":184,"column":85}},"39":{"start":{"line":185,"column":8},"end":{"line":185,"column":85}},"40":{"start":{"line":186,"column":8},"end":{"line":186,"column":58}},"41":{"start":{"line":187,"column":8},"end":{"line":187,"column":89}},"42":{"start":{"line":188,"column":8},"end":{"line":188,"column":86}},"43":{"start":{"line":198,"column":8},"end":{"line":198,"column":32}},"44":{"start":{"line":199,"column":8},"end":{"line":199,"column":8014}},"45":{"start":{"line":209,"column":8},"end":{"line":209,"column":8281}},"46":{"start":{"line":216,"column":8},"end":{"line":216,"column":8485}},"47":{"start":{"line":226,"column":8},"end":{"line":226,"column":56}},"48":{"start":{"line":230,"column":8},"end":{"line":230,"column":53}},"49":{"start":{"line":233,"column":8},"end":{"line":233,"column":88}},"50":{"start":{"line":236,"column":8},"end":{"line":236,"column":51}},"51":{"start":{"line":239,"column":8},"end":{"line":239,"column":46}},"52":{"start":{"line":242,"column":8},"end":{"line":242,"column":99}},"53":{"start":{"line":246,"column":8},"end":{"line":246,"column":43}},"54":{"start":{"line":249,"column":8},"end":{"line":249,"column":48}},"55":{"start":{"line":250,"column":8},"end":{"line":250,"column":59}},"56":{"start":{"line":258,"column":8},"end":{"line":258,"column":48}},"57":{"start":{"line":259,"column":8},"end":{"line":259,"column":53}},"58":{"start":{"line":260,"column":8},"end":{"line":260,"column":84}},"59":{"start":{"line":260,"column":29},"end":{"line":260,"column":83}},"60":{"start":{"line":261,"column":8},"end":{"line":261,"column":10526}},"61":{"start":{"line":262,"column":12},"end":{"line":262,"column":29}},"62":{"start":{"line":263,"column":15},"end":{"line":263,"column":69}},"63":{"start":{"line":280,"column":8},"end":{"line":280,"column":71}},"64":{"start":{"line":281,"column":8},"end":{"line":281,"column":49}},"65":{"start":{"line":282,"column":8},"end":{"line":282,"column":85}},"66":{"start":{"line":290,"column":8},"end":{"line":290,"column":75}},"67":{"start":{"line":300,"column":8},"end":{"line":300,"column":74}},"68":{"start":{"line":309,"column":8},"end":{"line":309,"column":50}},"69":{"start":{"line":310,"column":8},"end":{"line":310,"column":76}},"70":{"start":{"line":311,"column":8},"end":{"line":311,"column":74}},"71":{"start":{"line":318,"column":8},"end":{"line":318,"column":52}},"72":{"start":{"line":319,"column":8},"end":{"line":319,"column":41}},"73":{"start":{"line":320,"column":8},"end":{"line":320,"column":22}}},"branchMap":{"1":{"line":64,"type":"if","locations":[{"start":{"line":64,"column":8},"end":{"line":64,"column":8}},{"start":{"line":64,"column":8},"end":{"line":64,"column":8}}]},"2":{"line":87,"type":"if","locations":[{"start":{"line":87,"column":8},"end":{"line":87,"column":8}},{"start":{"line":87,"column":8},"end":{"line":87,"column":8}}]},"3":{"line":90,"type":"if","locations":[{"start":{"line":90,"column":8},"end":{"line":90,"column":8}},{"start":{"line":90,"column":8},"end":{"line":90,"column":8}}]},"4":{"line":112,"type":"if","locations":[{"start":{"line":112,"column":8},"end":{"line":112,"column":8}},{"start":{"line":112,"column":8},"end":{"line":112,"column":8}}]},"5":{"line":155,"type":"if","locations":[{"start":{"line":155,"column":8},"end":{"line":155,"column":8}},{"start":{"line":155,"column":8},"end":{"line":155,"column":8}}]},"6":{"line":177,"type":"if","locations":[{"start":{"line":177,"column":8},"end":{"line":177,"column":8}},{"start":{"line":177,"column":8},"end":{"line":177,"column":8}}]},"7":{"line":184,"type":"if","locations":[{"start":{"line":184,"column":8},"end":{"line":184,"column":8}},{"start":{"line":184,"column":8},"end":{"line":184,"column":8}}]},"8":{"line":185,"type":"if","locations":[{"start":{"line":185,"column":8},"end":{"line":185,"column":8}},{"start":{"line":185,"column":8},"end":{"line":185,"column":8}}]},"9":{"line":209,"type":"if","locations":[{"start":{"line":209,"column":8},"end":{"line":209,"column":8}},{"start":{"line":209,"column":8},"end":{"line":209,"column":8}}]},"10":{"line":233,"type":"if","locations":[{"start":{"line":233,"column":8},"end":{"line":233,"column":8}},{"start":{"line":233,"column":8},"end":{"line":233,"column":8}}]},"11":{"line":242,"type":"if","locations":[{"start":{"line":242,"column":8},"end":{"line":242,"column":8}},{"start":{"line":242,"column":8},"end":{"line":242,"column":8}}]},"12":{"line":260,"type":"if","locations":[{"start":{"line":260,"column":8},"end":{"line":260,"column":8}},{"start":{"line":260,"column":8},"end":{"line":260,"column":8}}]},"13":{"line":261,"type":"if","locations":[{"start":{"line":261,"column":8},"end":{"line":261,"column":8}},{"start":{"line":261,"column":8},"end":{"line":261,"column":8}}]},"14":{"line":319,"type":"if","locations":[{"start":{"line":319,"column":8},"end":{"line":319,"column":8}},{"start":{"line":319,"column":8},"end":{"line":319,"column":8}}]}}},"contracts\\PrimeOption.sol":{"l":{"44":29,"45":29,"55":103,"56":103,"61":31,"62":29,"76":1,"87":4,"88":4,"91":4,"94":4,"97":4,"106":134,"107":134,"108":134,"131":67,"132":67,"133":67,"136":67,"139":67,"142":61,"145":61,"146":61,"149":61,"150":61,"171":36,"172":36,"175":36,"176":34,"179":32,"180":32,"183":32,"184":32,"185":32,"188":32,"189":32,"192":32,"193":32,"196":32,"199":30,"202":30,"205":30,"208":30,"211":30,"214":30,"215":30,"234":22,"235":22,"238":22,"239":22,"242":22,"243":22,"244":20,"247":18,"248":18,"254":18,"255":18,"258":18,"259":18,"280":32,"281":32,"284":32,"285":32,"286":32,"289":32,"296":32,"303":32,"305":32,"306":26,"309":24,"310":24,"321":24,"322":24,"328":24,"329":24,"332":24,"333":24,"338":37,"339":37,"345":13,"346":13,"347":13,"365":359,"366":359,"367":359,"368":359,"369":359,"370":359,"371":359,"378":2,"379":2},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\PrimeOption.sol","s":{"1":29,"2":29,"3":103,"4":31,"5":29,"6":1,"7":4,"8":4,"9":4,"10":4,"11":4,"12":134,"13":134,"14":134,"15":67,"16":67,"17":67,"18":67,"19":67,"20":61,"21":61,"22":61,"23":61,"24":61,"25":36,"26":36,"27":36,"28":34,"29":32,"30":32,"31":32,"32":32,"33":32,"34":3,"35":32,"36":32,"37":32,"38":32,"39":32,"40":30,"41":30,"42":30,"43":30,"44":30,"45":30,"46":30,"47":22,"48":22,"49":22,"50":22,"51":22,"52":22,"53":20,"54":18,"55":18,"56":18,"57":18,"58":18,"59":18,"60":32,"61":32,"62":32,"63":32,"64":32,"65":32,"66":32,"67":32,"68":32,"69":26,"70":24,"71":24,"72":24,"73":24,"74":24,"75":24,"76":24,"77":24,"78":37,"79":37,"80":13,"81":13,"82":13,"83":154,"84":273,"85":206,"86":216,"87":13,"88":359,"89":359,"90":359,"91":359,"92":359,"93":359,"94":359,"95":2,"96":2},"b":{"1":[103,0],"2":[29,2],"3":[61,6],"4":[34,2],"5":[32,2],"6":[3,29],"7":[30,2],"8":[30,0],"9":[20,2],"10":[18,2],"11":[18,0],"12":[26,6],"13":[24,2],"14":[24,0],"15":[24,0]},"f":{"1":29,"2":103,"3":31,"4":1,"5":4,"6":134,"7":67,"8":36,"9":22,"10":32,"11":37,"12":13,"13":154,"14":273,"15":206,"16":216,"17":13,"18":359,"19":2},"fnMap":{"1":{"name":"constructor","line":42,"loc":{"start":{"line":42,"column":52},"end":{"line":43,"column":5}}},"2":{"name":"notExpired","line":54,"loc":{"start":{"line":54,"column":4},"end":{"line":54,"column":21}}},"3":{"name":"initTokenR","line":60,"loc":{"start":{"line":60,"column":4},"end":{"line":60,"column":45}}},"4":{"name":"update","line":75,"loc":{"start":{"line":75,"column":42},"end":{"line":75,"column":3}}},"5":{"name":"take","line":86,"loc":{"start":{"line":86,"column":40},"end":{"line":86,"column":3}}},"6":{"name":"_fund","line":105,"loc":{"start":{"line":105,"column":4},"end":{"line":105,"column":54}}},"7":{"name":"mint","line":127,"loc":{"start":{"line":127,"column":20},"end":{"line":129,"column":5}}},"8":{"name":"exercise","line":167,"loc":{"start":{"line":167,"column":20},"end":{"line":169,"column":5}}},"9":{"name":"redeem","line":231,"loc":{"start":{"line":231,"column":19},"end":{"line":233,"column":5}}},"10":{"name":"close","line":276,"loc":{"start":{"line":276,"column":19},"end":{"line":278,"column":5}}},"11":{"name":"getCaches","line":337,"loc":{"start":{"line":337,"column":4},"end":{"line":337,"column":80}}},"12":{"name":"getTokens","line":342,"loc":{"start":{"line":342,"column":4},"end":{"line":344,"column":7}}},"13":{"name":"tokenS","line":350,"loc":{"start":{"line":350,"column":4},"end":{"line":350,"column":58}}},"14":{"name":"tokenU","line":351,"loc":{"start":{"line":351,"column":4},"end":{"line":351,"column":58}}},"15":{"name":"base","line":352,"loc":{"start":{"line":352,"column":4},"end":{"line":352,"column":53}}},"16":{"name":"price","line":353,"loc":{"start":{"line":353,"column":4},"end":{"line":353,"column":54}}},"17":{"name":"expiry","line":354,"loc":{"start":{"line":354,"column":4},"end":{"line":354,"column":55}}},"18":{"name":"prime","line":356,"loc":{"start":{"line":356,"column":4},"end":{"line":364,"column":5}}},"19":{"name":"maxDraw","line":377,"loc":{"start":{"line":377,"column":4},"end":{"line":377,"column":61}}}},"statementMap":{"1":{"start":{"line":44,"column":8},"end":{"line":44,"column":27}},"2":{"start":{"line":45,"column":8},"end":{"line":45,"column":1322}},"3":{"start":{"line":55,"column":8},"end":{"line":55,"column":63}},"4":{"start":{"line":61,"column":8},"end":{"line":61,"column":54}},"5":{"start":{"line":62,"column":8},"end":{"line":62,"column":23}},"6":{"start":{"line":76,"column":8},"end":{"line":76,"column":2072}},"7":{"start":{"line":87,"column":8},"end":{"line":87,"column":73}},"8":{"start":{"line":88,"column":8},"end":{"line":88,"column":2503}},"9":{"start":{"line":91,"column":8},"end":{"line":91,"column":2625}},"10":{"start":{"line":94,"column":8},"end":{"line":94,"column":2747}},"11":{"start":{"line":97,"column":8},"end":{"line":97,"column":2857}},"12":{"start":{"line":106,"column":8},"end":{"line":106,"column":24}},"13":{"start":{"line":107,"column":8},"end":{"line":107,"column":24}},"14":{"start":{"line":108,"column":8},"end":{"line":108,"column":37}},"15":{"start":{"line":131,"column":8},"end":{"line":131,"column":70}},"16":{"start":{"line":132,"column":8},"end":{"line":132,"column":31}},"17":{"start":{"line":133,"column":8},"end":{"line":133,"column":33}},"18":{"start":{"line":136,"column":8},"end":{"line":136,"column":38}},"19":{"start":{"line":139,"column":8},"end":{"line":139,"column":55}},"20":{"start":{"line":142,"column":8},"end":{"line":142,"column":48}},"21":{"start":{"line":145,"column":8},"end":{"line":145,"column":53}},"22":{"start":{"line":146,"column":8},"end":{"line":146,"column":32}},"23":{"start":{"line":149,"column":8},"end":{"line":149,"column":30}},"24":{"start":{"line":150,"column":8},"end":{"line":150,"column":48}},"25":{"start":{"line":171,"column":8},"end":{"line":171,"column":39}},"26":{"start":{"line":172,"column":8},"end":{"line":172,"column":50}},"27":{"start":{"line":175,"column":8},"end":{"line":175,"column":41}},"28":{"start":{"line":176,"column":8},"end":{"line":176,"column":58}},"29":{"start":{"line":179,"column":8},"end":{"line":179,"column":38}},"30":{"start":{"line":180,"column":8},"end":{"line":180,"column":38}},"31":{"start":{"line":183,"column":8},"end":{"line":183,"column":52}},"32":{"start":{"line":184,"column":8},"end":{"line":184,"column":46}},"33":{"start":{"line":185,"column":8},"end":{"line":185,"column":92}},"34":{"start":{"line":185,"column":29},"end":{"line":185,"column":91}},"35":{"start":{"line":188,"column":8},"end":{"line":188,"column":70}},"36":{"start":{"line":189,"column":8},"end":{"line":189,"column":64}},"37":{"start":{"line":192,"column":8},"end":{"line":192,"column":39}},"38":{"start":{"line":193,"column":8},"end":{"line":193,"column":70}},"39":{"start":{"line":196,"column":8},"end":{"line":196,"column":56}},"40":{"start":{"line":199,"column":8},"end":{"line":199,"column":78}},"41":{"start":{"line":202,"column":8},"end":{"line":202,"column":70}},"42":{"start":{"line":205,"column":8},"end":{"line":205,"column":42}},"43":{"start":{"line":208,"column":8},"end":{"line":208,"column":80}},"44":{"start":{"line":211,"column":8},"end":{"line":211,"column":37}},"45":{"start":{"line":214,"column":8},"end":{"line":214,"column":32}},"46":{"start":{"line":215,"column":8},"end":{"line":215,"column":52}},"47":{"start":{"line":234,"column":8},"end":{"line":234,"column":39}},"48":{"start":{"line":235,"column":8},"end":{"line":235,"column":32}},"49":{"start":{"line":238,"column":8},"end":{"line":238,"column":64}},"50":{"start":{"line":239,"column":8},"end":{"line":239,"column":64}},"51":{"start":{"line":242,"column":8},"end":{"line":242,"column":26}},"52":{"start":{"line":243,"column":8},"end":{"line":243,"column":40}},"53":{"start":{"line":244,"column":8},"end":{"line":244,"column":54}},"54":{"start":{"line":247,"column":8},"end":{"line":247,"column":58}},"55":{"start":{"line":248,"column":8},"end":{"line":248,"column":8505}},"56":{"start":{"line":254,"column":8},"end":{"line":254,"column":58}},"57":{"start":{"line":255,"column":8},"end":{"line":255,"column":58}},"58":{"start":{"line":258,"column":8},"end":{"line":258,"column":30}},"59":{"start":{"line":259,"column":8},"end":{"line":259,"column":39}},"60":{"start":{"line":280,"column":8},"end":{"line":280,"column":39}},"61":{"start":{"line":281,"column":8},"end":{"line":281,"column":32}},"62":{"start":{"line":284,"column":8},"end":{"line":284,"column":64}},"63":{"start":{"line":285,"column":8},"end":{"line":285,"column":64}},"64":{"start":{"line":286,"column":8},"end":{"line":286,"column":48}},"65":{"start":{"line":289,"column":8},"end":{"line":289,"column":26}},"66":{"start":{"line":296,"column":8},"end":{"line":296,"column":62}},"67":{"start":{"line":303,"column":8},"end":{"line":303,"column":72}},"68":{"start":{"line":305,"column":8},"end":{"line":305,"column":56}},"69":{"start":{"line":306,"column":8},"end":{"line":306,"column":84}},"70":{"start":{"line":309,"column":8},"end":{"line":309,"column":11145}},"71":{"start":{"line":310,"column":12},"end":{"line":310,"column":41}},"72":{"start":{"line":321,"column":8},"end":{"line":321,"column":58}},"73":{"start":{"line":322,"column":8},"end":{"line":322,"column":11827}},"74":{"start":{"line":328,"column":8},"end":{"line":328,"column":58}},"75":{"start":{"line":329,"column":8},"end":{"line":329,"column":58}},"76":{"start":{"line":332,"column":8},"end":{"line":332,"column":30}},"77":{"start":{"line":333,"column":8},"end":{"line":333,"column":39}},"78":{"start":{"line":338,"column":8},"end":{"line":338,"column":23}},"79":{"start":{"line":339,"column":8},"end":{"line":339,"column":23}},"80":{"start":{"line":345,"column":8},"end":{"line":345,"column":30}},"81":{"start":{"line":346,"column":8},"end":{"line":346,"column":30}},"82":{"start":{"line":347,"column":8},"end":{"line":347,"column":23}},"83":{"start":{"line":350,"column":63},"end":{"line":350,"column":83}},"84":{"start":{"line":351,"column":63},"end":{"line":351,"column":83}},"85":{"start":{"line":352,"column":58},"end":{"line":352,"column":76}},"86":{"start":{"line":353,"column":59},"end":{"line":353,"column":78}},"87":{"start":{"line":354,"column":60},"end":{"line":354,"column":80}},"88":{"start":{"line":365,"column":8},"end":{"line":365,"column":48}},"89":{"start":{"line":366,"column":8},"end":{"line":366,"column":30}},"90":{"start":{"line":367,"column":8},"end":{"line":367,"column":30}},"91":{"start":{"line":368,"column":8},"end":{"line":368,"column":23}},"92":{"start":{"line":369,"column":8},"end":{"line":369,"column":26}},"93":{"start":{"line":370,"column":8},"end":{"line":370,"column":28}},"94":{"start":{"line":371,"column":8},"end":{"line":371,"column":30}},"95":{"start":{"line":378,"column":8},"end":{"line":378,"column":60}},"96":{"start":{"line":379,"column":8},"end":{"line":379,"column":51}}},"branchMap":{"1":{"line":55,"type":"if","locations":[{"start":{"line":55,"column":8},"end":{"line":55,"column":8}},{"start":{"line":55,"column":8},"end":{"line":55,"column":8}}]},"2":{"line":61,"type":"if","locations":[{"start":{"line":61,"column":8},"end":{"line":61,"column":8}},{"start":{"line":61,"column":8},"end":{"line":61,"column":8}}]},"3":{"line":139,"type":"if","locations":[{"start":{"line":139,"column":8},"end":{"line":139,"column":8}},{"start":{"line":139,"column":8},"end":{"line":139,"column":8}}]},"4":{"line":175,"type":"if","locations":[{"start":{"line":175,"column":8},"end":{"line":175,"column":8}},{"start":{"line":175,"column":8},"end":{"line":175,"column":8}}]},"5":{"line":176,"type":"if","locations":[{"start":{"line":176,"column":8},"end":{"line":176,"column":8}},{"start":{"line":176,"column":8},"end":{"line":176,"column":8}}]},"6":{"line":185,"type":"if","locations":[{"start":{"line":185,"column":8},"end":{"line":185,"column":8}},{"start":{"line":185,"column":8},"end":{"line":185,"column":8}}]},"7":{"line":196,"type":"if","locations":[{"start":{"line":196,"column":8},"end":{"line":196,"column":8}},{"start":{"line":196,"column":8},"end":{"line":196,"column":8}}]},"8":{"line":208,"type":"if","locations":[{"start":{"line":208,"column":8},"end":{"line":208,"column":8}},{"start":{"line":208,"column":8},"end":{"line":208,"column":8}}]},"9":{"line":243,"type":"if","locations":[{"start":{"line":243,"column":8},"end":{"line":243,"column":8}},{"start":{"line":243,"column":8},"end":{"line":243,"column":8}}]},"10":{"line":244,"type":"if","locations":[{"start":{"line":244,"column":8},"end":{"line":244,"column":8}},{"start":{"line":244,"column":8},"end":{"line":244,"column":8}}]},"11":{"line":248,"type":"if","locations":[{"start":{"line":248,"column":8},"end":{"line":248,"column":8}},{"start":{"line":248,"column":8},"end":{"line":248,"column":8}}]},"12":{"line":305,"type":"if","locations":[{"start":{"line":305,"column":8},"end":{"line":305,"column":8}},{"start":{"line":305,"column":8},"end":{"line":305,"column":8}}]},"13":{"line":306,"type":"if","locations":[{"start":{"line":306,"column":8},"end":{"line":306,"column":8}},{"start":{"line":306,"column":8},"end":{"line":306,"column":8}}]},"14":{"line":309,"type":"if","locations":[{"start":{"line":309,"column":8},"end":{"line":309,"column":8}},{"start":{"line":309,"column":8},"end":{"line":309,"column":8}}]},"15":{"line":322,"type":"if","locations":[{"start":{"line":322,"column":8},"end":{"line":322,"column":8}},{"start":{"line":322,"column":8},"end":{"line":322,"column":8}}]}}},"contracts\\PrimePerpetual.sol":{"l":{"29":7,"30":7,"31":7,"32":7,"33":7,"39":28,"40":28,"41":28,"42":28,"43":28,"48":24,"49":24,"53":10,"54":10,"55":10,"56":10,"57":8,"58":8,"59":8,"60":8,"69":21,"70":21,"75":21,"76":21,"77":21,"78":21,"84":19,"85":19,"86":19,"92":19,"96":19,"97":19,"100":19,"102":19,"103":19,"110":12,"111":12,"112":12,"115":10,"118":10,"121":10,"124":10,"125":10,"126":10,"129":10,"130":10,"134":11,"135":11,"136":11,"139":9,"142":9,"145":9,"148":9,"149":9,"152":9,"153":9,"162":43,"163":43,"164":43,"173":46,"174":46,"175":46,"179":254,"180":254,"184":178,"185":178,"186":178},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\PrimePerpetual.sol","s":{"1":7,"2":7,"3":7,"4":7,"5":7,"6":28,"7":28,"8":28,"9":28,"10":28,"11":24,"12":24,"13":10,"14":10,"15":10,"16":10,"17":8,"18":8,"19":8,"20":8,"21":21,"22":21,"23":21,"24":21,"25":21,"26":21,"27":19,"28":19,"29":19,"30":19,"31":19,"32":19,"33":19,"34":19,"35":19,"36":12,"37":12,"38":12,"39":10,"40":10,"41":10,"42":10,"43":10,"44":10,"45":10,"46":10,"47":11,"48":11,"49":11,"50":9,"51":9,"52":9,"53":9,"54":9,"55":9,"56":9,"57":43,"58":43,"59":43,"60":46,"61":46,"62":46,"63":254,"64":254,"65":178,"66":178,"67":178},"b":{"1":[24,4],"2":[8,0],"3":[19,2],"4":[19,0],"5":[19,0],"6":[10,2],"7":[10,0],"8":[9,2],"9":[9,0],"10":[43,0],"11":[46,0]},"f":{"1":7,"2":28,"3":10,"4":21,"5":12,"6":11,"7":43,"8":46,"9":254,"10":178},"fnMap":{"1":{"name":"constructor","line":27,"loc":{"start":{"line":27,"column":44},"end":{"line":28,"column":5}}},"2":{"name":"deposit","line":36,"loc":{"start":{"line":36,"column":79},"end":{"line":38,"column":5}}},"3":{"name":"withdraw","line":52,"loc":{"start":{"line":52,"column":83},"end":{"line":52,"column":18}}},"4":{"name":"mint","line":67,"loc":{"start":{"line":67,"column":76},"end":{"line":67,"column":18}}},"5":{"name":"redeem","line":109,"loc":{"start":{"line":109,"column":64},"end":{"line":109,"column":18}}},"6":{"name":"exercise","line":133,"loc":{"start":{"line":133,"column":66},"end":{"line":133,"column":18}}},"7":{"name":"swapToInterestBearing","line":161,"loc":{"start":{"line":161,"column":4},"end":{"line":161,"column":84}}},"8":{"name":"swapFromInterestBearing","line":172,"loc":{"start":{"line":172,"column":4},"end":{"line":172,"column":86}}},"9":{"name":"interestBalances","line":178,"loc":{"start":{"line":178,"column":4},"end":{"line":178,"column":89}}},"10":{"name":"totalBalance","line":183,"loc":{"start":{"line":183,"column":4},"end":{"line":183,"column":74}}}},"statementMap":{"1":{"start":{"line":29,"column":8},"end":{"line":29,"column":17}},"2":{"start":{"line":30,"column":8},"end":{"line":30,"column":19}},"3":{"start":{"line":31,"column":8},"end":{"line":31,"column":21}},"4":{"start":{"line":32,"column":8},"end":{"line":32,"column":78}},"5":{"start":{"line":33,"column":8},"end":{"line":33,"column":77}},"6":{"start":{"line":39,"column":8},"end":{"line":39,"column":32}},"7":{"start":{"line":40,"column":8},"end":{"line":40,"column":52}},"8":{"start":{"line":41,"column":8},"end":{"line":41,"column":44}},"9":{"start":{"line":42,"column":8},"end":{"line":42,"column":82}},"10":{"start":{"line":43,"column":8},"end":{"line":43,"column":1472}},"11":{"start":{"line":48,"column":8},"end":{"line":48,"column":45}},"12":{"start":{"line":49,"column":8},"end":{"line":49,"column":21}},"13":{"start":{"line":53,"column":8},"end":{"line":53,"column":32}},"14":{"start":{"line":54,"column":8},"end":{"line":54,"column":52}},"15":{"start":{"line":55,"column":8},"end":{"line":55,"column":44}},"16":{"start":{"line":56,"column":8},"end":{"line":56,"column":82}},"17":{"start":{"line":57,"column":8},"end":{"line":57,"column":48}},"18":{"start":{"line":58,"column":8},"end":{"line":58,"column":37}},"19":{"start":{"line":59,"column":8},"end":{"line":59,"column":61}},"20":{"start":{"line":60,"column":8},"end":{"line":60,"column":61}},"21":{"start":{"line":69,"column":8},"end":{"line":69,"column":32}},"22":{"start":{"line":70,"column":8},"end":{"line":70,"column":92}},"23":{"start":{"line":75,"column":8},"end":{"line":75,"column":54}},"24":{"start":{"line":76,"column":8},"end":{"line":76,"column":37}},"25":{"start":{"line":77,"column":8},"end":{"line":77,"column":41}},"26":{"start":{"line":78,"column":8},"end":{"line":78,"column":81}},"27":{"start":{"line":84,"column":8},"end":{"line":84,"column":48}},"28":{"start":{"line":85,"column":8},"end":{"line":85,"column":90}},"29":{"start":{"line":86,"column":8},"end":{"line":86,"column":70}},"30":{"start":{"line":92,"column":8},"end":{"line":92,"column":63}},"31":{"start":{"line":96,"column":8},"end":{"line":96,"column":67}},"32":{"start":{"line":97,"column":8},"end":{"line":97,"column":52}},"33":{"start":{"line":100,"column":8},"end":{"line":100,"column":89}},"34":{"start":{"line":102,"column":8},"end":{"line":102,"column":43}},"35":{"start":{"line":103,"column":8},"end":{"line":103,"column":86}},"36":{"start":{"line":110,"column":8},"end":{"line":110,"column":32}},"37":{"start":{"line":111,"column":8},"end":{"line":111,"column":92}},"38":{"start":{"line":112,"column":8},"end":{"line":112,"column":82}},"39":{"start":{"line":115,"column":8},"end":{"line":115,"column":54}},"40":{"start":{"line":118,"column":8},"end":{"line":118,"column":47}},"41":{"start":{"line":121,"column":8},"end":{"line":121,"column":67}},"42":{"start":{"line":124,"column":8},"end":{"line":124,"column":53}},"43":{"start":{"line":125,"column":8},"end":{"line":125,"column":66}},"44":{"start":{"line":126,"column":8},"end":{"line":126,"column":50}},"45":{"start":{"line":129,"column":8},"end":{"line":129,"column":43}},"46":{"start":{"line":130,"column":8},"end":{"line":130,"column":56}},"47":{"start":{"line":134,"column":8},"end":{"line":134,"column":32}},"48":{"start":{"line":135,"column":8},"end":{"line":135,"column":92}},"49":{"start":{"line":136,"column":8},"end":{"line":136,"column":82}},"50":{"start":{"line":139,"column":8},"end":{"line":139,"column":54}},"51":{"start":{"line":142,"column":8},"end":{"line":142,"column":47}},"52":{"start":{"line":145,"column":8},"end":{"line":145,"column":67}},"53":{"start":{"line":148,"column":8},"end":{"line":148,"column":50}},"54":{"start":{"line":149,"column":8},"end":{"line":149,"column":66}},"55":{"start":{"line":152,"column":8},"end":{"line":152,"column":67}},"56":{"start":{"line":153,"column":8},"end":{"line":153,"column":50}},"57":{"start":{"line":162,"column":8},"end":{"line":162,"column":53}},"58":{"start":{"line":163,"column":8},"end":{"line":163,"column":47}},"59":{"start":{"line":164,"column":8},"end":{"line":164,"column":27}},"60":{"start":{"line":173,"column":8},"end":{"line":173,"column":67}},"61":{"start":{"line":174,"column":8},"end":{"line":174,"column":54}},"62":{"start":{"line":175,"column":8},"end":{"line":175,"column":32}},"63":{"start":{"line":179,"column":8},"end":{"line":179,"column":67}},"64":{"start":{"line":180,"column":8},"end":{"line":180,"column":66}},"65":{"start":{"line":184,"column":8},"end":{"line":184,"column":45}},"66":{"start":{"line":185,"column":8},"end":{"line":185,"column":77}},"67":{"start":{"line":186,"column":8},"end":{"line":186,"column":96}}},"branchMap":{"1":{"line":43,"type":"if","locations":[{"start":{"line":43,"column":8},"end":{"line":43,"column":8}},{"start":{"line":43,"column":8},"end":{"line":43,"column":8}}]},"2":{"line":59,"type":"if","locations":[{"start":{"line":59,"column":8},"end":{"line":59,"column":8}},{"start":{"line":59,"column":8},"end":{"line":59,"column":8}}]},"3":{"line":78,"type":"if","locations":[{"start":{"line":78,"column":8},"end":{"line":78,"column":8}},{"start":{"line":78,"column":8},"end":{"line":78,"column":8}}]},"4":{"line":85,"type":"if","locations":[{"start":{"line":85,"column":8},"end":{"line":85,"column":8}},{"start":{"line":85,"column":8},"end":{"line":85,"column":8}}]},"5":{"line":96,"type":"if","locations":[{"start":{"line":96,"column":8},"end":{"line":96,"column":8}},{"start":{"line":96,"column":8},"end":{"line":96,"column":8}}]},"6":{"line":112,"type":"if","locations":[{"start":{"line":112,"column":8},"end":{"line":112,"column":8}},{"start":{"line":112,"column":8},"end":{"line":112,"column":8}}]},"7":{"line":121,"type":"if","locations":[{"start":{"line":121,"column":8},"end":{"line":121,"column":8}},{"start":{"line":121,"column":8},"end":{"line":121,"column":8}}]},"8":{"line":136,"type":"if","locations":[{"start":{"line":136,"column":8},"end":{"line":136,"column":8}},{"start":{"line":136,"column":8},"end":{"line":136,"column":8}}]},"9":{"line":145,"type":"if","locations":[{"start":{"line":145,"column":8},"end":{"line":145,"column":8}},{"start":{"line":145,"column":8},"end":{"line":145,"column":8}}]},"10":{"line":163,"type":"if","locations":[{"start":{"line":163,"column":8},"end":{"line":163,"column":8}},{"start":{"line":163,"column":8},"end":{"line":163,"column":8}}]},"11":{"line":174,"type":"if","locations":[{"start":{"line":174,"column":8},"end":{"line":174,"column":8}},{"start":{"line":174,"column":8},"end":{"line":174,"column":8}}]}}},"contracts\\PrimeRedeem.sol":{"l":{"24":29,"25":29,"26":29,"30":63,"31":61,"35":44,"36":42},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\PrimeRedeem.sol","s":{"1":29,"2":29,"3":29,"4":63,"5":61,"6":44,"7":42},"b":{"1":[61,2],"2":[42,2]},"f":{"1":29,"2":63,"3":44},"fnMap":{"1":{"name":"constructor","line":22,"loc":{"start":{"line":22,"column":49},"end":{"line":23,"column":5}}},"2":{"name":"mint","line":29,"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":58}}},"3":{"name":"burn","line":34,"loc":{"start":{"line":34,"column":4},"end":{"line":34,"column":58}}}},"statementMap":{"1":{"start":{"line":24,"column":8},"end":{"line":24,"column":25}},"2":{"start":{"line":25,"column":8},"end":{"line":25,"column":23}},"3":{"start":{"line":26,"column":8},"end":{"line":26,"column":31}},"4":{"start":{"line":30,"column":8},"end":{"line":30,"column":53}},"5":{"start":{"line":31,"column":8},"end":{"line":31,"column":24}},"6":{"start":{"line":35,"column":8},"end":{"line":35,"column":53}},"7":{"start":{"line":36,"column":8},"end":{"line":36,"column":24}}},"branchMap":{"1":{"line":30,"type":"if","locations":[{"start":{"line":30,"column":8},"end":{"line":30,"column":8}},{"start":{"line":30,"column":8},"end":{"line":30,"column":8}}]},"2":{"line":35,"type":"if","locations":[{"start":{"line":35,"column":8},"end":{"line":35,"column":8}},{"start":{"line":35,"column":8},"end":{"line":35,"column":8}}]}}}} \ No newline at end of file +{"contracts\\applications\\PrimeAMM.sol":{"l":{"44":22,"45":22,"46":22,"47":22,"48":22,"58":23,"59":23,"60":23,"61":23,"62":21,"66":19,"75":23,"76":23,"77":23,"78":23,"81":23,"84":15,"85":2,"87":15,"88":13,"102":2,"103":2,"104":2,"107":2,"108":2,"110":2,"111":2,"113":2,"114":2,"115":2,"116":2,"133":25,"134":25,"144":25,"147":21,"150":21,"160":21,"161":21,"162":21,"166":21,"167":21,"168":21,"178":14,"179":14,"189":14,"196":10,"206":10,"210":10,"211":10,"214":10,"217":10,"218":10,"221":10,"222":10,"225":10,"226":10,"234":157,"235":157,"236":157,"237":157,"238":46,"256":777,"257":777,"265":619,"275":457},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\applications\\PrimeAMM.sol","s":{"1":22,"2":22,"3":22,"4":22,"5":22,"6":23,"7":23,"8":23,"9":23,"10":21,"11":19,"12":23,"13":23,"14":23,"15":23,"16":23,"17":15,"18":2,"19":15,"20":13,"21":2,"22":2,"23":2,"24":2,"25":2,"26":2,"27":2,"28":2,"29":2,"30":2,"31":2,"32":25,"33":25,"34":25,"35":21,"36":21,"37":21,"38":21,"39":14,"40":21,"41":21,"42":21,"43":21,"44":14,"45":14,"46":14,"47":10,"48":10,"49":10,"50":10,"51":7,"52":10,"53":10,"54":10,"55":10,"56":10,"57":10,"58":10,"59":157,"60":157,"61":157,"62":144,"63":157,"64":46,"65":111,"66":777,"67":777,"68":619,"69":457},"b":{"1":[19,2],"2":[2,13],"3":[13,2],"4":[2,0],"5":[14,7],"6":[21,0],"7":[10,4],"8":[7,3],"9":[10,0],"10":[10,0],"11":[10,0],"12":[144,13],"13":[46,111]},"f":{"1":22,"2":23,"3":23,"4":2,"5":25,"6":14,"7":157,"8":777,"9":619,"10":457},"fnMap":{"1":{"name":"constructor","line":42,"loc":{"start":{"line":42,"column":35},"end":{"line":43,"column":5}}},"2":{"name":"deposit","line":55,"loc":{"start":{"line":55,"column":70},"end":{"line":57,"column":5}}},"3":{"name":"withdraw","line":73,"loc":{"start":{"line":73,"column":74},"end":{"line":73,"column":18}}},"4":{"name":"_redeemAndSwapStrike","line":97,"loc":{"start":{"line":97,"column":4},"end":{"line":100,"column":5}}},"5":{"name":"buy","line":131,"loc":{"start":{"line":131,"column":53},"end":{"line":131,"column":18}}},"6":{"name":"sell","line":176,"loc":{"start":{"line":176,"column":53},"end":{"line":176,"column":18}}},"7":{"name":"calculateVolatilityProxy","line":233,"loc":{"start":{"line":233,"column":4},"end":{"line":233,"column":91}}},"8":{"name":"totalUtilized","line":246,"loc":{"start":{"line":246,"column":4},"end":{"line":246,"column":77}}},"9":{"name":"totalUnutilized","line":263,"loc":{"start":{"line":263,"column":4},"end":{"line":263,"column":79}}},"10":{"name":"totalPoolBalance","line":272,"loc":{"start":{"line":272,"column":4},"end":{"line":272,"column":84}}}},"statementMap":{"1":{"start":{"line":44,"column":8},"end":{"line":44,"column":19}},"2":{"start":{"line":45,"column":8},"end":{"line":45,"column":23}},"3":{"start":{"line":46,"column":8},"end":{"line":46,"column":23}},"4":{"start":{"line":47,"column":8},"end":{"line":47,"column":23}},"5":{"start":{"line":48,"column":8},"end":{"line":48,"column":73}},"6":{"start":{"line":58,"column":8},"end":{"line":58,"column":32}},"7":{"start":{"line":59,"column":8},"end":{"line":59,"column":49}},"8":{"start":{"line":60,"column":8},"end":{"line":60,"column":55}},"9":{"start":{"line":61,"column":8},"end":{"line":61,"column":73}},"10":{"start":{"line":62,"column":8},"end":{"line":62,"column":1832}},"11":{"start":{"line":66,"column":8},"end":{"line":66,"column":21}},"12":{"start":{"line":75,"column":8},"end":{"line":75,"column":32}},"13":{"start":{"line":76,"column":8},"end":{"line":76,"column":87}},"14":{"start":{"line":77,"column":8},"end":{"line":77,"column":55}},"15":{"start":{"line":78,"column":8},"end":{"line":78,"column":37}},"16":{"start":{"line":81,"column":8},"end":{"line":81,"column":82}},"17":{"start":{"line":84,"column":8},"end":{"line":84,"column":2708}},"18":{"start":{"line":85,"column":12},"end":{"line":85,"column":64}},"19":{"start":{"line":87,"column":8},"end":{"line":87,"column":61}},"20":{"start":{"line":88,"column":8},"end":{"line":88,"column":61}},"21":{"start":{"line":102,"column":8},"end":{"line":102,"column":63}},"22":{"start":{"line":103,"column":8},"end":{"line":103,"column":46}},"23":{"start":{"line":104,"column":8},"end":{"line":104,"column":60}},"24":{"start":{"line":107,"column":8},"end":{"line":107,"column":52}},"25":{"start":{"line":108,"column":8},"end":{"line":108,"column":35}},"26":{"start":{"line":110,"column":8},"end":{"line":110,"column":56}},"27":{"start":{"line":111,"column":8},"end":{"line":111,"column":84}},"28":{"start":{"line":113,"column":8},"end":{"line":113,"column":48}},"29":{"start":{"line":114,"column":8},"end":{"line":114,"column":23}},"30":{"start":{"line":115,"column":8},"end":{"line":115,"column":23}},"31":{"start":{"line":116,"column":8},"end":{"line":116,"column":3986}},"32":{"start":{"line":133,"column":8},"end":{"line":133,"column":32}},"33":{"start":{"line":134,"column":8},"end":{"line":134,"column":4689}},"34":{"start":{"line":144,"column":8},"end":{"line":144,"column":38}},"35":{"start":{"line":147,"column":8},"end":{"line":147,"column":53}},"36":{"start":{"line":150,"column":8},"end":{"line":150,"column":5261}},"37":{"start":{"line":160,"column":8},"end":{"line":160,"column":54}},"38":{"start":{"line":161,"column":8},"end":{"line":161,"column":58}},"39":{"start":{"line":161,"column":27},"end":{"line":161,"column":57}},"40":{"start":{"line":162,"column":8},"end":{"line":162,"column":47}},"41":{"start":{"line":166,"column":8},"end":{"line":166,"column":48}},"42":{"start":{"line":167,"column":8},"end":{"line":167,"column":70}},"43":{"start":{"line":168,"column":8},"end":{"line":168,"column":62}},"44":{"start":{"line":178,"column":8},"end":{"line":178,"column":32}},"45":{"start":{"line":179,"column":8},"end":{"line":179,"column":6459}},"46":{"start":{"line":189,"column":8},"end":{"line":189,"column":6716}},"47":{"start":{"line":196,"column":8},"end":{"line":196,"column":6913}},"48":{"start":{"line":206,"column":8},"end":{"line":206,"column":56}},"49":{"start":{"line":210,"column":8},"end":{"line":210,"column":53}},"50":{"start":{"line":211,"column":8},"end":{"line":211,"column":62}},"51":{"start":{"line":211,"column":29},"end":{"line":211,"column":59}},"52":{"start":{"line":214,"column":8},"end":{"line":214,"column":88}},"53":{"start":{"line":217,"column":8},"end":{"line":217,"column":54}},"54":{"start":{"line":218,"column":8},"end":{"line":218,"column":86}},"55":{"start":{"line":221,"column":8},"end":{"line":221,"column":54}},"56":{"start":{"line":222,"column":8},"end":{"line":222,"column":36}},"57":{"start":{"line":225,"column":8},"end":{"line":225,"column":48}},"58":{"start":{"line":226,"column":8},"end":{"line":226,"column":59}},"59":{"start":{"line":234,"column":8},"end":{"line":234,"column":48}},"60":{"start":{"line":235,"column":8},"end":{"line":235,"column":53}},"61":{"start":{"line":236,"column":8},"end":{"line":236,"column":84}},"62":{"start":{"line":236,"column":29},"end":{"line":236,"column":83}},"63":{"start":{"line":237,"column":8},"end":{"line":237,"column":8800}},"64":{"start":{"line":238,"column":12},"end":{"line":238,"column":29}},"65":{"start":{"line":239,"column":15},"end":{"line":239,"column":69}},"66":{"start":{"line":256,"column":8},"end":{"line":256,"column":80}},"67":{"start":{"line":257,"column":8},"end":{"line":257,"column":78}},"68":{"start":{"line":265,"column":8},"end":{"line":265,"column":75}},"69":{"start":{"line":275,"column":8},"end":{"line":275,"column":74}}},"branchMap":{"1":{"line":62,"type":"if","locations":[{"start":{"line":62,"column":8},"end":{"line":62,"column":8}},{"start":{"line":62,"column":8},"end":{"line":62,"column":8}}]},"2":{"line":84,"type":"if","locations":[{"start":{"line":84,"column":8},"end":{"line":84,"column":8}},{"start":{"line":84,"column":8},"end":{"line":84,"column":8}}]},"3":{"line":87,"type":"if","locations":[{"start":{"line":87,"column":8},"end":{"line":87,"column":8}},{"start":{"line":87,"column":8},"end":{"line":87,"column":8}}]},"4":{"line":108,"type":"if","locations":[{"start":{"line":108,"column":8},"end":{"line":108,"column":8}},{"start":{"line":108,"column":8},"end":{"line":108,"column":8}}]},"5":{"line":161,"type":"if","locations":[{"start":{"line":161,"column":8},"end":{"line":161,"column":8}},{"start":{"line":161,"column":8},"end":{"line":161,"column":8}}]},"6":{"line":162,"type":"if","locations":[{"start":{"line":162,"column":8},"end":{"line":162,"column":8}},{"start":{"line":162,"column":8},"end":{"line":162,"column":8}}]},"7":{"line":189,"type":"if","locations":[{"start":{"line":189,"column":8},"end":{"line":189,"column":8}},{"start":{"line":189,"column":8},"end":{"line":189,"column":8}}]},"8":{"line":211,"type":"if","locations":[{"start":{"line":211,"column":8},"end":{"line":211,"column":8}},{"start":{"line":211,"column":8},"end":{"line":211,"column":8}}]},"9":{"line":214,"type":"if","locations":[{"start":{"line":214,"column":8},"end":{"line":214,"column":8}},{"start":{"line":214,"column":8},"end":{"line":214,"column":8}}]},"10":{"line":218,"type":"if","locations":[{"start":{"line":218,"column":8},"end":{"line":218,"column":8}},{"start":{"line":218,"column":8},"end":{"line":218,"column":8}}]},"11":{"line":222,"type":"if","locations":[{"start":{"line":222,"column":8},"end":{"line":222,"column":8}},{"start":{"line":222,"column":8},"end":{"line":222,"column":8}}]},"12":{"line":236,"type":"if","locations":[{"start":{"line":236,"column":8},"end":{"line":236,"column":8}},{"start":{"line":236,"column":8},"end":{"line":236,"column":8}}]},"13":{"line":237,"type":"if","locations":[{"start":{"line":237,"column":8},"end":{"line":237,"column":8}},{"start":{"line":237,"column":8},"end":{"line":237,"column":8}}]}}},"contracts\\applications\\PrimePerpetual.sol":{"l":{"29":7,"30":7,"31":7,"32":7,"33":7,"39":28,"40":28,"41":28,"42":26,"47":24,"48":24,"52":10,"53":10,"54":10,"55":8,"56":8,"65":21,"66":21,"70":21,"71":21,"72":21,"73":21,"79":19,"80":19,"83":19,"85":19,"86":19,"87":19,"94":12,"95":12,"96":12,"99":10,"102":10,"105":10,"108":10,"109":10,"113":11,"114":11,"115":11,"118":9,"119":9,"122":9,"125":9,"126":9,"135":43,"136":43,"137":43,"146":46,"147":46,"148":46,"152":254,"153":254,"157":178,"158":178,"159":178},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\applications\\PrimePerpetual.sol","s":{"1":7,"2":7,"3":7,"4":7,"5":7,"6":28,"7":28,"8":28,"9":26,"10":24,"11":24,"12":10,"13":10,"14":10,"15":8,"16":8,"17":21,"18":21,"19":21,"20":21,"21":21,"22":21,"23":19,"24":19,"25":19,"26":19,"27":19,"28":19,"29":12,"30":12,"31":12,"32":10,"33":10,"34":10,"35":10,"36":10,"37":11,"38":11,"39":11,"40":9,"41":9,"42":9,"43":9,"44":9,"45":43,"46":43,"47":43,"48":46,"49":46,"50":46,"51":254,"52":254,"53":178,"54":178,"55":178},"b":{"1":[24,2],"2":[19,2],"3":[10,2],"4":[9,2],"5":[43,0],"6":[46,0]},"f":{"1":7,"2":28,"3":10,"4":21,"5":12,"6":11,"7":43,"8":46,"9":254,"10":178},"fnMap":{"1":{"name":"constructor","line":27,"loc":{"start":{"line":27,"column":42},"end":{"line":28,"column":5}}},"2":{"name":"deposit","line":36,"loc":{"start":{"line":36,"column":79},"end":{"line":38,"column":5}}},"3":{"name":"withdraw","line":51,"loc":{"start":{"line":51,"column":83},"end":{"line":51,"column":18}}},"4":{"name":"mint","line":63,"loc":{"start":{"line":63,"column":76},"end":{"line":63,"column":18}}},"5":{"name":"redeem","line":93,"loc":{"start":{"line":93,"column":64},"end":{"line":93,"column":18}}},"6":{"name":"exercise","line":112,"loc":{"start":{"line":112,"column":66},"end":{"line":112,"column":18}}},"7":{"name":"swapToInterestBearing","line":134,"loc":{"start":{"line":134,"column":4},"end":{"line":134,"column":84}}},"8":{"name":"swapFromInterestBearing","line":145,"loc":{"start":{"line":145,"column":4},"end":{"line":145,"column":86}}},"9":{"name":"interestBalances","line":151,"loc":{"start":{"line":151,"column":4},"end":{"line":151,"column":89}}},"10":{"name":"totalBalance","line":156,"loc":{"start":{"line":156,"column":4},"end":{"line":156,"column":73}}}},"statementMap":{"1":{"start":{"line":29,"column":8},"end":{"line":29,"column":17}},"2":{"start":{"line":30,"column":8},"end":{"line":30,"column":19}},"3":{"start":{"line":31,"column":8},"end":{"line":31,"column":21}},"4":{"start":{"line":32,"column":8},"end":{"line":32,"column":78}},"5":{"start":{"line":33,"column":8},"end":{"line":33,"column":77}},"6":{"start":{"line":39,"column":8},"end":{"line":39,"column":52}},"7":{"start":{"line":40,"column":8},"end":{"line":40,"column":43}},"8":{"start":{"line":41,"column":8},"end":{"line":41,"column":72}},"9":{"start":{"line":42,"column":8},"end":{"line":42,"column":1424}},"10":{"start":{"line":47,"column":8},"end":{"line":47,"column":45}},"11":{"start":{"line":48,"column":8},"end":{"line":48,"column":21}},"12":{"start":{"line":52,"column":8},"end":{"line":52,"column":52}},"13":{"start":{"line":53,"column":8},"end":{"line":53,"column":43}},"14":{"start":{"line":54,"column":8},"end":{"line":54,"column":81}},"15":{"start":{"line":55,"column":8},"end":{"line":55,"column":48}},"16":{"start":{"line":56,"column":8},"end":{"line":56,"column":61}},"17":{"start":{"line":65,"column":8},"end":{"line":65,"column":32}},"18":{"start":{"line":66,"column":8},"end":{"line":66,"column":78}},"19":{"start":{"line":70,"column":8},"end":{"line":70,"column":54}},"20":{"start":{"line":71,"column":8},"end":{"line":71,"column":37}},"21":{"start":{"line":72,"column":8},"end":{"line":72,"column":41}},"22":{"start":{"line":73,"column":8},"end":{"line":73,"column":81}},"23":{"start":{"line":79,"column":8},"end":{"line":79,"column":48}},"24":{"start":{"line":80,"column":8},"end":{"line":80,"column":44}},"25":{"start":{"line":83,"column":8},"end":{"line":83,"column":70}},"26":{"start":{"line":85,"column":8},"end":{"line":85,"column":52}},"27":{"start":{"line":86,"column":8},"end":{"line":86,"column":43}},"28":{"start":{"line":87,"column":8},"end":{"line":87,"column":62}},"29":{"start":{"line":94,"column":8},"end":{"line":94,"column":32}},"30":{"start":{"line":95,"column":8},"end":{"line":95,"column":78}},"31":{"start":{"line":96,"column":8},"end":{"line":96,"column":82}},"32":{"start":{"line":99,"column":8},"end":{"line":99,"column":54}},"33":{"start":{"line":102,"column":8},"end":{"line":102,"column":47}},"34":{"start":{"line":105,"column":8},"end":{"line":105,"column":53}},"35":{"start":{"line":108,"column":8},"end":{"line":108,"column":34}},"36":{"start":{"line":109,"column":8},"end":{"line":109,"column":56}},"37":{"start":{"line":113,"column":8},"end":{"line":113,"column":32}},"38":{"start":{"line":114,"column":8},"end":{"line":114,"column":64}},"39":{"start":{"line":115,"column":8},"end":{"line":115,"column":82}},"40":{"start":{"line":118,"column":8},"end":{"line":118,"column":54}},"41":{"start":{"line":119,"column":8},"end":{"line":119,"column":70}},"42":{"start":{"line":122,"column":8},"end":{"line":122,"column":47}},"43":{"start":{"line":125,"column":8},"end":{"line":125,"column":49}},"44":{"start":{"line":126,"column":8},"end":{"line":126,"column":50}},"45":{"start":{"line":135,"column":8},"end":{"line":135,"column":52}},"46":{"start":{"line":136,"column":8},"end":{"line":136,"column":47}},"47":{"start":{"line":137,"column":8},"end":{"line":137,"column":27}},"48":{"start":{"line":146,"column":8},"end":{"line":146,"column":67}},"49":{"start":{"line":147,"column":8},"end":{"line":147,"column":54}},"50":{"start":{"line":148,"column":8},"end":{"line":148,"column":32}},"51":{"start":{"line":152,"column":8},"end":{"line":152,"column":67}},"52":{"start":{"line":153,"column":8},"end":{"line":153,"column":66}},"53":{"start":{"line":157,"column":8},"end":{"line":157,"column":45}},"54":{"start":{"line":158,"column":8},"end":{"line":158,"column":77}},"55":{"start":{"line":159,"column":8},"end":{"line":159,"column":95}}},"branchMap":{"1":{"line":42,"type":"if","locations":[{"start":{"line":42,"column":8},"end":{"line":42,"column":8}},{"start":{"line":42,"column":8},"end":{"line":42,"column":8}}]},"2":{"line":73,"type":"if","locations":[{"start":{"line":73,"column":8},"end":{"line":73,"column":8}},{"start":{"line":73,"column":8},"end":{"line":73,"column":8}}]},"3":{"line":96,"type":"if","locations":[{"start":{"line":96,"column":8},"end":{"line":96,"column":8}},{"start":{"line":96,"column":8},"end":{"line":96,"column":8}}]},"4":{"line":115,"type":"if","locations":[{"start":{"line":115,"column":8},"end":{"line":115,"column":8}},{"start":{"line":115,"column":8},"end":{"line":115,"column":8}}]},"5":{"line":136,"type":"if","locations":[{"start":{"line":136,"column":8},"end":{"line":136,"column":8}},{"start":{"line":136,"column":8},"end":{"line":136,"column":8}}]},"6":{"line":147,"type":"if","locations":[{"start":{"line":147,"column":8},"end":{"line":147,"column":8}},{"start":{"line":147,"column":8},"end":{"line":147,"column":8}}]}}},"contracts\\extensions\\PrimeOracle.sol":{"l":{"24":4,"25":4,"54":131,"55":131,"58":131,"61":131,"68":422,"87":173,"91":172,"92":172,"121":165,"123":165,"125":165,"129":165,"131":165,"139":165,"151":166,"152":165,"153":165,"154":165,"155":2577,"156":2577,"159":1},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimeOracle.sol","s":{"1":4,"2":4,"3":131,"4":131,"5":131,"6":131,"7":422,"8":173,"9":172,"10":172,"11":99,"12":73,"13":165,"14":165,"15":165,"16":165,"17":165,"18":165,"19":166,"20":165,"21":165,"22":165,"23":2577,"24":2577,"25":1,"26":1},"b":{"1":[172,1],"2":[99,73],"3":[165,1],"4":[1,0]},"f":{"1":4,"2":131,"3":422,"4":173,"5":165,"6":165,"7":166},"fnMap":{"1":{"name":"constructor","line":23,"loc":{"start":{"line":23,"column":4},"end":{"line":23,"column":52}}},"2":{"name":"calculatePremium","line":40,"loc":{"start":{"line":40,"column":4},"end":{"line":52,"column":5}}},"3":{"name":"marketPrice","line":67,"loc":{"start":{"line":67,"column":4},"end":{"line":67,"column":67}}},"4":{"name":"calculateIntrinsic","line":80,"loc":{"start":{"line":80,"column":4},"end":{"line":85,"column":5}}},"5":{"name":"calculateExtrinsic","line":107,"loc":{"start":{"line":107,"column":4},"end":{"line":119,"column":5}}},"6":{"name":"_extrinsic","line":134,"loc":{"start":{"line":134,"column":4},"end":{"line":138,"column":5}}},"7":{"name":"sqrt","line":150,"loc":{"start":{"line":150,"column":4},"end":{"line":150,"column":54}}}},"statementMap":{"1":{"start":{"line":24,"column":8},"end":{"line":24,"column":23}},"2":{"start":{"line":25,"column":8},"end":{"line":25,"column":19}},"3":{"start":{"line":54,"column":8},"end":{"line":54,"column":74}},"4":{"start":{"line":55,"column":8},"end":{"line":55,"column":94}},"5":{"start":{"line":58,"column":8},"end":{"line":58,"column":43}},"6":{"start":{"line":61,"column":8},"end":{"line":61,"column":62}},"7":{"start":{"line":68,"column":8},"end":{"line":68,"column":56}},"8":{"start":{"line":87,"column":8},"end":{"line":87,"column":73}},"9":{"start":{"line":91,"column":8},"end":{"line":91,"column":37}},"10":{"start":{"line":92,"column":8},"end":{"line":92,"column":3605}},"11":{"start":{"line":92,"column":29},"end":{"line":92,"column":84}},"12":{"start":{"line":93,"column":13},"end":{"line":93,"column":66}},"13":{"start":{"line":121,"column":8},"end":{"line":121,"column":37}},"14":{"start":{"line":123,"column":8},"end":{"line":123,"column":58}},"15":{"start":{"line":125,"column":8},"end":{"line":125,"column":5056}},"16":{"start":{"line":129,"column":8},"end":{"line":129,"column":58}},"17":{"start":{"line":131,"column":8},"end":{"line":131,"column":69}},"18":{"start":{"line":139,"column":8},"end":{"line":139,"column":5584}},"19":{"start":{"line":151,"column":8},"end":{"line":151,"column":5980}},"20":{"start":{"line":152,"column":12},"end":{"line":152,"column":32}},"21":{"start":{"line":153,"column":12},"end":{"line":153,"column":16}},"22":{"start":{"line":154,"column":12},"end":{"line":154,"column":6062}},"23":{"start":{"line":155,"column":16},"end":{"line":155,"column":20}},"24":{"start":{"line":156,"column":16},"end":{"line":156,"column":34}},"25":{"start":{"line":158,"column":15},"end":{"line":158,"column":6163}},"26":{"start":{"line":159,"column":12},"end":{"line":159,"column":16}}},"branchMap":{"1":{"line":87,"type":"if","locations":[{"start":{"line":87,"column":8},"end":{"line":87,"column":8}},{"start":{"line":87,"column":8},"end":{"line":87,"column":8}}]},"2":{"line":92,"type":"if","locations":[{"start":{"line":92,"column":8},"end":{"line":92,"column":8}},{"start":{"line":92,"column":8},"end":{"line":92,"column":8}}]},"3":{"line":151,"type":"if","locations":[{"start":{"line":151,"column":8},"end":{"line":151,"column":8}},{"start":{"line":151,"column":8},"end":{"line":151,"column":8}}]},"4":{"line":158,"type":"if","locations":[{"start":{"line":158,"column":15},"end":{"line":158,"column":15}},{"start":{"line":158,"column":15},"end":{"line":158,"column":15}}]}}},"contracts\\extensions\\PrimePool.sol":{"l":{"31":29,"32":29,"45":51,"48":51,"49":25,"51":26,"54":51,"55":47,"56":47,"63":33,"64":23,"67":23,"68":23,"70":23,"71":23,"75":44,"76":44,"77":44,"79":42,"82":42,"89":9,"91":9,"94":9,"97":9,"101":2,"103":2,"105":2,"109":20,"111":20,"114":20,"117":20,"121":24,"122":24,"123":24},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimePool.sol","s":{"1":29,"2":29,"3":2,"4":51,"5":51,"6":25,"7":26,"8":51,"9":47,"10":47,"11":33,"12":23,"13":23,"14":23,"15":23,"16":23,"17":44,"18":44,"19":44,"20":42,"21":42,"22":9,"23":9,"24":9,"25":9,"26":2,"27":2,"28":2,"29":20,"30":20,"31":20,"32":20,"33":24,"34":24,"35":24},"b":{"1":[25,26],"2":[47,4],"3":[23,10],"4":[23,0],"5":[42,2]},"f":{"1":29,"2":2,"3":51,"4":33,"5":44,"6":9,"7":2,"8":20,"9":24},"fnMap":{"1":{"name":"constructor","line":29,"loc":{"start":{"line":29,"column":41},"end":{"line":30,"column":5}}},"2":{"name":"kill","line":35,"loc":{"start":{"line":35,"column":44},"end":{"line":35,"column":18}}},"3":{"name":"_addLiquidity","line":40,"loc":{"start":{"line":40,"column":4},"end":{"line":43,"column":5}}},"4":{"name":"_removeLiquidity","line":59,"loc":{"start":{"line":59,"column":4},"end":{"line":62,"column":5}}},"5":{"name":"_write","line":74,"loc":{"start":{"line":74,"column":4},"end":{"line":74,"column":67}}},"6":{"name":"_exercise","line":85,"loc":{"start":{"line":85,"column":4},"end":{"line":88,"column":5}}},"7":{"name":"_redeem","line":100,"loc":{"start":{"line":100,"column":4},"end":{"line":100,"column":85}}},"8":{"name":"_close","line":108,"loc":{"start":{"line":108,"column":4},"end":{"line":108,"column":82}}},"9":{"name":"balances","line":120,"loc":{"start":{"line":120,"column":4},"end":{"line":120,"column":81}}}},"statementMap":{"1":{"start":{"line":31,"column":8},"end":{"line":31,"column":23}},"2":{"start":{"line":32,"column":8},"end":{"line":32,"column":25}},"3":{"start":{"line":35,"column":63},"end":{"line":35,"column":94}},"4":{"start":{"line":45,"column":8},"end":{"line":45,"column":41}},"5":{"start":{"line":48,"column":8},"end":{"line":48,"column":1570}},"6":{"start":{"line":49,"column":12},"end":{"line":49,"column":34}},"7":{"start":{"line":51,"column":12},"end":{"line":51,"column":69}},"8":{"start":{"line":54,"column":8},"end":{"line":54,"column":93}},"9":{"start":{"line":55,"column":8},"end":{"line":55,"column":30}},"10":{"start":{"line":56,"column":8},"end":{"line":56,"column":48}},"11":{"start":{"line":63,"column":8},"end":{"line":63,"column":79}},"12":{"start":{"line":64,"column":8},"end":{"line":64,"column":41}},"13":{"start":{"line":67,"column":8},"end":{"line":67,"column":65}},"14":{"start":{"line":68,"column":8},"end":{"line":68,"column":47}},"15":{"start":{"line":70,"column":8},"end":{"line":70,"column":29}},"16":{"start":{"line":71,"column":8},"end":{"line":71,"column":49}},"17":{"start":{"line":75,"column":8},"end":{"line":75,"column":32}},"18":{"start":{"line":76,"column":8},"end":{"line":76,"column":49}},"19":{"start":{"line":77,"column":8},"end":{"line":77,"column":90}},"20":{"start":{"line":79,"column":8},"end":{"line":79,"column":50}},"21":{"start":{"line":82,"column":8},"end":{"line":82,"column":58}},"22":{"start":{"line":89,"column":8},"end":{"line":89,"column":32}},"23":{"start":{"line":91,"column":8},"end":{"line":91,"column":68}},"24":{"start":{"line":94,"column":8},"end":{"line":94,"column":66}},"25":{"start":{"line":97,"column":8},"end":{"line":97,"column":81}},"26":{"start":{"line":101,"column":8},"end":{"line":101,"column":32}},"27":{"start":{"line":103,"column":8},"end":{"line":103,"column":68}},"28":{"start":{"line":105,"column":8},"end":{"line":105,"column":50}},"29":{"start":{"line":109,"column":8},"end":{"line":109,"column":32}},"30":{"start":{"line":111,"column":8},"end":{"line":111,"column":68}},"31":{"start":{"line":114,"column":8},"end":{"line":114,"column":66}},"32":{"start":{"line":117,"column":8},"end":{"line":117,"column":59}},"33":{"start":{"line":121,"column":8},"end":{"line":121,"column":71}},"34":{"start":{"line":122,"column":8},"end":{"line":122,"column":57}},"35":{"start":{"line":123,"column":8},"end":{"line":123,"column":57}}},"branchMap":{"1":{"line":48,"type":"if","locations":[{"start":{"line":48,"column":8},"end":{"line":48,"column":8}},{"start":{"line":48,"column":8},"end":{"line":48,"column":8}}]},"2":{"line":54,"type":"if","locations":[{"start":{"line":54,"column":8},"end":{"line":54,"column":8}},{"start":{"line":54,"column":8},"end":{"line":54,"column":8}}]},"3":{"line":63,"type":"if","locations":[{"start":{"line":63,"column":8},"end":{"line":63,"column":8}},{"start":{"line":63,"column":8},"end":{"line":63,"column":8}}]},"4":{"line":68,"type":"if","locations":[{"start":{"line":68,"column":8},"end":{"line":68,"column":8}},{"start":{"line":68,"column":8},"end":{"line":68,"column":8}}]},"5":{"line":77,"type":"if","locations":[{"start":{"line":77,"column":8},"end":{"line":77,"column":8}},{"start":{"line":77,"column":8},"end":{"line":77,"column":8}}]}}},"contracts\\extensions\\PrimeTrader.sol":{"l":{"40":40,"41":38,"42":32,"43":32,"59":25,"60":23,"61":21,"63":21,"64":19,"65":17,"66":17,"82":17,"83":15,"85":13,"86":11,"87":9,"104":15,"105":13,"106":11,"107":11,"108":9,"109":7,"110":7,"111":7,"126":11,"127":9,"128":5,"129":5,"130":3,"131":3,"132":3},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\extensions\\PrimeTrader.sol","s":{"1":25,"2":40,"3":38,"4":32,"5":32,"6":25,"7":23,"8":21,"9":21,"10":19,"11":17,"12":17,"13":17,"14":15,"15":13,"16":11,"17":9,"18":15,"19":13,"20":11,"21":11,"22":9,"23":7,"24":7,"25":7,"26":11,"27":9,"28":5,"29":5,"30":3,"31":3,"32":3},"b":{"1":[38,2],"2":[23,2],"3":[21,2],"4":[19,2],"5":[15,2],"6":[13,2],"7":[13,2],"8":[11,2],"9":[9,2],"10":[9,2],"11":[5,4],"12":[3,2]},"f":{"1":25,"2":40,"3":25,"4":17,"5":15,"6":11},"fnMap":{"1":{"name":"constructor","line":25,"loc":{"start":{"line":25,"column":4},"end":{"line":25,"column":44}}},"2":{"name":"safeMint","line":37,"loc":{"start":{"line":37,"column":19},"end":{"line":39,"column":5}}},"3":{"name":"safeExercise","line":56,"loc":{"start":{"line":56,"column":19},"end":{"line":58,"column":5}}},"4":{"name":"safeRedeem","line":79,"loc":{"start":{"line":79,"column":19},"end":{"line":81,"column":5}}},"5":{"name":"safeClose","line":101,"loc":{"start":{"line":101,"column":19},"end":{"line":103,"column":5}}},"6":{"name":"safeUnwind","line":123,"loc":{"start":{"line":123,"column":19},"end":{"line":125,"column":5}}}},"statementMap":{"1":{"start":{"line":25,"column":49},"end":{"line":25,"column":60}},"2":{"start":{"line":40,"column":8},"end":{"line":40,"column":38}},"3":{"start":{"line":41,"column":8},"end":{"line":41,"column":80}},"4":{"start":{"line":42,"column":8},"end":{"line":42,"column":52}},"5":{"start":{"line":43,"column":8},"end":{"line":43,"column":50}},"6":{"start":{"line":59,"column":8},"end":{"line":59,"column":38}},"7":{"start":{"line":60,"column":8},"end":{"line":60,"column":88}},"8":{"start":{"line":61,"column":8},"end":{"line":61,"column":85}},"9":{"start":{"line":63,"column":8},"end":{"line":63,"column":91}},"10":{"start":{"line":64,"column":8},"end":{"line":64,"column":82}},"11":{"start":{"line":65,"column":8},"end":{"line":65,"column":80}},"12":{"start":{"line":66,"column":8},"end":{"line":66,"column":77}},"13":{"start":{"line":82,"column":8},"end":{"line":82,"column":38}},"14":{"start":{"line":83,"column":8},"end":{"line":83,"column":89}},"15":{"start":{"line":85,"column":8},"end":{"line":85,"column":80}},"16":{"start":{"line":86,"column":8},"end":{"line":86,"column":43}},"17":{"start":{"line":87,"column":8},"end":{"line":87,"column":41}},"18":{"start":{"line":104,"column":8},"end":{"line":104,"column":38}},"19":{"start":{"line":105,"column":8},"end":{"line":105,"column":88}},"20":{"start":{"line":106,"column":8},"end":{"line":106,"column":63}},"21":{"start":{"line":107,"column":8},"end":{"line":107,"column":91}},"22":{"start":{"line":108,"column":8},"end":{"line":108,"column":82}},"23":{"start":{"line":109,"column":8},"end":{"line":109,"column":80}},"24":{"start":{"line":110,"column":8},"end":{"line":110,"column":63}},"25":{"start":{"line":111,"column":8},"end":{"line":111,"column":40}},"26":{"start":{"line":126,"column":8},"end":{"line":126,"column":38}},"27":{"start":{"line":127,"column":8},"end":{"line":127,"column":68}},"28":{"start":{"line":128,"column":8},"end":{"line":128,"column":63}},"29":{"start":{"line":129,"column":8},"end":{"line":129,"column":91}},"30":{"start":{"line":130,"column":8},"end":{"line":130,"column":82}},"31":{"start":{"line":131,"column":8},"end":{"line":131,"column":63}},"32":{"start":{"line":132,"column":8},"end":{"line":132,"column":40}}},"branchMap":{"1":{"line":40,"type":"if","locations":[{"start":{"line":40,"column":8},"end":{"line":40,"column":8}},{"start":{"line":40,"column":8},"end":{"line":40,"column":8}}]},"2":{"line":59,"type":"if","locations":[{"start":{"line":59,"column":8},"end":{"line":59,"column":8}},{"start":{"line":59,"column":8},"end":{"line":59,"column":8}}]},"3":{"line":60,"type":"if","locations":[{"start":{"line":60,"column":8},"end":{"line":60,"column":8}},{"start":{"line":60,"column":8},"end":{"line":60,"column":8}}]},"4":{"line":63,"type":"if","locations":[{"start":{"line":63,"column":8},"end":{"line":63,"column":8}},{"start":{"line":63,"column":8},"end":{"line":63,"column":8}}]},"5":{"line":82,"type":"if","locations":[{"start":{"line":82,"column":8},"end":{"line":82,"column":8}},{"start":{"line":82,"column":8},"end":{"line":82,"column":8}}]},"6":{"line":83,"type":"if","locations":[{"start":{"line":83,"column":8},"end":{"line":83,"column":8}},{"start":{"line":83,"column":8},"end":{"line":83,"column":8}}]},"7":{"line":104,"type":"if","locations":[{"start":{"line":104,"column":8},"end":{"line":104,"column":8}},{"start":{"line":104,"column":8},"end":{"line":104,"column":8}}]},"8":{"line":105,"type":"if","locations":[{"start":{"line":105,"column":8},"end":{"line":105,"column":8}},{"start":{"line":105,"column":8},"end":{"line":105,"column":8}}]},"9":{"line":107,"type":"if","locations":[{"start":{"line":107,"column":8},"end":{"line":107,"column":8}},{"start":{"line":107,"column":8},"end":{"line":107,"column":8}}]},"10":{"line":126,"type":"if","locations":[{"start":{"line":126,"column":8},"end":{"line":126,"column":8}},{"start":{"line":126,"column":8},"end":{"line":126,"column":8}}]},"11":{"line":127,"type":"if","locations":[{"start":{"line":127,"column":8},"end":{"line":127,"column":8}},{"start":{"line":127,"column":8},"end":{"line":127,"column":8}}]},"12":{"line":129,"type":"if","locations":[{"start":{"line":129,"column":8},"end":{"line":129,"column":8}},{"start":{"line":129,"column":8},"end":{"line":129,"column":8}}]}}},"contracts\\primitives\\PrimeOption.sol":{"l":{"44":47,"45":47,"55":164,"56":160,"60":34,"61":32,"65":4,"66":2,"75":3,"86":4,"87":4,"90":4,"93":4,"96":4,"105":197,"106":197,"107":197,"126":106,"127":106,"128":106,"131":106,"132":106,"133":106,"136":100,"137":100,"140":100,"141":100,"160":50,"161":50,"164":50,"165":48,"168":44,"169":42,"172":42,"173":42,"176":42,"177":42,"178":42,"183":38,"186":38,"189":38,"192":38,"195":38,"198":36,"201":36,"202":36,"216":28,"217":28,"218":28,"219":28,"222":28,"223":28,"224":26,"227":22,"228":22,"234":20,"235":20,"238":20,"239":20,"254":48,"255":48,"256":48,"257":48,"258":48,"261":48,"270":48,"274":48,"275":48,"276":42,"279":40,"280":36,"287":40,"288":40,"294":38,"295":38,"298":38,"299":38,"304":51,"305":51,"311":29,"312":29,"313":29,"331":1065,"332":1065,"333":1065,"334":1065,"335":1065,"336":1065,"337":1065},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\primitives\\PrimeOption.sol","s":{"1":47,"2":47,"3":164,"4":34,"5":32,"6":4,"7":2,"8":3,"9":4,"10":4,"11":4,"12":4,"13":4,"14":197,"15":197,"16":197,"17":106,"18":106,"19":106,"20":106,"21":106,"22":106,"23":100,"24":100,"25":100,"26":100,"27":50,"28":50,"29":50,"30":48,"31":44,"32":42,"33":3,"34":42,"35":42,"36":42,"37":42,"38":42,"39":38,"40":38,"41":38,"42":38,"43":38,"44":36,"45":36,"46":36,"47":28,"48":28,"49":28,"50":28,"51":28,"52":28,"53":26,"54":22,"55":22,"56":20,"57":20,"58":20,"59":20,"60":48,"61":48,"62":48,"63":48,"64":48,"65":48,"66":48,"67":48,"68":48,"69":42,"70":40,"71":36,"72":40,"73":40,"74":38,"75":38,"76":38,"77":38,"78":51,"79":51,"80":29,"81":29,"82":29,"83":72,"84":723,"85":105,"86":105,"87":81,"88":1065,"89":1065,"90":1065,"91":1065,"92":1065,"93":1065,"94":1065},"b":{"1":[160,4],"2":[32,2],"3":[2,2],"4":[100,6],"5":[48,2],"6":[44,4],"7":[3,39],"8":[38,4],"9":[36,2],"10":[26,2],"11":[22,4],"12":[20,2],"13":[42,6],"14":[40,2],"15":[36,4],"16":[38,2]},"f":{"1":47,"2":164,"3":34,"4":4,"5":3,"6":4,"7":197,"8":106,"9":50,"10":28,"11":48,"12":51,"13":29,"14":72,"15":723,"16":105,"17":105,"18":81,"19":1065},"fnMap":{"1":{"name":"constructor","line":42,"loc":{"start":{"line":42,"column":52},"end":{"line":43,"column":5}}},"2":{"name":"notExpired","line":54,"loc":{"start":{"line":54,"column":4},"end":{"line":54,"column":21}}},"3":{"name":"initTokenR","line":59,"loc":{"start":{"line":59,"column":4},"end":{"line":59,"column":56}}},"4":{"name":"kill","line":64,"loc":{"start":{"line":64,"column":4},"end":{"line":64,"column":26}}},"5":{"name":"update","line":74,"loc":{"start":{"line":74,"column":42},"end":{"line":74,"column":3}}},"6":{"name":"take","line":85,"loc":{"start":{"line":85,"column":40},"end":{"line":85,"column":3}}},"7":{"name":"_fund","line":104,"loc":{"start":{"line":104,"column":4},"end":{"line":104,"column":54}}},"8":{"name":"mint","line":122,"loc":{"start":{"line":122,"column":20},"end":{"line":124,"column":5}}},"9":{"name":"exercise","line":156,"loc":{"start":{"line":156,"column":20},"end":{"line":158,"column":5}}},"10":{"name":"redeem","line":213,"loc":{"start":{"line":213,"column":19},"end":{"line":215,"column":5}}},"11":{"name":"close","line":250,"loc":{"start":{"line":250,"column":19},"end":{"line":252,"column":5}}},"12":{"name":"getCaches","line":303,"loc":{"start":{"line":303,"column":4},"end":{"line":303,"column":80}}},"13":{"name":"getTokens","line":308,"loc":{"start":{"line":308,"column":4},"end":{"line":310,"column":7}}},"14":{"name":"tokenS","line":316,"loc":{"start":{"line":316,"column":4},"end":{"line":316,"column":58}}},"15":{"name":"tokenU","line":317,"loc":{"start":{"line":317,"column":4},"end":{"line":317,"column":58}}},"16":{"name":"base","line":318,"loc":{"start":{"line":318,"column":4},"end":{"line":318,"column":53}}},"17":{"name":"price","line":319,"loc":{"start":{"line":319,"column":4},"end":{"line":319,"column":54}}},"18":{"name":"expiry","line":320,"loc":{"start":{"line":320,"column":4},"end":{"line":320,"column":55}}},"19":{"name":"prime","line":322,"loc":{"start":{"line":322,"column":4},"end":{"line":330,"column":5}}}},"statementMap":{"1":{"start":{"line":44,"column":8},"end":{"line":44,"column":27}},"2":{"start":{"line":45,"column":8},"end":{"line":45,"column":1379}},"3":{"start":{"line":55,"column":8},"end":{"line":55,"column":63}},"4":{"start":{"line":60,"column":8},"end":{"line":60,"column":54}},"5":{"start":{"line":61,"column":8},"end":{"line":61,"column":23}},"6":{"start":{"line":65,"column":8},"end":{"line":65,"column":54}},"7":{"start":{"line":66,"column":8},"end":{"line":66,"column":39}},"8":{"start":{"line":75,"column":8},"end":{"line":75,"column":2121}},"9":{"start":{"line":86,"column":8},"end":{"line":86,"column":73}},"10":{"start":{"line":87,"column":8},"end":{"line":87,"column":2564}},"11":{"start":{"line":90,"column":8},"end":{"line":90,"column":2689}},"12":{"start":{"line":93,"column":8},"end":{"line":93,"column":2814}},"13":{"start":{"line":96,"column":8},"end":{"line":96,"column":2927}},"14":{"start":{"line":105,"column":8},"end":{"line":105,"column":24}},"15":{"start":{"line":106,"column":8},"end":{"line":106,"column":24}},"16":{"start":{"line":107,"column":8},"end":{"line":107,"column":37}},"17":{"start":{"line":126,"column":8},"end":{"line":126,"column":70}},"18":{"start":{"line":127,"column":8},"end":{"line":127,"column":31}},"19":{"start":{"line":128,"column":8},"end":{"line":128,"column":33}},"20":{"start":{"line":131,"column":8},"end":{"line":131,"column":38}},"21":{"start":{"line":132,"column":8},"end":{"line":132,"column":48}},"22":{"start":{"line":133,"column":8},"end":{"line":133,"column":41}},"23":{"start":{"line":136,"column":8},"end":{"line":136,"column":53}},"24":{"start":{"line":137,"column":8},"end":{"line":137,"column":32}},"25":{"start":{"line":140,"column":8},"end":{"line":140,"column":30}},"26":{"start":{"line":141,"column":8},"end":{"line":141,"column":48}},"27":{"start":{"line":160,"column":8},"end":{"line":160,"column":39}},"28":{"start":{"line":161,"column":8},"end":{"line":161,"column":50}},"29":{"start":{"line":164,"column":8},"end":{"line":164,"column":41}},"30":{"start":{"line":165,"column":8},"end":{"line":165,"column":91}},"31":{"start":{"line":168,"column":8},"end":{"line":168,"column":52}},"32":{"start":{"line":169,"column":8},"end":{"line":169,"column":92}},"33":{"start":{"line":169,"column":29},"end":{"line":169,"column":91}},"34":{"start":{"line":172,"column":8},"end":{"line":172,"column":70}},"35":{"start":{"line":173,"column":8},"end":{"line":173,"column":64}},"36":{"start":{"line":176,"column":8},"end":{"line":176,"column":39}},"37":{"start":{"line":177,"column":8},"end":{"line":177,"column":60}},"38":{"start":{"line":178,"column":8},"end":{"line":178,"column":56}},"39":{"start":{"line":183,"column":8},"end":{"line":183,"column":42}},"40":{"start":{"line":186,"column":8},"end":{"line":186,"column":75}},"41":{"start":{"line":189,"column":8},"end":{"line":189,"column":81}},"42":{"start":{"line":192,"column":8},"end":{"line":192,"column":42}},"43":{"start":{"line":195,"column":8},"end":{"line":195,"column":77}},"44":{"start":{"line":198,"column":8},"end":{"line":198,"column":37}},"45":{"start":{"line":201,"column":8},"end":{"line":201,"column":32}},"46":{"start":{"line":202,"column":8},"end":{"line":202,"column":52}},"47":{"start":{"line":216,"column":8},"end":{"line":216,"column":39}},"48":{"start":{"line":217,"column":8},"end":{"line":217,"column":32}},"49":{"start":{"line":218,"column":8},"end":{"line":218,"column":64}},"50":{"start":{"line":219,"column":8},"end":{"line":219,"column":64}},"51":{"start":{"line":222,"column":8},"end":{"line":222,"column":26}},"52":{"start":{"line":223,"column":8},"end":{"line":223,"column":40}},"53":{"start":{"line":224,"column":8},"end":{"line":224,"column":54}},"54":{"start":{"line":227,"column":8},"end":{"line":227,"column":58}},"55":{"start":{"line":228,"column":8},"end":{"line":228,"column":7968}},"56":{"start":{"line":234,"column":8},"end":{"line":234,"column":58}},"57":{"start":{"line":235,"column":8},"end":{"line":235,"column":58}},"58":{"start":{"line":238,"column":8},"end":{"line":238,"column":30}},"59":{"start":{"line":239,"column":8},"end":{"line":239,"column":39}},"60":{"start":{"line":254,"column":8},"end":{"line":254,"column":39}},"61":{"start":{"line":255,"column":8},"end":{"line":255,"column":32}},"62":{"start":{"line":256,"column":8},"end":{"line":256,"column":64}},"63":{"start":{"line":257,"column":8},"end":{"line":257,"column":64}},"64":{"start":{"line":258,"column":8},"end":{"line":258,"column":48}},"65":{"start":{"line":261,"column":8},"end":{"line":261,"column":26}},"66":{"start":{"line":270,"column":8},"end":{"line":270,"column":62}},"67":{"start":{"line":274,"column":8},"end":{"line":274,"column":72}},"68":{"start":{"line":275,"column":8},"end":{"line":275,"column":56}},"69":{"start":{"line":276,"column":8},"end":{"line":276,"column":84}},"70":{"start":{"line":279,"column":8},"end":{"line":279,"column":10254}},"71":{"start":{"line":280,"column":12},"end":{"line":280,"column":41}},"72":{"start":{"line":287,"column":8},"end":{"line":287,"column":58}},"73":{"start":{"line":288,"column":8},"end":{"line":288,"column":10663}},"74":{"start":{"line":294,"column":8},"end":{"line":294,"column":58}},"75":{"start":{"line":295,"column":8},"end":{"line":295,"column":58}},"76":{"start":{"line":298,"column":8},"end":{"line":298,"column":30}},"77":{"start":{"line":299,"column":8},"end":{"line":299,"column":39}},"78":{"start":{"line":304,"column":8},"end":{"line":304,"column":23}},"79":{"start":{"line":305,"column":8},"end":{"line":305,"column":23}},"80":{"start":{"line":311,"column":8},"end":{"line":311,"column":30}},"81":{"start":{"line":312,"column":8},"end":{"line":312,"column":30}},"82":{"start":{"line":313,"column":8},"end":{"line":313,"column":23}},"83":{"start":{"line":316,"column":63},"end":{"line":316,"column":83}},"84":{"start":{"line":317,"column":63},"end":{"line":317,"column":83}},"85":{"start":{"line":318,"column":58},"end":{"line":318,"column":76}},"86":{"start":{"line":319,"column":59},"end":{"line":319,"column":78}},"87":{"start":{"line":320,"column":60},"end":{"line":320,"column":80}},"88":{"start":{"line":331,"column":8},"end":{"line":331,"column":48}},"89":{"start":{"line":332,"column":8},"end":{"line":332,"column":30}},"90":{"start":{"line":333,"column":8},"end":{"line":333,"column":30}},"91":{"start":{"line":334,"column":8},"end":{"line":334,"column":23}},"92":{"start":{"line":335,"column":8},"end":{"line":335,"column":26}},"93":{"start":{"line":336,"column":8},"end":{"line":336,"column":28}},"94":{"start":{"line":337,"column":8},"end":{"line":337,"column":30}}},"branchMap":{"1":{"line":55,"type":"if","locations":[{"start":{"line":55,"column":8},"end":{"line":55,"column":8}},{"start":{"line":55,"column":8},"end":{"line":55,"column":8}}]},"2":{"line":60,"type":"if","locations":[{"start":{"line":60,"column":8},"end":{"line":60,"column":8}},{"start":{"line":60,"column":8},"end":{"line":60,"column":8}}]},"3":{"line":65,"type":"if","locations":[{"start":{"line":65,"column":8},"end":{"line":65,"column":8}},{"start":{"line":65,"column":8},"end":{"line":65,"column":8}}]},"4":{"line":133,"type":"if","locations":[{"start":{"line":133,"column":8},"end":{"line":133,"column":8}},{"start":{"line":133,"column":8},"end":{"line":133,"column":8}}]},"5":{"line":164,"type":"if","locations":[{"start":{"line":164,"column":8},"end":{"line":164,"column":8}},{"start":{"line":164,"column":8},"end":{"line":164,"column":8}}]},"6":{"line":165,"type":"if","locations":[{"start":{"line":165,"column":8},"end":{"line":165,"column":8}},{"start":{"line":165,"column":8},"end":{"line":165,"column":8}}]},"7":{"line":169,"type":"if","locations":[{"start":{"line":169,"column":8},"end":{"line":169,"column":8}},{"start":{"line":169,"column":8},"end":{"line":169,"column":8}}]},"8":{"line":178,"type":"if","locations":[{"start":{"line":178,"column":8},"end":{"line":178,"column":8}},{"start":{"line":178,"column":8},"end":{"line":178,"column":8}}]},"9":{"line":195,"type":"if","locations":[{"start":{"line":195,"column":8},"end":{"line":195,"column":8}},{"start":{"line":195,"column":8},"end":{"line":195,"column":8}}]},"10":{"line":223,"type":"if","locations":[{"start":{"line":223,"column":8},"end":{"line":223,"column":8}},{"start":{"line":223,"column":8},"end":{"line":223,"column":8}}]},"11":{"line":224,"type":"if","locations":[{"start":{"line":224,"column":8},"end":{"line":224,"column":8}},{"start":{"line":224,"column":8},"end":{"line":224,"column":8}}]},"12":{"line":228,"type":"if","locations":[{"start":{"line":228,"column":8},"end":{"line":228,"column":8}},{"start":{"line":228,"column":8},"end":{"line":228,"column":8}}]},"13":{"line":275,"type":"if","locations":[{"start":{"line":275,"column":8},"end":{"line":275,"column":8}},{"start":{"line":275,"column":8},"end":{"line":275,"column":8}}]},"14":{"line":276,"type":"if","locations":[{"start":{"line":276,"column":8},"end":{"line":276,"column":8}},{"start":{"line":276,"column":8},"end":{"line":276,"column":8}}]},"15":{"line":279,"type":"if","locations":[{"start":{"line":279,"column":8},"end":{"line":279,"column":8}},{"start":{"line":279,"column":8},"end":{"line":279,"column":8}}]},"16":{"line":288,"type":"if","locations":[{"start":{"line":288,"column":8},"end":{"line":288,"column":8}},{"start":{"line":288,"column":8},"end":{"line":288,"column":8}}]}}},"contracts\\primitives\\PrimeRedeem.sol":{"l":{"24":47,"25":47,"26":47,"30":102,"31":100,"35":64,"36":62},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\primitives\\PrimeRedeem.sol","s":{"1":47,"2":47,"3":47,"4":102,"5":100,"6":64,"7":62},"b":{"1":[100,2],"2":[62,2]},"f":{"1":47,"2":102,"3":64},"fnMap":{"1":{"name":"constructor","line":22,"loc":{"start":{"line":22,"column":49},"end":{"line":23,"column":5}}},"2":{"name":"mint","line":29,"loc":{"start":{"line":29,"column":4},"end":{"line":29,"column":58}}},"3":{"name":"burn","line":34,"loc":{"start":{"line":34,"column":4},"end":{"line":34,"column":58}}}},"statementMap":{"1":{"start":{"line":24,"column":8},"end":{"line":24,"column":25}},"2":{"start":{"line":25,"column":8},"end":{"line":25,"column":23}},"3":{"start":{"line":26,"column":8},"end":{"line":26,"column":31}},"4":{"start":{"line":30,"column":8},"end":{"line":30,"column":53}},"5":{"start":{"line":31,"column":8},"end":{"line":31,"column":24}},"6":{"start":{"line":35,"column":8},"end":{"line":35,"column":53}},"7":{"start":{"line":36,"column":8},"end":{"line":36,"column":24}}},"branchMap":{"1":{"line":30,"type":"if","locations":[{"start":{"line":30,"column":8},"end":{"line":30,"column":8}},{"start":{"line":30,"column":8},"end":{"line":30,"column":8}}]},"2":{"line":35,"type":"if","locations":[{"start":{"line":35,"column":8},"end":{"line":35,"column":8}},{"start":{"line":35,"column":8},"end":{"line":35,"column":8}}]}}},"contracts\\registry\\Factory.sol":{"l":{"20":32,"25":32},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\registry\\Factory.sol","s":{"1":5,"2":32,"3":2,"4":32},"b":{},"f":{"1":5,"2":32,"3":2,"4":32},"fnMap":{"1":{"name":"constructor","line":14,"loc":{"start":{"line":14,"column":4},"end":{"line":14,"column":38}}},"2":{"name":"deploy","line":18,"loc":{"start":{"line":18,"column":16},"end":{"line":20,"column":5}}},"3":{"name":"kill","line":22,"loc":{"start":{"line":22,"column":50},"end":{"line":22,"column":3}}},"4":{"name":"initialize","line":24,"loc":{"start":{"line":24,"column":72},"end":{"line":24,"column":3}}}},"statementMap":{"1":{"start":{"line":14,"column":43},"end":{"line":14,"column":69}},"2":{"start":{"line":20,"column":6},"end":{"line":20,"column":74}},"3":{"start":{"line":22,"column":54},"end":{"line":22,"column":78}},"4":{"start":{"line":25,"column":8},"end":{"line":25,"column":44}}},"branchMap":{}},"contracts\\registry\\FactoryRedeem.sol":{"l":{"17":32},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\registry\\FactoryRedeem.sol","s":{"1":5,"2":32},"b":{},"f":{"1":5,"2":32},"fnMap":{"1":{"name":"constructor","line":14,"loc":{"start":{"line":14,"column":4},"end":{"line":14,"column":38}}},"2":{"name":"deploy","line":16,"loc":{"start":{"line":16,"column":73},"end":{"line":16,"column":28}}}},"statementMap":{"1":{"start":{"line":14,"column":43},"end":{"line":14,"column":69}},"2":{"start":{"line":17,"column":8},"end":{"line":17,"column":69}}},"branchMap":{}},"contracts\\registry\\Registry.sol":{"l":{"34":5,"35":5,"52":34,"54":32,"58":32,"59":32,"60":32,"61":32,"63":32,"64":32,"68":2,"72":1,"76":33,"86":33,"96":1},"path":"C:\\Users\\alexa\\OneDrive\\Documents\\Master\\Blockchain\\primitive-contracts\\contracts\\registry\\Registry.sol","s":{"1":5,"2":5,"3":5,"4":34,"5":32,"6":32,"7":32,"8":32,"9":32,"10":32,"11":32,"12":2,"13":1,"14":33,"15":33,"16":1},"b":{"1":[32,2]},"f":{"1":5,"2":5,"3":34,"4":2,"5":1,"6":33,"7":33,"8":1},"fnMap":{"1":{"name":"constructor","line":31,"loc":{"start":{"line":31,"column":4},"end":{"line":31,"column":22}}},"2":{"name":"initialize","line":33,"loc":{"start":{"line":33,"column":92},"end":{"line":33,"column":3}}},"3":{"name":"deployOption","line":48,"loc":{"start":{"line":48,"column":20},"end":{"line":50,"column":5}}},"4":{"name":"kill","line":67,"loc":{"start":{"line":67,"column":59},"end":{"line":67,"column":3}}},"5":{"name":"setFeeReceiver","line":71,"loc":{"start":{"line":71,"column":76},"end":{"line":71,"column":3}}},"6":{"name":"optionsLength","line":75,"loc":{"start":{"line":75,"column":4},"end":{"line":75,"column":66}}},"7":{"name":"getId","line":79,"loc":{"start":{"line":79,"column":4},"end":{"line":85,"column":40}}},"8":{"name":"getOption","line":89,"loc":{"start":{"line":89,"column":4},"end":{"line":95,"column":44}}}},"statementMap":{"1":{"start":{"line":31,"column":27},"end":{"line":31,"column":55}},"2":{"start":{"line":34,"column":8},"end":{"line":34,"column":25}},"3":{"start":{"line":35,"column":8},"end":{"line":35,"column":37}},"4":{"start":{"line":52,"column":8},"end":{"line":52,"column":95}},"5":{"start":{"line":54,"column":8},"end":{"line":54,"column":63}},"6":{"start":{"line":58,"column":8},"end":{"line":58,"column":76}},"7":{"start":{"line":59,"column":8},"end":{"line":59,"column":26}},"8":{"start":{"line":60,"column":8},"end":{"line":60,"column":32}},"9":{"start":{"line":61,"column":8},"end":{"line":61,"column":76}},"10":{"start":{"line":63,"column":8},"end":{"line":63,"column":50}},"11":{"start":{"line":64,"column":8},"end":{"line":64,"column":42}},"12":{"start":{"line":68,"column":8},"end":{"line":68,"column":36}},"13":{"start":{"line":72,"column":8},"end":{"line":72,"column":33}},"14":{"start":{"line":76,"column":8},"end":{"line":76,"column":33}},"15":{"start":{"line":86,"column":8},"end":{"line":86,"column":76}},"16":{"start":{"line":96,"column":8},"end":{"line":96,"column":67}}},"branchMap":{"1":{"line":52,"type":"if","locations":[{"start":{"line":52,"column":8},"end":{"line":52,"column":8}},{"start":{"line":52,"column":8},"end":{"line":52,"column":8}}]}}}} \ No newline at end of file diff --git a/scripts/rinkeby.js b/scripts/rinkeby.js index 5508b297..6870e324 100644 --- a/scripts/rinkeby.js +++ b/scripts/rinkeby.js @@ -3,11 +3,22 @@ // When running the script with `buidler run