{"componentChunkName":"component---src-pages-sips-sip-markdown-remark-frontmatter-sip-tsx","path":"/sips/sip-65/","result":{"data":{"markdownRemark":{"fileAbsolutePath":"/vercel/path0/content/sips/sip-65.md","frontmatter":{"sip":65,"sccp":null,"title":"Decentralized Circuit Breaker","network":"Ethereum","author":"Justin J Moses (@justinjmoses)","type":"Governance","proposal":null,"implementor":null,"release":null,"created":"2020-06-17T00:00:00.000Z","updated":null,"status":"Implemented"},"html":"<!--You can leave these HTML comments in your merged SIP and delete the visible duplicate text guides, they will not appear and may be helpful to refer to if you edit it again. This is the suggested template for new SIPs. Note that an SIP number will be assigned by an editor. When opening a pull request to submit your SIP, please use an abbreviated title in the filename, `sip-draft_title_abbrev.md`. The title should be 44 characters or less.-->\n<h2 id=\"simple-summary\" style=\"position:relative;\"><a href=\"#simple-summary\" aria-label=\"simple summary permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Simple Summary</h2>\n<!--\"If you can't explain it simply, you don't understand it well enough.\" Simply describe the outcome the proposed changes intends to achieve. This should be non-technical and accessible to a casual community member.-->\n<p>Integrate a circuit breaker into each exchange, if the price of either Synth being exchanged has changed by more than a specific percentage the Synth will be suspended.</p>\n<h2 id=\"abstract\" style=\"position:relative;\"><a href=\"#abstract\" aria-label=\"abstract permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Abstract</h2>\n<!--A short (~200 word) description of the proposed change, the abstract should clearly describe the proposed change. This is what *will* be done if the SIP is implemented, not *why* it should be done or *how* it will be done. If the SIP proposes deploying a new contract, write, \"we propose to deploy a new contract that will do x\".-->\n<p>When any exchange is attempted, prior to executing the exchange the protocol will check to see the price difference on both the source and destination synths since the last exchange of either. If the price difference on either is over a certain threshold (SCCP modifible), then the synth will be suspended (via <a href=\"/8f8378e71e5dfb03590105fcf519de10/sip-44.md\">SIP-44</a>) and the exchange prevented. It will then be up to the protocolDAO to investigate the issue and to activate the synth once again after reviewing the incident.</p>\n<h2 id=\"motivation\" style=\"position:relative;\"><a href=\"#motivation\" aria-label=\"motivation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Motivation</h2>\n<!--This is the problem statement. This is the *why* of the SIP. It should clearly explain *why* the current state of the protocol is inadequate.  It is critical that you explain *why* the change is needed, if the SIP proposes changing how something is calculated, you must address *why* the current calculation is innaccurate or wrong. This is not the place to describe how the SIP will address the issue!-->\n<p>Both of the major outages of the Synthetix protocol have been the result of an incorrect price being reported via an oracle. The first was the <code>KRW</code> case from the Synthetix oracle in June 2019 and was exploited by a bot. The second was the mispricing of silver (<code>XAG</code>) to gold (<code>XAU</code>) from the Chainlink pricing network in February 2020. Even with robust data integrity checking, both instances reflect situations where multiple failures occurred simultaneously and prices were published that were incorrect and exploitable.</p>\n<p>Both of these should have immediately caused the synth to be suspended and unusable until the <code>protocolDAO</code> had time to investigate.</p>\n<p>Because the debt pool is shared among all <code>SNX</code> stakers, and because of Synthetix's <em>infinite liquidity</em> feature whereby 100% of any synth can be traded into the same USD value of any other synth, a mispriced synth could have catastropic consequences for the debt pool - inflating it to a point where the <code>SNX</code> collateral was not sufficient to back all outstanding debt.</p>\n<p>This change will ensure that at the moment of exploit (trying to exchange one synth to another), a check is performed. Note that <code>sUSD</code> is fixed to <code>1</code> so by tackling this problem at the <code>exchange</code> action we capture the vast majority of the exploits (more on this below).</p>\n<h2 id=\"specification\" style=\"position:relative;\"><a href=\"#specification\" aria-label=\"specification permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Specification</h2>\n<!--The specification should describe the syntax and semantics of any new feature, there are five sections\n1. Overview\n2. Rationale\n3. Technical Specification\n4. Test Cases\n5. Configurable Values\n-->\n<h3 id=\"overview\" style=\"position:relative;\"><a href=\"#overview\" aria-label=\"overview permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Overview</h3>\n<!--This is a high level overview of *how* the SIP will solve the problem. The overview should clearly describe how the new feature will be implemented.-->\n<p>The <code>Exchanger</code> contract will be amended to include a new <code>priceDeviationThresholdFactor</code> parameter (configurable by SCCP, see below).</p>\n<p>Every time an exchange occurs, we will check that both the source and destination synth prices have not changed by more than the threshold. We will then persist these rates as the <code>lastExchangeRate</code> for both synths. If there is not a <code>lastExchangeRate</code> for either synth, the contract will lookup the last three price changes on chain and compare each of them to the current one (which is more gas intensive but is a rare edge-case).</p>\n<p>The function to check and potentially suspend will also be publicly available, so that anyone may invoke it without needing to attempt an <code>exchange</code>.</p>\n<p>In addition, we need to handle the settlement of a trade (see <a href=\"/d79d8a4a9c16298633efde4eb4935f86/sip-37.md\">SIP-37</a> for more details on trade settlement). Because settlement is called to process some past event (i.e. how much is owed when the price of the oracle after the waiting period ends is taken into account) - we cannot nor would not want to do any suspension during settlement. However, we also cannot leave the trade in an unsettled state and block future user exchanges. As such, we propose to waive any reclaims or rebates in the event that the amount received deviates from the amount that should have been received by more than the <code>priceDeviationThresholdFactor</code>.</p>\n<blockquote>\n<p>There is a remote possibility that an exchange gets in before a spike, fronrunning a real rate change, but by the time the waiting period expires <code>N</code> minutes later, a spike occurs, and the exchange is settled with no fee reclaim. As such, the <code>protocolDAO</code>, when investigating suspended synths via price spikes, must also look through the unsettled exchanges performed right before the spike and determine the necessary course of action before resuming the synth in question. That being said, as long as the synth pricing is returned to normal after the outage, than the settlement occuring after that will not be cause for concern.</p>\n</blockquote>\n<p>Finally, as the suspension is limited to the synth, even in a case of a false positive - where a synth is suspended when it shouldn't be - the only concern is increased downtime for any user to exchange or transfer that synth. It will be on the protocolDAO to investigate and resume the synth after a thorough investigation.</p>\n<h3 id=\"rationale\" style=\"position:relative;\"><a href=\"#rationale\" aria-label=\"rationale permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Rationale</h3>\n<!--This is where you explain the reasoning behind how you propose to solve the problem. Why did you propose to implement the change in this way, what were the considerations and trade-offs. The rationale fleshes out what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.-->\n<p>A cleaner way to solve this problem would be to suspend the system on price updates, not on exchanges. However as Synthetix partially uses decentralized price feeds from Chainlink (and is planning to migrate to them fully in the near term with <a href=\"/3728de0dec1a8fabf7c3c38676a900e2/sip-36.md\">SIP-36</a>), it cannot hook into actions from contracts it reads due to the limitations of smart contract interactions.</p>\n<blockquote>\n<p>Note: a future version of this will instead incorporate upcoming changes in Chainlink Aggregators to read circuit breaker switches from them, instead of having to rely on previous prices from exchanges.</p>\n</blockquote>\n<p>In the meantime, checking at the moment of exchange is the optimal strategy. Unfortunately this means slightly more gas for the user, which in the current climate is a difficult decision, but necessary to prevent collapse of the system.</p>\n<p>In order to reduce gas as much as possible, this SIP proposes to store a <code>lastExchangeRate</code> mapping locally on <code>Exchanger</code> and use that as the source of truth, rather than looking back through <code>ExchangeRates</code> for some amount of predetermined time to determine if an invalid price occurred.</p>\n<h3 id=\"caveats\" style=\"position:relative;\"><a href=\"#caveats\" aria-label=\"caveats permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Caveats</h3>\n<ol>\n<li>\n<p>Imposing the suspension on a user's <code>exchange</code> will incur slightly more gas cost per successful exchange (~5%). This is unfortunate in the current Ethereum gas climate but necessary.</p>\n</li>\n<li>\n<p>If the suspension is hit, then the user who performs the action will pay the gas cost (which is much less than an exchange) and not have their exchange processed. However, this suspension action is expected to be a <em>very</em> rare edge case, and adding extra development work to repay them for their efforts is not worth it given the unlikeliness of this being needed. Additionally we are investigating the implementation of a keeper network to ensure that actions like this are incentivised and do not fall onto the user.</p>\n</li>\n<li>\n<p>If we only check <code>exchange</code> actions, this does not prevent <code>SNX</code> stakers from issuing or burning <code>sUSD</code> while an invalid price is on-chain. However, the primary risk is that a staker can pay off their debt using the exploit. That is, that the debt pool has reduced and they now need to burn far less <code>sUSD</code> to unlock their <code>SNX</code>. This exploit is only possible if one or more prices are returned much lower than is accurate (otherwise the debt pool would expand rather than contract), and that those synths consist of a large enough proportion of the debt pool. Additionally, since sUSD is always fixed to <code>1</code>, the proportion of the debt pool denominated in <code>sUSD</code> will never change regardless of the other synths. As such, this extreme edge case does not seem worthy of also performing the check on <code>issue</code>, <code>burn</code> and <code>claim</code> actions given the additional gas costs per action.</p>\n</li>\n<li>\n<p>Checking the last price from an exchange isn't a perfect solution, it may miss scenarios where the price fluctuates in and out of a reasonable band - but it's a acceptable compromise until such time as Chainlink have integrated circuit breakers onto all their Aggregators and we have migrated to Chainlink completely.</p>\n</li>\n</ol>\n<h3 id=\"technical-specification\" style=\"position:relative;\"><a href=\"#technical-specification\" aria-label=\"technical specification permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Technical Specification</h3>\n<!--The technical specification should outline the public API of the changes proposed. That is, changes to any of the interfaces Synthetix currently exposes or the creations of new ones.-->\n<p><code>IExchanger</code> additions:</p>\n<pre><code class=\"language-solidity\">\n// Views\nfunction isSynthRateInvalid(bytes32 currencyKey) external view returns (bool);\n\n// Mutative functions\nfunction suspendSynthWithInvalidRate(bytes32 currencyKey) external;\n  // requires isSynthPricingInvalid(currencyKey) is true\n</code></pre>\n<p>In order to save gas, each time a new <code>exchange</code> occurs, the price of both the <code>src</code> and <code>dest</code> synths will be stored locally in <code>Exchanger</code> (rather than looking back in <code>ExchangeRates</code> for some amount of time).</p>\n<p>Additionally, <code>Exchanger.exchange</code> will be amended to perform <code>suspendSynthWithInvalidRate(currencyKey)</code> for either (or both) source or destination synth when <code>isSynthRateInvalid(currencyKey)</code> is <code>true</code>.</p>\n<h3 id=\"workflow\" style=\"position:relative;\"><a href=\"#workflow\" aria-label=\"workflow permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Workflow</h3>\n<ul>\n<li>\n<p><code>Synthetix.exchange(onBehalf)?</code> invoked from synth <code>src</code> to <code>dest</code> by <code>user</code> for <code>amount</code></p>\n<ul>\n<li>For both <code>src</code> and <code>dest</code> synths:\n<ul>\n<li><em>Is there a previous rate for the synth?</em>\n<ul>\n<li>Yes:\n<ul>\n<li><em>Is the factor difference in rate now compared to the previous rate >= <code>priceDeviationThresholdFactor</code>?</em>\n<ul>\n<li>Yes: ✅🔚 Settle any unsettled trades into <code>src</code> as per usual (if <code>src</code> was the breach, then settle with no reclaim or rebate - see below), then suspend the synth and return immediately.</li>\n<li>No: Persist the current rate as the last</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>No:\n<ul>\n<li>For each of the last <code>3</code> rounds,\n<ul>\n<li><em>Is the factor difference in rate now compared to the rate at current round >= <code>priceDeviationThresholdFactor</code>?</em>\n<ul>\n<li>Yes: ✅🔚 Suspend the synth and return immediately.</li>\n<li>No: Persist the current rate as the last</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Then\n<ul>\n<li>✅ Continue with exchange</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>\n<p><code>Synthetix.settle</code> invoked on <code>dest</code> for <code>user</code></p>\n<ul>\n<li>For each unsettled exchange from some <code>synth</code> to <code>dest</code>:\n<ul>\n<li><em>Is the factor difference in <code>amountReceived</code> compared <code>amountShouldHaveReceived</code> >= <code>priceDeviationThresholdFactor</code>?</em>\n<ul>\n<li>Yes: Settle the exchange with <code>0</code> reclaim and <code>0</code> rebate</li>\n<li>No: Settle the exchange as per usual</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"test-cases\" style=\"position:relative;\"><a href=\"#test-cases\" aria-label=\"test cases permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Test Cases</h3>\n<!--Test cases for an implementation are mandatory for SIPs but can be included with the implementation..-->\n<h4 id=\"preconditions\" style=\"position:relative;\"><a href=\"#preconditions\" aria-label=\"preconditions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Preconditions</h4>\n<ul>\n<li>Given the <code>priceDeviationThresholdFactor</code> is set to <code>1.5</code> (stored on-chain as <code>1.5e18</code>)</li>\n<li>And the <code>waitingPeriodSecs</code> is set to <code>180</code> (3 minutes)</li>\n</ul>\n<h4 id=\"common-cases\" style=\"position:relative;\"><a href=\"#common-cases\" aria-label=\"common cases permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Common cases</h4>\n<ul>\n<li>Given there was previously an exchange for <code>sUSD</code> (or any synth) to <code>sETH</code>, recording the last sETH price as <code>200</code>\n<ul>\n<li>And the current market price of <code>sETH</code> is returning <code>500</code>\n<ul>\n<li>When a user attempts to exchange <code>sBTC</code> (or any other synth) into <code>sETH</code> (or from any synth into <code>sETH</code>)\n<ul>\n<li>Then as <code>500</code> is more than <code>1.5x</code> away from <code>200</code> (i.e. it's more than <code>300</code>), <code>sETH</code> will be suspended, and the exchange will be prevented.</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>And the current market price of <code>sETH</code> is returning <code>105</code>\n<ul>\n<li>When a user attempts to exchange <code>sBTC</code> (or any other synth) into <code>sETH</code>\n<ul>\n<li>Then as <code>105</code> is less than <code>0.67x</code> away from <code>200</code> (i.e. it's above <code>100</code>), then the exchange will continue, and <code>105</code> will be persisted as the last price.\n<ul>\n<li>When one minute elapses</li>\n<li>And a new price for <code>sETH</code> is returned at <code>5</code></li>\n<li>And five minutes elapses (thus ending their waiting period)</li>\n<li>And a new price for <code>sETH</code> is returned at <code>100</code></li>\n<li>And the <code>user</code> attempts to <code>exchange</code> <code>sETH</code> into any other synth\n<ul>\n<li>Then as the price of <code>5</code> (the price at three minutes after their exchange) is more than <code>0.67x</code> away from <code>105</code> (i.e. below <code>52.5</code>), then the settlement will process with no reclaim or rebate.</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h4 id=\"edge-cases\" style=\"position:relative;\"><a href=\"#edge-cases\" aria-label=\"edge cases permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Edge cases</h4>\n<ul>\n<li>Given there is no previous exchange recorded for <code>sETH</code>\n<ul>\n<li>And the protocol upgrades <code>Exchanger</code> contract\n<ul>\n<li>And there are 10 previous rates for <code>sETH</code> price, all within 1% of each other\n<ul>\n<li>When a user attempts to exchange <code>sETH</code> for <code>sUSD</code>,\n<ul>\n<li>Then the current rate will be within 1% of the previous three rates, and the exchange will continue, persisting the current rate</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>And the protocol upgrades <code>ExchangeRates</code> contract or a Chainlink <code>Aggregator</code> is replaced for a price\n<ul>\n<li>And there is no previous rates for <code>sETH</code>\n<ul>\n<li>Then the exchange will continue, persisting the current rate</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</li>\n<li>Given ExchangeRates returns 0 for the <code>sETH</code> rate\n<ul>\n<li>When a user attempts to exchange <code>sUSD</code> for <code>sETH</code>\n<ul>\n<li>Then it fails with divide by 0 error from ExchangeRates.effectiveValue (as is current)</li>\n</ul>\n</li>\n<li>When a user attempts to exchange <code>sETH</code> for <code>sUSD</code>\n<ul>\n<li>Then it suspends the <code>sETH</code> synth as the <code>0</code> rate trips the circuit breaker</li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h3 id=\"configurable-values-via-sccp\" style=\"position:relative;\"><a href=\"#configurable-values-via-sccp\" aria-label=\"configurable values via sccp permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Configurable Values (Via SCCP)</h3>\n<!--Please list all values configurable via SCCP under this implementation.-->\n<ul>\n<li><code>priceDeviationThresholdFactor</code> the factor from which that price must deviate (from it's last exchange) to trigger the suspension (stored with 18 decimals). For example, a factor <code>3</code> (stored as <code>3e18</code>) would mean that with an last exchange rate of <code>100</code> and a new rate of <code>300</code> or greater, or a new rate of <code>33.3</code> (recurring) and lower, would cause suspension.</li>\n</ul>\n<h2 id=\"copyright\" style=\"position:relative;\"><a href=\"#copyright\" aria-label=\"copyright permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Copyright</h2>\n<p>Copyright and related rights waived via <a href=\"https://creativecommons.org/publicdomain/zero/1.0/\">CC0</a>.</p>"}},"pageContext":{"id":"67ae40a7-852f-58c6-abe2-94d39a310dc5","frontmatter__sip":65,"__params":{"frontmatter__sip":"65"}}},"staticQueryHashes":[]}