Page Not Found
We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/404.html b/404.html new file mode 100644 index 000000000..b09a3dc7d --- /dev/null +++ b/404.html @@ -0,0 +1,24 @@ + + +
+ + +We could not find what you were looking for.
Please contact the owner of the site that linked you to the original URL and let them know their link is broken.
-t, --tools <className[:key=value...]>
",id:"-t---tools-classnamekeyvalue",level:3},{value:"--output-path <PATH>
",id:"--output-path-path",level:3},{value:"--list-tools
",id:"--list-tools",level:3},{value:"-o, --output-format <json|plain>
",id:"-o---output-format-jsonplain",level:3},{value:"-C, --no-colors
",id:"-c---no-colors",level:3},{value:"--souffle-binary <PATH>
",id:"--souffle-binary-path",level:3},{value:"--souffle-path <PATH>
",id:"--souffle-path-path",level:3},{value:"--souffle-verbose
",id:"--souffle-verbose",level:3},{value:"--tact-stdlib-path <PATH>
",id:"--tact-stdlib-path-path",level:3},{value:"-v, --verbose
",id:"-v---verbose",level:3},{value:"-q, --quiet
",id:"-q---quiet",level:3},{value:"-m, --min-severity <info|low|medium|high|critical>
",id:"-m---min-severity-infolowmediumhighcritical",level:3},{value:"-de, --enabled-detectors <name|path:name>
",id:"-de---enabled-detectors-namepathname",level:3},{value:"-dd, --disabled-detectors <names>
",id:"-dd---disabled-detectors-names",level:3},{value:"-A, --all-detectors
",id:"-a---all-detectors",level:3},{value:"-c, --config <PATH>
",id:"-c---config-path",level:3},{value:"--new-detector <PATH>
",id:"--new-detector-path",level:3}];function a(e){const n={code:"code",h1:"h1",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"command-line-interface",children:"Command-Line Interface"}),"\n",(0,s.jsx)(n.p,{children:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each."}),"\n",(0,s.jsx)(n.h3,{id:"-t---tools-classnamekeyvalue",children:(0,s.jsx)(n.code,{children:"-t, --tools -t, --tools <className[:key=value...]>
",id:"-t---tools-classnamekeyvalue",level:3},{value:"--output-path <PATH>
",id:"--output-path-path",level:3},{value:"--list-tools
",id:"--list-tools",level:3},{value:"-o, --output-format <json|plain>
",id:"-o---output-format-jsonplain",level:3},{value:"-C, --no-colors
",id:"-c---no-colors",level:3},{value:"--souffle-binary <PATH>
",id:"--souffle-binary-path",level:3},{value:"--souffle-path <PATH>
",id:"--souffle-path-path",level:3},{value:"--souffle-verbose
",id:"--souffle-verbose",level:3},{value:"--tact-stdlib-path <PATH>
",id:"--tact-stdlib-path-path",level:3},{value:"-v, --verbose
",id:"-v---verbose",level:3},{value:"-q, --quiet
",id:"-q---quiet",level:3},{value:"-m, --min-severity <info|low|medium|high|critical>
",id:"-m---min-severity-infolowmediumhighcritical",level:3},{value:"-de, --enabled-detectors <name|path:name>
",id:"-de---enabled-detectors-namepathname",level:3},{value:"-dd, --disabled-detectors <names>
",id:"-dd---disabled-detectors-names",level:3},{value:"-A, --all-detectors
",id:"-a---all-detectors",level:3},{value:"-c, --config <PATH>
",id:"-c---config-path",level:3},{value:"--new-detector <PATH>
",id:"--new-detector-path",level:3},{value:"Exit Codes",id:"exit-codes",level:2}];function a(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"command-line-interface",children:"Command-Line Interface"}),"\n",(0,s.jsx)(n.h2,{id:"cli-options",children:"CLI Options"}),"\n",(0,s.jsx)(n.p,{children:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each."}),"\n",(0,s.jsx)(n.h3,{id:"-t---tools-classnamekeyvalue",children:(0,s.jsx)(n.code,{children:"-t, --tools ["'])(?.*?)\1/,p=/\{(? [\d,-]+)\}/,x={js:{start:"\\/\\/",end:""},jsBlock:{start:"\\/\\*",end:"\\*\\/"},jsx:{start:"\\{\\s*\\/\\*",end:"\\*\\/\\s*\\}"},bash:{start:"#",end:""},html:{start:"\x3c!--",end:"--\x3e"}},g={...x,lua:{start:"--",end:""},wasm:{start:"\\;\\;",end:""},tex:{start:"%",end:""},vb:{start:"['\u2018\u2019]",end:""},vbnet:{start:"(?:_\\s*)?['\u2018\u2019]",end:""},rem:{start:"[Rr][Ee][Mm]\\b",end:""},f90:{start:"!",end:""},ml:{start:"\\(\\*",end:"\\*\\)"},cobol:{start:"\\*>",end:""}},b=Object.keys(x);function v(e,t){const n=e.map((e=>{const{start:n,end:s}=g[e];return`(?:${n}\\s*(${t.flatMap((e=>[e.line,e.block?.start,e.block?.end].filter(Boolean))).join("|")})\\s*${s})`})).join("|");return new RegExp(`^\\s*(?:${n})\\s*$`)}function j(e,t){let n=e.replace(/\n$/,"");const{language:s,magicComments:o,metastring:a}=t;if(a&&p.test(a)){const e=a.match(p).groups.range;if(0===o.length)throw new Error(`A highlight range has been given in code block's metastring (\`\`\` ${a}), but no magic comment config is available. Docusaurus applies the first magic comment entry's className for metastring ranges.`);const t=o[0].className,s=h()(e).filter((e=>e>0)).map((e=>[e-1,[t]]));return{lineClassNames:Object.fromEntries(s),code:n}}if(void 0===s)return{lineClassNames:{},code:n};const c=function(e,t){switch(e){case"js":case"javascript":case"ts":case"typescript":return v(["js","jsBlock"],t);case"jsx":case"tsx":return v(["js","jsBlock","jsx"],t);case"html":return v(["js","jsBlock","html"],t);case"python":case"py":case"bash":return v(["bash"],t);case"markdown":case"md":return v(["html","jsx","bash"],t);case"tex":case"latex":case"matlab":return v(["tex"],t);case"lua":case"haskell":case"sql":return v(["lua"],t);case"wasm":return v(["wasm"],t);case"vb":case"vba":case"visual-basic":return v(["vb","rem"],t);case"vbnet":return v(["vbnet","rem"],t);case"batch":return v(["rem"],t);case"basic":return v(["rem","f90"],t);case"fsharp":return v(["js","ml"],t);case"ocaml":case"sml":return v(["ml"],t);case"fortran":return v(["f90"],t);case"cobol":return v(["cobol"],t);default:return v(b,t)}}(s,o),i=n.split("\n"),r=Object.fromEntries(o.map((e=>[e.className,{start:0,range:""}]))),l=Object.fromEntries(o.filter((e=>e.line)).map((e=>{let{className:t,line:n}=e;return[n,t]}))),d=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.start,t]}))),u=Object.fromEntries(o.filter((e=>e.block)).map((e=>{let{className:t,block:n}=e;return[n.end,t]})));for(let h=0;h void 0!==e));l[t]?r[l[t]].range+=`${h},`:d[t]?r[d[t]].start=h:u[t]&&(r[u[t]].range+=`${r[u[t]].start}-${h-1},`),i.splice(h,1)}n=i.join("\n");const m={};return Object.entries(r).forEach((e=>{let[t,{range:n}]=e;h()(n).forEach((e=>{m[e]??=[],m[e].push(t)}))})),{lineClassNames:m,code:n}}const N={codeBlockContainer:"codeBlockContainer_Ckt0"};var y=n(4848);function A(e){let{as:t,...n}=e;const s=function(e){const t={color:"--prism-color",backgroundColor:"--prism-background-color"},n={};return Object.entries(e.plain).forEach((e=>{let[s,o]=e;const a=t[s];a&&"string"==typeof o&&(n[a]=o)})),n}(d());return(0,y.jsx)(t,{...n,style:s,className:(0,i.A)(n.className,N.codeBlockContainer,u.G.common.codeBlock)})}const C={codeBlockContent:"codeBlockContent_biex",codeBlockTitle:"codeBlockTitle_Ktv7",codeBlock:"codeBlock_bY9V",codeBlockStandalone:"codeBlockStandalone_MEMb",codeBlockLines:"codeBlockLines_e6Vv",codeBlockLinesWithNumbering:"codeBlockLinesWithNumbering_o6Pm",buttonGroup:"buttonGroup__atx"};function k(e){let{children:t,className:n}=e;return(0,y.jsx)(A,{as:"pre",tabIndex:0,className:(0,i.A)(C.codeBlockStandalone,"thin-scrollbar",n),children:(0,y.jsx)("code",{className:C.codeBlockLines,children:t})})}var B=n(9532);const w={attributes:!0,characterData:!0,childList:!0,subtree:!0};function L(e,t){const[n,o]=(0,s.useState)(),a=(0,s.useCallback)((()=>{o(e.current?.closest("[role=tabpanel][hidden]"))}),[e,o]);(0,s.useEffect)((()=>{a()}),[a]),function(e,t,n){void 0===n&&(n=w);const o=(0,B._q)(t),a=(0,B.Be)(n);(0,s.useEffect)((()=>{const t=new MutationObserver(o);return e&&t.observe(e,a),()=>t.disconnect()}),[e,o,a])}(n,(e=>{e.forEach((e=>{"attributes"===e.type&&"hidden"===e.attributeName&&(t(),a())}))}),{attributes:!0,characterData:!1,childList:!1,subtree:!1})}var E=n(1765);const T={codeLine:"codeLine_lJS_",codeLineNumber:"codeLineNumber_Tfdd",codeLineContent:"codeLineContent_feaV"};function _(e){let{line:t,classNames:n,showLineNumbers:s,getLineProps:o,getTokenProps:a}=e;1===t.length&&"\n"===t[0].content&&(t[0].content="");const c=o({line:t,className:(0,i.A)(n,s&&T.codeLine)}),r=t.map(((e,t)=>(0,y.jsx)("span",{...a({token:e})},t)));return(0,y.jsxs)("span",{...c,children:[s?(0,y.jsxs)(y.Fragment,{children:[(0,y.jsx)("span",{className:T.codeLineNumber}),(0,y.jsx)("span",{className:T.codeLineContent,children:r})]}):r,(0,y.jsx)("br",{})]})}var H=n(1312);function S(e){return(0,y.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,y.jsx)("path",{fill:"currentColor",d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})})}function I(e){return(0,y.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,y.jsx)("path",{fill:"currentColor",d:"M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"})})}const M={copyButtonCopied:"copyButtonCopied_obH4",copyButtonIcons:"copyButtonIcons_eSgA",copyButtonIcon:"copyButtonIcon_y97N",copyButtonSuccessIcon:"copyButtonSuccessIcon_LjdS"};function U(e){let{code:t,className:n}=e;const[o,a]=(0,s.useState)(!1),c=(0,s.useRef)(void 0),r=(0,s.useCallback)((()=>{!function(e,t){let{target:n=document.body}=void 0===t?{}:t;if("string"!=typeof e)throw new TypeError(`Expected parameter \`text\` to be a \`string\`, got \`${typeof e}\`.`);const s=document.createElement("textarea"),o=document.activeElement;s.value=e,s.setAttribute("readonly",""),s.style.contain="strict",s.style.position="absolute",s.style.left="-9999px",s.style.fontSize="12pt";const a=document.getSelection(),c=a.rangeCount>0&&a.getRangeAt(0);n.append(s),s.select(),s.selectionStart=0,s.selectionEnd=e.length;let i=!1;try{i=document.execCommand("copy")}catch{}s.remove(),c&&(a.removeAllRanges(),a.addRange(c)),o&&o.focus()}(t),a(!0),c.current=window.setTimeout((()=>{a(!1)}),1e3)}),[t]);return(0,s.useEffect)((()=>()=>window.clearTimeout(c.current)),[]),(0,y.jsx)("button",{type:"button","aria-label":o?(0,H.T)({id:"theme.CodeBlock.copied",message:"Copied",description:"The copied button label on code blocks"}):(0,H.T)({id:"theme.CodeBlock.copyButtonAriaLabel",message:"Copy code to clipboard",description:"The ARIA label for copy code blocks button"}),title:(0,H.T)({id:"theme.CodeBlock.copy",message:"Copy",description:"The copy button label on code blocks"}),className:(0,i.A)("clean-btn",n,M.copyButton,o&&M.copyButtonCopied),onClick:r,children:(0,y.jsxs)("span",{className:M.copyButtonIcons,"aria-hidden":"true",children:[(0,y.jsx)(S,{className:M.copyButtonIcon}),(0,y.jsx)(I,{className:M.copyButtonSuccessIcon})]})})}function z(e){return(0,y.jsx)("svg",{viewBox:"0 0 24 24",...e,children:(0,y.jsx)("path",{fill:"currentColor",d:"M4 19h6v-2H4v2zM20 5H4v2h16V5zm-3 6H4v2h13.25c1.1 0 2 .9 2 2s-.9 2-2 2H15v-2l-3 3l3 3v-2h2c2.21 0 4-1.79 4-4s-1.79-4-4-4z"})})}const R={wordWrapButtonIcon:"wordWrapButtonIcon_Bwma",wordWrapButtonEnabled:"wordWrapButtonEnabled_EoeP"};function O(e){let{className:t,onClick:n,isEnabled:s}=e;const o=(0,H.T)({id:"theme.CodeBlock.wordWrapToggle",message:"Toggle word wrap",description:"The title attribute for toggle word wrapping button of code block lines"});return(0,y.jsx)("button",{type:"button",onClick:n,className:(0,i.A)("clean-btn",t,s&&R.wordWrapButtonEnabled),"aria-label":o,title:o,children:(0,y.jsx)(z,{className:R.wordWrapButtonIcon,"aria-hidden":"true"})})}function $(e){let{children:t,className:n="",metastring:o,title:a,showLineNumbers:c,language:r}=e;const{prism:{defaultLanguage:u,magicComments:m}}=(0,l.p)(),h=function(e){return e?.toLowerCase()}(r??function(e){const t=e.split(" ").find((e=>e.startsWith("language-")));return t?.replace(/language-/,"")}(n)??u),p=d(),x=function(){const[e,t]=(0,s.useState)(!1),[n,o]=(0,s.useState)(!1),a=(0,s.useRef)(null),c=(0,s.useCallback)((()=>{const n=a.current.querySelector("code");e?n.removeAttribute("style"):(n.style.whiteSpace="pre-wrap",n.style.overflowWrap="anywhere"),t((e=>!e))}),[a,e]),i=(0,s.useCallback)((()=>{const{scrollWidth:e,clientWidth:t}=a.current,n=e>t||a.current.querySelector("code").hasAttribute("style");o(n)}),[a]);return L(a,i),(0,s.useEffect)((()=>{i()}),[e,i]),(0,s.useEffect)((()=>(window.addEventListener("resize",i,{passive:!0}),()=>{window.removeEventListener("resize",i)})),[i]),{codeBlockRef:a,isEnabled:e,isCodeScrollable:n,toggle:c}}(),g=function(e){return e?.match(f)?.groups.title??""}(o)||a,{lineClassNames:b,code:v}=j(t,{metastring:o,language:h,magicComments:m}),N=c??function(e){return Boolean(e?.includes("showLineNumbers"))}(o);return(0,y.jsxs)(A,{as:"div",className:(0,i.A)(n,h&&!n.includes(`language-${h}`)&&`language-${h}`),children:[g&&(0,y.jsx)("div",{className:C.codeBlockTitle,children:g}),(0,y.jsxs)("div",{className:C.codeBlockContent,children:[(0,y.jsx)(E.f4,{theme:p,code:v,language:h??"text",children:e=>{let{className:t,style:n,tokens:s,getLineProps:o,getTokenProps:a}=e;return(0,y.jsx)("pre",{tabIndex:0,ref:x.codeBlockRef,className:(0,i.A)(t,C.codeBlock,"thin-scrollbar"),style:n,children:(0,y.jsx)("code",{className:(0,i.A)(C.codeBlockLines,N&&C.codeBlockLinesWithNumbering),children:s.map(((e,t)=>(0,y.jsx)(_,{line:e,getLineProps:o,getTokenProps:a,classNames:b[t],showLineNumbers:N},t)))})})}}),(0,y.jsxs)("div",{className:C.buttonGroup,children:[(x.isEnabled||x.isCodeScrollable)&&(0,y.jsx)(O,{className:C.codeButton,onClick:()=>x.toggle(),isEnabled:x.isEnabled}),(0,y.jsx)(U,{className:C.codeButton,code:v})]})]})]})}function V(e){let{children:t,...n}=e;const o=(0,c.A)(),a=function(e){return s.Children.toArray(e).some((e=>(0,s.isValidElement)(e)))?e:Array.isArray(e)?e.join(""):e}(t),i="string"==typeof a?$:k;return(0,y.jsx)(i,{...n,children:a},String(o))}function P(e){return(0,y.jsx)("code",{...e})}var W=n(8774);var D=n(3427),q=n(1422);const G={details:"details_lb9f",isBrowser:"isBrowser_bmU9",collapsibleContent:"collapsibleContent_i85q"};function F(e){return!!e&&("SUMMARY"===e.tagName||F(e.parentElement))}function Z(e,t){return!!e&&(e===t||Z(e.parentElement,t))}function J(e){let{summary:t,children:n,...o}=e;(0,D.A)().collectAnchor(o.id);const a=(0,c.A)(),r=(0,s.useRef)(null),{collapsed:l,setCollapsed:d}=(0,q.u)({initialState:!o.open}),[u,m]=(0,s.useState)(o.open),h=s.isValidElement(t)?t:(0,y.jsx)("summary",{children:t??"Details"});return(0,y.jsxs)("details",{...o,ref:r,open:u,"data-collapsed":l,className:(0,i.A)(G.details,a&&G.isBrowser,o.className),onMouseDown:e=>{F(e.target)&&e.detail>1&&e.preventDefault()},onClick:e=>{e.stopPropagation();const t=e.target;F(t)&&Z(t,r.current)&&(e.preventDefault(),l?(d(!1),m(!0)):d(!0))},children:[h,(0,y.jsx)(q.N,{lazy:!1,collapsed:l,disableSSRStyle:!0,onCollapseTransitionEnd:e=>{d(e),m(!e)},children:(0,y.jsx)("div",{className:G.collapsibleContent,children:n})})]})}const Y={details:"details_b_Ee"},K="alert alert--info";function Q(e){let{...t}=e;return(0,y.jsx)(J,{...t,className:(0,i.A)(K,Y.details,t.className)})}function X(e){const t=s.Children.toArray(e.children),n=t.find((e=>s.isValidElement(e)&&"summary"===e.type)),o=(0,y.jsx)(y.Fragment,{children:t.filter((e=>e!==n))});return(0,y.jsx)(Q,{...e,summary:n,children:o})}var ee=n(1107);function te(e){return(0,y.jsx)(ee.A,{...e})}const ne={containsTaskList:"containsTaskList_mC6p"};function se(e){if(void 0!==e)return(0,i.A)(e,e?.includes("contains-task-list")&&ne.containsTaskList)}const oe={img:"img_ev3q"};var ae=n(7293),ce=n(418);const ie={Head:a.A,details:X,Details:X,code:function(e){return function(e){return void 0!==e.children&&s.Children.toArray(e.children).every((e=>"string"==typeof e&&!e.includes("\n")))}(e)?(0,y.jsx)(P,{...e}):(0,y.jsx)(V,{...e})},a:function(e){return(0,y.jsx)(W.A,{...e})},pre:function(e){return(0,y.jsx)(y.Fragment,{children:e.children})},ul:function(e){return(0,y.jsx)("ul",{...e,className:se(e.className)})},li:function(e){return(0,D.A)().collectAnchor(e.id),(0,y.jsx)("li",{...e})},img:function(e){return(0,y.jsx)("img",{decoding:"async",loading:"lazy",...e,className:(t=e.className,(0,i.A)(t,oe.img))});var t},h1:e=>(0,y.jsx)(te,{as:"h1",...e}),h2:e=>(0,y.jsx)(te,{as:"h2",...e}),h3:e=>(0,y.jsx)(te,{as:"h3",...e}),h4:e=>(0,y.jsx)(te,{as:"h4",...e}),h5:e=>(0,y.jsx)(te,{as:"h5",...e}),h6:e=>(0,y.jsx)(te,{as:"h6",...e}),admonition:ae.A,mermaid:ce.A};function re(e){let{children:t}=e;return(0,y.jsx)(o.x,{components:ie,children:t})}},7763:(e,t,n)=>{"use strict";n.d(t,{A:()=>l});n(6540);var s=n(4164),o=n(5195);const a={tableOfContents:"tableOfContents_bqdL",docItemContainer:"docItemContainer_F8PC"};var c=n(4848);const i="table-of-contents__link toc-highlight",r="table-of-contents__link--active";function l(e){let{className:t,...n}=e;return(0,c.jsx)("div",{className:(0,s.A)(a.tableOfContents,"thin-scrollbar",t),children:(0,c.jsx)(o.A,{...n,linkClassName:i,linkActiveClassName:r})})}},5195:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});var s=n(6540),o=n(6342);function a(e){const t=e.map((e=>({...e,parentIndex:-1,children:[]}))),n=Array(7).fill(-1);t.forEach(((e,t)=>{const s=n.slice(2,e.level);e.parentIndex=Math.max(...s),n[e.level]=t}));const s=[];return t.forEach((e=>{const{parentIndex:n,...o}=e;n>=0?t[n].children.push(o):s.push(o)})),s}function c(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:s}=e;return t.flatMap((e=>{const t=c({toc:e.children,minHeadingLevel:n,maxHeadingLevel:s});return function(e){return e.level>=n&&e.level<=s}(e)?[{...e,children:t}]:t}))}function i(e){const t=e.getBoundingClientRect();return t.top===t.bottom?i(e.parentNode):t}function r(e,t){let{anchorTopOffset:n}=t;const s=e.find((e=>i(e).top>=n));if(s){return function(e){return e.top>0&&e.bottom {e.current=t?0:document.querySelector(".navbar").clientHeight}),[t]),e}function d(e){const t=(0,s.useRef)(void 0),n=l();(0,s.useEffect)((()=>{if(!e)return()=>{};const{linkClassName:s,linkActiveClassName:o,minHeadingLevel:a,maxHeadingLevel:c}=e;function i(){const e=function(e){return Array.from(document.getElementsByClassName(e))}(s),i=function(e){let{minHeadingLevel:t,maxHeadingLevel:n}=e;const s=[];for(let o=t;o<=n;o+=1)s.push(`h${o}.anchor`);return Array.from(document.querySelectorAll(s.join()))}({minHeadingLevel:a,maxHeadingLevel:c}),l=r(i,{anchorTopOffset:n.current}),d=e.find((e=>l&&l.id===function(e){return decodeURIComponent(e.href.substring(e.href.indexOf("#")+1))}(e)));e.forEach((e=>{!function(e,n){n?(t.current&&t.current!==e&&t.current.classList.remove(o),e.classList.add(o),t.current=e):e.classList.remove(o)}(e,e===d)}))}return document.addEventListener("scroll",i),document.addEventListener("resize",i),i(),()=>{document.removeEventListener("scroll",i),document.removeEventListener("resize",i)}}),[e,n])}var u=n(8774),m=n(4848);function h(e){let{toc:t,className:n,linkClassName:s,isChild:o}=e;return t.length?(0,m.jsx)("ul",{className:o?void 0:n,children:t.map((e=>(0,m.jsxs)("li",{children:[(0,m.jsx)(u.A,{to:`#${e.id}`,className:s??void 0,dangerouslySetInnerHTML:{__html:e.value}}),(0,m.jsx)(h,{isChild:!0,toc:e.children,className:n,linkClassName:s})]},e.id)))}):null}const f=s.memo(h);function p(e){let{toc:t,className:n="table-of-contents table-of-contents__left-border",linkClassName:i="table-of-contents__link",linkActiveClassName:r,minHeadingLevel:l,maxHeadingLevel:u,...h}=e;const p=(0,o.p)(),x=l??p.tableOfContents.minHeadingLevel,g=u??p.tableOfContents.maxHeadingLevel,b=function(e){let{toc:t,minHeadingLevel:n,maxHeadingLevel:o}=e;return(0,s.useMemo)((()=>c({toc:a(t),minHeadingLevel:n,maxHeadingLevel:o})),[t,n,o])}({toc:t,minHeadingLevel:x,maxHeadingLevel:g});return d((0,s.useMemo)((()=>{if(i&&r)return{linkClassName:i,linkActiveClassName:r,minHeadingLevel:x,maxHeadingLevel:g}}),[i,r,x,g])),(0,m.jsx)(f,{toc:b,className:n,linkClassName:i,...h})}},996:(e,t,n)=>{"use strict";n.d(t,{A:()=>h});n(6540);var s=n(4164),o=n(1312),a=n(5260),c=n(4848);function i(){return(0,c.jsx)(o.A,{id:"theme.unlistedContent.title",description:"The unlisted content banner title",children:"Unlisted page"})}function r(){return(0,c.jsx)(o.A,{id:"theme.unlistedContent.message",description:"The unlisted content banner message",children:"This page is unlisted. Search engines will not index it, and only users having a direct link can access it."})}function l(){return(0,c.jsx)(a.A,{children:(0,c.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})}var d=n(7559),u=n(7293);function m(e){let{className:t}=e;return(0,c.jsx)(u.A,{type:"caution",title:(0,c.jsx)(i,{}),className:(0,s.A)(t,d.G.common.unlistedBanner),children:(0,c.jsx)(r,{})})}function h(e){return(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(l,{}),(0,c.jsx)(m,{...e})]})}},8426:(e,t)=>{function n(e){let t,n=[];for(let s of e.split(",").map((e=>e.trim())))if(/^-?\d+$/.test(s))n.push(parseInt(s,10));else if(t=s.match(/^(-?\d+)(-|\.\.\.?|\u2025|\u2026|\u22EF)(-?\d+)$/)){let[e,s,o,a]=t;if(s&&a){s=parseInt(s),a=parseInt(a);const e=s{"use strict";n.d(t,{R:()=>c,x:()=>i});var s=n(6540);const o={},a=s.createContext(o);function c(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/36ebdf3e.c81514b8.js b/assets/js/36ebdf3e.c81514b8.js new file mode 100644 index 000000000..db15bf8c7 --- /dev/null +++ b/assets/js/36ebdf3e.c81514b8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7787],{7162:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var n=t(4848),o=t(8453);const r={},d="Zero Address",i={id:"detectors/ZeroAddress",title:"Zero Address",description:"A detector that identifies uses of the zero address.",source:"@site/versioned_docs/version-0.1.2/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/0.1.2/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/detectors/ZeroAddress.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Unbound Loops",permalink:"/tools/misti/docs/0.1.2/detectors/UnboundLoops"},next:{title:"Contributing",permalink:"/tools/misti/docs/0.1.2/hacking/contributing"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"zero-address",children:"Zero Address"}),"\n",(0,n.jsx)(s.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(s.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(s.p,{children:"Use instead:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initializaiton.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>d,x:()=>i});var n=t(6540);const o={},r=n.createContext(o);function d(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/377c4f81.79a338ae.js b/assets/js/377c4f81.79a338ae.js new file mode 100644 index 000000000..00298847f --- /dev/null +++ b/assets/js/377c4f81.79a338ae.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3448],{235:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>I,default:()=>c,frontMatter:()=>l,metadata:()=>d,toc:()=>g});var n=t(4848),s=t(8453);const l={},I="Tools Guide",d={id:"hacking/tools",title:"Tools Guide",description:"This page describes the internal analyzer tools available in Misti to aid in development and debugging.",source:"@site/versioned_docs/version-0.3.0/hacking/tools.md",sourceDirName:"hacking",slug:"/hacking/tools",permalink:"/tools/misti/docs/0.3.0/hacking/tools",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/hacking/tools.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.3.0/hacking/souffle"},next:{title:"Custom Detectors",permalink:"/tools/misti/docs/0.3.0/hacking/custom-detector"}},o={},g=[{value:"CFG Dump",id:"cfg-dump",level:2},{value:"Usage",id:"usage",level:3},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function a(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"tools-guide",children:"Tools Guide"}),"\n",(0,n.jsx)(e.p,{children:"This page describes the internal analyzer tools available in Misti to aid in development and debugging."}),"\n",(0,n.jsx)(e.h2,{id:"cfg-dump",children:"CFG Dump"}),"\n",(0,n.jsx)(e.p,{children:"Misti provides a feature to dump the Control Flow Graph (CFG) in both JSON and DOT formats. This is essential for understanding the internal representation (IR) of the code and analyzing the control flow within contracts."}),"\n",(0,n.jsx)(e.h3,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="json" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" \n'})}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, you can save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allows you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for gaining a better understanding of the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function c(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(a,{...i})}):a(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>I,x:()=>d});var n=t(6540);const s={},l=n.createContext(s);function I(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function d(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:I(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/393be207.fc96af0e.js b/assets/js/393be207.fc96af0e.js new file mode 100644 index 000000000..d58aab05e --- /dev/null +++ b/assets/js/393be207.fc96af0e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4134],{633:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>p,default:()=>l,frontMatter:()=>r,metadata:()=>s,toc:()=>i});var o=t(4848),a=t(8453);const r={title:"Markdown page example"},p="Markdown page example",s={type:"mdx",permalink:"/markdown-page",source:"@site/src/pages/markdown-page.md",title:"Markdown page example",description:"You don't need React to write simple standalone pages.",frontMatter:{title:"Markdown page example"},unlisted:!1},c={},i=[];function d(e){const n={h1:"h1",p:"p",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"markdown-page-example",children:"Markdown page example"}),"\n",(0,o.jsx)(n.p,{children:"You don't need React to write simple standalone pages."})]})}function l(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>p,x:()=>s});var o=t(6540);const a={},r=o.createContext(a);function p(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:p(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3b3a1a75.bf621ae4.js b/assets/js/3b3a1a75.bf621ae4.js new file mode 100644 index 000000000..ad9722d13 --- /dev/null +++ b/assets/js/3b3a1a75.bf621ae4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2478],{4727:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var s=n(4848),o=n(8453);const a={},i="ArgCopyMutation",r={id:"detectors/ArgCopyMutation",title:"ArgCopyMutation",description:"A detector that highlights cases where function argument mutations are ineffective",source:"@site/versioned_docs/version-0.4.0/detectors/ArgCopyMutation.md",sourceDirName:"detectors",slug:"/detectors/ArgCopyMutation",permalink:"/tools/misti/docs/0.4.0/detectors/ArgCopyMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/ArgCopyMutation.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.4.0/detectors"},next:{title:"AsmIsUsed",permalink:"/tools/misti/docs/0.4.0/detectors/AsmIsUsed"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"argcopymutation",children:"ArgCopyMutation"}),"\n",(0,s.jsxs)(t.p,{children:["A detector that highlights cases where function argument mutations are ineffective\ndue to ",(0,s.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value",children:"call-by-value semantics"})," in Tact."]}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"In Tact, function arguments are passed by value, meaning that any mutations applied\nto these arguments will only affect the local copy of the variable within the function.\nSuch mutations are unobservable outside the function, except for potentially\nincreasing gas consumption or causing exceptions."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun addEntry(m: map ) {\n m.set(1, 10); // Bad: Mutating the copy\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun addEntry() {\n self.m.set(1, 10); // OK: Changing contract's state\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Alternatively, you could redesign the method:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun generateNewValue(): Int {\n // ... produce new value for the map\n return self.nextValue + 1;\n}\n\nm.set(self.nextKey, self.generateNewValue()); // OK\n"})})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>r});var s=n(6540);const o={},a=s.createContext(o);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3bfe497f.10b20c3b.js b/assets/js/3bfe497f.10b20c3b.js new file mode 100644 index 000000000..19a7062e0 --- /dev/null +++ b/assets/js/3bfe497f.10b20c3b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5381],{4512:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var n=i(4848),s=i(8453);const r={},o="DivideBeforeMultiply",l={id:"detectors/DivideBeforeMultiply",title:"DivideBeforeMultiply",description:"A detector that identifies and corrects instances of division before multiplication to",source:"@site/versioned_docs/version-0.4.0/detectors/DivideBeforeMultiply.md",sourceDirName:"detectors",slug:"/detectors/DivideBeforeMultiply",permalink:"/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/DivideBeforeMultiply.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"ConstantAddress",permalink:"/tools/misti/docs/0.4.0/detectors/ConstantAddress"},next:{title:"DumpIsUsed",permalink:"/tools/misti/docs/0.4.0/detectors/DumpIsUsed"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function a(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dividebeforemultiply",children:"DivideBeforeMultiply"}),"\n",(0,n.jsx)(t.p,{children:"A detector that identifies and corrects instances of division before multiplication to\nensure accurate mathematical operations."}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Performing division before multiplication can lead to unexpected results due to precision loss and rounding errors:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Precision Loss:"})," Dividing first can result in significant precision loss, especially when dealing with integers or fixed-point numbers."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Rounding Errors:"})," Early division might cause rounding errors that propagate through subsequent calculations."]}),"\n",(0,n.jsxs)(t.li,{children:[(0,n.jsx)(t.strong,{children:"Unexpected Behavior:"})," Incorrectly ordered operations can lead to incorrect outcomes, making debugging and maintenance more challenging."]}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Bad: Division before multiplication\nlet result: Int = a / b * c;\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Correct: Multiplication before division\nlet result: Int = a * c / b;\n"})})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>l});var n=i(6540);const s={},r=n.createContext(s);function o(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3c9b1461.4a5fe7e2.js b/assets/js/3c9b1461.4a5fe7e2.js new file mode 100644 index 000000000..f8f747342 --- /dev/null +++ b/assets/js/3c9b1461.4a5fe7e2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3988],{849:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=n(4848),r=n(8453);const i={},o="PreferAugmentedAssign",a={id:"detectors/PreferAugmentedAssign",title:"PreferAugmentedAssign",description:"Detects non-idiomatic statements that can be written using augmented assignment",source:"@site/versioned_docs/version-0.5/detectors/PreferAugmentedAssign.md",sourceDirName:"detectors",slug:"/detectors/PreferAugmentedAssign",permalink:"/tools/misti/docs/detectors/PreferAugmentedAssign",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/PreferAugmentedAssign.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"OptimalMathFunction",permalink:"/tools/misti/docs/detectors/OptimalMathFunction"},next:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/detectors/PreferredStdlibApi"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"preferaugmentedassign",children:"PreferAugmentedAssign"}),"\n",(0,s.jsxs)(t.p,{children:["Detects non-idiomatic statements that can be written using augmented assignment\noperators like ",(0,s.jsx)(t.code,{children:"+="}),", ",(0,s.jsx)(t.code,{children:"-="}),", etc."]}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Using augmented assignment operations improves the readability of the source code\nand reduces the risk of mistakes, such as those that occur during copy-pasting\nand refactoring code."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue = (msgValue - ctx.readForwardFee());\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue -= ctx.readForwardFee());\n"})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/3db5102b.08380390.js b/assets/js/3db5102b.08380390.js new file mode 100644 index 000000000..706c5a887 --- /dev/null +++ b/assets/js/3db5102b.08380390.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6774],{6931:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>u});var i=e(4848),o=e(8453);const s={},r="Integrating Misti into CI/CD",c={id:"tutorial/ci-cd",title:"Integrating Misti into CI/CD",description:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.",source:"@site/versioned_docs/version-0.2.1/tutorial/ci-cd.md",sourceDirName:"tutorial",slug:"/tutorial/ci-cd",permalink:"/tools/misti/docs/0.2.1/tutorial/ci-cd",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/tutorial/ci-cd.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Getting Started",permalink:"/tools/misti/docs/0.2.1/tutorial/getting-started"},next:{title:"Configuration",permalink:"/tools/misti/docs/0.2.1/tutorial/configuration"}},a={},u=[{value:"GitHub Actions",id:"github-actions",level:2}];function l(t){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"integrating-misti-into-cicd",children:"Integrating Misti into CI/CD"}),"\n",(0,i.jsx)(n.p,{children:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle."}),"\n",(0,i.jsx)(n.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(n.p,{children:"To integrate Misti into your GitHub Actions workflow, you need to add a command that runs Misti as part of your CI process. Here's how you can do it:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"1. Open your GitHub repository"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"2. Create or edit the GitHub Actions workflow YAML file"})}),"\n",(0,i.jsxs)(n.p,{children:["It could be located at e.g., ",(0,i.jsx)(n.code,{children:".github/workflows/main.yml"}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"3. Add the step to run Misti to your YAML file"})}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"name: Run Misti\non: [push, pull_request]\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n\n - name: Install dependencies\n run: npm install\n\n - name: Run Misti\n run: npx misti /path/to/your/tact.config.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"npx misti /path/to/your/tact.config.json"})," command will run Misti against your project. If Misti detects any issues that are not suppressed by your configuration, it will return a non-zero exit code, causing the CI pipeline to fail."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"4. Adjusting the Misti Configuration"})}),"\n",(0,i.jsxs)(n.p,{children:["If you find that Misti is too noisy (e.g., detecting issues that are not relevant to your project), you can adjust your Misti configuration file to suppress those warnings. Refer to the ",(0,i.jsx)(n.a,{href:"./configuration",children:"Configuration"})," section for more details on how to customize your settings."]})]})}function d(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(l,{...t})}):l(t)}},8453:(t,n,e)=>{e.d(n,{R:()=>r,x:()=>c});var i=e(6540);const o={},s=i.createContext(o);function r(t){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function c(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:r(t.components),i.createElement(s.Provider,{value:n},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/40440f59.e19073b4.js b/assets/js/40440f59.e19073b4.js new file mode 100644 index 000000000..53036f164 --- /dev/null +++ b/assets/js/40440f59.e19073b4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5671],{8246:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var t=i(4848),s=i(8453);const o={},r="Contributing Guide",c={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/versioned_docs/version-0.5/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/hacking/contributing.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/hacking/souffle"},next:{title:"Developing Misti",permalink:"/tools/misti/docs/hacking/developing-misti"}},a={},l=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["See ",(0,t.jsx)(n.a,{href:"/tools/misti/docs/hacking/developing-misti",children:"Developing Misti"})," for information about initializing the environment and additional hacking tips."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>c});var t=i(6540);const s={},o=t.createContext(s);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/40be7dfa.be7d2a62.js b/assets/js/40be7dfa.be7d2a62.js new file mode 100644 index 000000000..f7bd65463 --- /dev/null +++ b/assets/js/40be7dfa.be7d2a62.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6602],{7991:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.2.0/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/0.2.0/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/index.md",tags:[],version:"0.2.0",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/0.2.0/tutorial/getting-started"}},c={},d=[{value:"Use Cases",id:"use-cases",level:2},{value:"Funding",id:"funding",level:2}];function l(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.4.4 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been ",(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"funded"})," by ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"}),". This support has enabled us to develop and maintain the tool."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/42510f93.835e2f8a.js b/assets/js/42510f93.835e2f8a.js new file mode 100644 index 000000000..0593bb056 --- /dev/null +++ b/assets/js/42510f93.835e2f8a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2913],{5875:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var i=n(4848),s=n(8453);const r={},o="Developing Misti",a={id:"hacking/developing-misti",title:"Developing Misti",description:"Prerequisites",source:"@site/versioned_docs/version-0.4.0/hacking/developing-misti.md",sourceDirName:"hacking",slug:"/hacking/developing-misti",permalink:"/tools/misti/docs/0.4.0/hacking/developing-misti",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/hacking/developing-misti.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.4.0/hacking/contributing"},next:{title:"Design Overview",permalink:"/tools/misti/docs/0.4.0/hacking/design"}},c={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Cloning the Repository",id:"cloning-the-repository",level:2},{value:"Building the Project",id:"building-the-project",level:2},{value:"Running the Analyzer",id:"running-the-analyzer",level:2},{value:"Adding Backtraces to the Logger",id:"adding-backtraces-to-the-logger",level:2},{value:"Updating Expected Outputs of Tests",id:"updating-expected-outputs-of-tests",level:2}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"developing-misti",children:"Developing Misti"}),"\n",(0,i.jsx)(t.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsxs)(t.p,{children:["Before you begin, please refer to the ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/docs/next/tutorial/getting-started",children:"Getting Started documentation"})," for the required system dependencies."]}),"\n",(0,i.jsx)(t.h2,{id:"cloning-the-repository",children:"Cloning the Repository"}),"\n",(0,i.jsx)(t.p,{children:"Clone the Misti repository:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"git clone 'https://github.com/nowarp/misti'\n"})}),"\n",(0,i.jsx)(t.h2,{id:"building-the-project",children:"Building the Project"}),"\n",(0,i.jsx)(t.p,{children:"Navigate to the project directory, install dependencies, generate necessary files, and build the project:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"cd misti && yarn install && yarn gen && yarn build\n"})}),"\n",(0,i.jsx)(t.h2,{id:"running-the-analyzer",children:"Running the Analyzer"}),"\n",(0,i.jsx)(t.p,{children:"During development, you can run the analyzer using:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"yarn misti\n"})}),"\n",(0,i.jsx)(t.p,{children:"For example, to run it for tests:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"yarn misti test/good/never-accessed.tact\n"})}),"\n",(0,i.jsx)(t.h2,{id:"adding-backtraces-to-the-logger",children:"Adding Backtraces to the Logger"}),"\n",(0,i.jsxs)(t.p,{children:["To add debug traces to all log messages, set the ",(0,i.jsx)(t.code,{children:"MISTI_TRACE"})," environment variable to ",(0,i.jsx)(t.code,{children:"1"}),":"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"export MISTI_TRACE=1\n"})}),"\n",(0,i.jsx)(t.h2,{id:"updating-expected-outputs-of-tests",children:"Updating Expected Outputs of Tests"}),"\n",(0,i.jsxs)(t.p,{children:["To update the expected outputs of tests, set the ",(0,i.jsx)(t.code,{children:"BLESS"})," environment variable and run the tests:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test\n"})}),"\n",(0,i.jsx)(t.p,{children:"You can also run a single test or update its expected output when working with a specific test file:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test test/tactIR.spec.ts tests/good/never-accessed.tact\n"})}),"\n",(0,i.jsx)(t.p,{children:"And for another specific test:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test test/builtinDetectors.spec.ts test/good/branch-duplicate.tact\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var i=n(6540);const s={},r=i.createContext(s);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/432cb5a5.d823b28c.js b/assets/js/432cb5a5.d823b28c.js new file mode 100644 index 000000000..d17dfa682 --- /dev/null +++ b/assets/js/432cb5a5.d823b28c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3840],{4303:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>l,toc:()=>c});var s=n(4848),a=n(8453);const t={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.4.0/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.4.0/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/hacking/design.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Developing Misti",permalink:"/tools/misti/docs/0.4.0/hacking/developing-misti"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.4.0/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,a.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const a={},t=s.createContext(a);function o(e){const i=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:o(e.components),s.createElement(t.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/43c93918.b3c5c4ff.js b/assets/js/43c93918.b3c5c4ff.js new file mode 100644 index 000000000..e97ab7b8b --- /dev/null +++ b/assets/js/43c93918.b3c5c4ff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1299],{955:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.3.1/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/0.3.1/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/index.md",tags:[],version:"0.3.1",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/0.3.1/tutorial/getting-started"}},c={},d=[{value:"Use Cases",id:"use-cases",level:2},{value:"Name Origin",id:"name-origin",level:2},{value:"Funding",id:"funding",level:2}];function l(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.5 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"name-origin",children:"Name Origin"}),"\n",(0,i.jsx)(t.p,{children:'The name "Misti" comes from the Misti volcano in Peru. It was chosen because it\'s catchy and easy to remember.'}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been ",(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"funded"})," by ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"}),". This support has enabled us to develop and maintain the tool."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4518efa7.b9ef0cc5.js b/assets/js/4518efa7.b9ef0cc5.js new file mode 100644 index 000000000..c70bbf268 --- /dev/null +++ b/assets/js/4518efa7.b9ef0cc5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6544],{2308:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="Branch Duplicate",o={id:"detectors/BranchDuplicate",title:"Branch Duplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.2.2/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/0.2.2/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/BranchDuplicate.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Constant Address",permalink:"/tools/misti/docs/0.2.2/detectors/ConstantAddress"},next:{title:"`dump` Is Used",permalink:"/tools/misti/docs/0.2.2/detectors/DumpIsUsed"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branch-duplicate",children:"Branch Duplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4624921c.a36b4fff.js b/assets/js/4624921c.a36b4fff.js new file mode 100644 index 000000000..62d7860f5 --- /dev/null +++ b/assets/js/4624921c.a36b4fff.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9510],{9567:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>s,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>d});var i=t(4848),r=t(8453);const a={},s="ReadOnlyVariables",l={id:"detectors/ReadOnlyVariables",title:"ReadOnlyVariables",description:"A detector that identifies read-only variables and fields.",source:"@site/versioned_docs/version-0.5/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/ReadOnlyVariables.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/detectors/PreferredStdlibApi"},next:{title:"SendInLoop",permalink:"/tools/misti/docs/detectors/SendInLoop"}},o={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"readonlyvariables",children:"ReadOnlyVariables"}),"\n",(0,i.jsx)(n.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,i.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsx)(n.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,i.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Use instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the analyzer highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>l});var i=t(6540);const r={},a=i.createContext(r);function s(e){const n=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),i.createElement(a.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/46947df5.86adfe22.js b/assets/js/46947df5.86adfe22.js new file mode 100644 index 000000000..787c1dd41 --- /dev/null +++ b/assets/js/46947df5.86adfe22.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4992],{1904:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var i=t(4848),r=t(8453);const o={},a="EnsurePrgSeed",s={id:"detectors/EnsurePrgSeed",title:"EnsurePrgSeed",description:"A detector that identifies all calls to nativeRandom and nativeRandomInterval",source:"@site/versioned_docs/version-0.5/detectors/EnsurePrgSeed.md",sourceDirName:"detectors",slug:"/detectors/EnsurePrgSeed",permalink:"/tools/misti/docs/detectors/EnsurePrgSeed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/EnsurePrgSeed.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"DuplicatedCondition",permalink:"/tools/misti/docs/detectors/DuplicatedCondition"},next:{title:"FalseCondition",permalink:"/tools/misti/docs/detectors/FalseCondition"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"ensureprgseed",children:"EnsurePrgSeed"}),"\n",(0,i.jsxs)(n.p,{children:["A detector that identifies all calls to ",(0,i.jsx)(n.code,{children:"nativeRandom"})," and ",(0,i.jsx)(n.code,{children:"nativeRandomInterval"}),"\nwithout a preceding PRG seed initialization."]}),"\n",(0,i.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(n.p,{children:["Using ",(0,i.jsx)(n.code,{children:"nativeRandom"})," or ",(0,i.jsx)(n.code,{children:"nativeRandomInterval"})," without first initializing the PRG seed via\n",(0,i.jsx)(n.code,{children:"nativePrepareRandom"}),", ",(0,i.jsx)(n.code,{children:"nativeRandomize"}),", or ",(0,i.jsx)(n.code,{children:"nativeRandomizeLt"})," may lead to unintended behavior\nor weak random number generation. This detector ensures that PRG seed initialization\nis always performed before any use of random functions, enhancing contract security."]}),"\n",(0,i.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"// Bad: `nativeRandom` is used without prior PRG seed initialization\nfun generateRandomValue(): Int {\n return nativeRandom()\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Use instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"fun test(): Int {\n nativePrepareRandom();\n}\n\n// OK: PRG has been initialized somewhere in the contract\nfun generateRandomValue(): Int {\n return nativeRandom()\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>s});var i=t(6540);const r={},o=i.createContext(r);function a(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/474ce197.29e1c442.js b/assets/js/474ce197.29e1c442.js new file mode 100644 index 000000000..615c99e26 --- /dev/null +++ b/assets/js/474ce197.29e1c442.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4069],{7715:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"0.2.1","label":"0.2.1","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-0.2.1","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/0.2.1/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/0.2.1/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"CI/CD Integration","href":"/tools/misti/docs/0.2.1/tutorial/ci-cd","docId":"tutorial/ci-cd","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/0.2.1/tutorial/configuration","docId":"tutorial/configuration","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Detectors Overview","href":"/tools/misti/docs/0.2.1/detectors","docId":"detectors","unlisted":false},{"type":"category","label":"Detectors","items":[{"type":"link","label":"Divide before Multiply","href":"/tools/misti/docs/0.2.1/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"Never-accessed Variables","href":"/tools/misti/docs/0.2.1/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"Read-only Variables","href":"/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"Unbound Loops","href":"/tools/misti/docs/0.2.1/detectors/UnboundLoops","docId":"detectors/UnboundLoops","unlisted":false},{"type":"link","label":"Zero Address","href":"/tools/misti/docs/0.2.1/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false},{"type":"link","label":"Constant Address","href":"/tools/misti/docs/0.2.1/detectors/ConstantAddress","docId":"detectors/ConstantAddress","unlisted":false},{"type":"link","label":"Branch Duplicate","href":"/tools/misti/docs/0.2.1/detectors/BranchDuplicate","docId":"detectors/BranchDuplicate","unlisted":false},{"type":"link","label":"`dump` Is Used","href":"/tools/misti/docs/0.2.1/detectors/DumpIsUsed","docId":"detectors/DumpIsUsed","unlisted":false},{"type":"link","label":"Field Initialized Twice","href":"/tools/misti/docs/0.2.1/detectors/FieldDoubleInit","docId":"detectors/FieldDoubleInit","unlisted":false},{"type":"link","label":"Prefer Augmented Assignment","href":"/tools/misti/docs/0.2.1/detectors/PreferAugmentedAssign","docId":"detectors/PreferAugmentedAssign","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/0.2.1/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Design Overview","href":"/tools/misti/docs/0.2.1/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/0.2.1/hacking/souffle","docId":"hacking/souffle","unlisted":false},{"type":"link","label":"Tools","href":"/tools/misti/docs/0.2.1/hacking/tools","docId":"hacking/tools","unlisted":false},{"type":"link","label":"Custom Detectors","href":"/tools/misti/docs/0.2.1/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"detectors":{"id":"detectors","title":"Detectors Overview","description":"Here\'s a list of all the detectors:","sidebar":"sidebar"},"detectors/BranchDuplicate":{"id":"detectors/BranchDuplicate","title":"Branch Duplicate","description":"Detector that reports duplicated code in conditional branches.","sidebar":"sidebar"},"detectors/ConstantAddress":{"id":"detectors/ConstantAddress","title":"Constant Address","description":"An optional detector that highlights all the constant addresses appearing in the source code.","sidebar":"sidebar"},"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"Divide before Multiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/DumpIsUsed":{"id":"detectors/DumpIsUsed","title":"dump Is Used","description":"An optional detector that highlights all the dump function calls.","sidebar":"sidebar"},"detectors/FieldDoubleInit":{"id":"detectors/FieldDoubleInit","title":"Field Initialized Twice","description":"A detector that highlights cases where a field is initialized both in the init function and at the point of definition.","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"Never-accessed Variables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/PreferAugmentedAssign":{"id":"detectors/PreferAugmentedAssign","title":"Prefer Augmented Assignment","description":"Detects non-idiomatic statements that can be written using augmented assignment operators like +=, -=, etc.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"Read-only Variables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/UnboundLoops":{"id":"detectors/UnboundLoops","title":"Unbound Loops","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"Zero Address","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"hacking/tools":{"id":"hacking/tools","title":"Tools Guide","description":"This page describes the internal analyzer tools available in Misti to aid in development and debugging.","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tutorial/ci-cd":{"id":"tutorial/ci-cd","title":"Integrating Misti into CI/CD","description":"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/49256311.be5c404d.js b/assets/js/49256311.be5c404d.js new file mode 100644 index 000000000..bd5aea274 --- /dev/null +++ b/assets/js/49256311.be5c404d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2734],{9475:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="ConstantAddress",a={id:"detectors/ConstantAddress",title:"ConstantAddress",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/versioned_docs/version-0.3.1/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/0.3.1/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/ConstantAddress.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"BranchDuplicate",permalink:"/tools/misti/docs/0.3.1/detectors/BranchDuplicate"},next:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constantaddress",children:"ConstantAddress"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4ab26116.35b4841f.js b/assets/js/4ab26116.35b4841f.js new file mode 100644 index 000000000..f601f891b --- /dev/null +++ b/assets/js/4ab26116.35b4841f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9276],{1857:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="ConstantAddress",a={id:"detectors/ConstantAddress",title:"ConstantAddress",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/versioned_docs/version-0.4.0/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/0.4.0/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/ConstantAddress.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"BranchDuplicate",permalink:"/tools/misti/docs/0.4.0/detectors/BranchDuplicate"},next:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constantaddress",children:"ConstantAddress"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4b89306f.efdf0920.js b/assets/js/4b89306f.efdf0920.js new file mode 100644 index 000000000..44f92da7b --- /dev/null +++ b/assets/js/4b89306f.efdf0920.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6769],{1821:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.3.1/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.3.1/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/hacking/souffle.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.3.1/hacking/design"},next:{title:"Tools",permalink:"/tools/misti/docs/0.3.1/hacking/tools"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is implemented in the ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/souffle.js",children:"Souffle.js library"}),". See the ",(0,t.jsx)(n.a,{href:"https://nowarp.io/lib/souffle-js/api/",children:"Souffle.js API reference"})," for more detailed information."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4d74b396.8aebea31.js b/assets/js/4d74b396.8aebea31.js new file mode 100644 index 000000000..34cece6f8 --- /dev/null +++ b/assets/js/4d74b396.8aebea31.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9802],{1167:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var a=t(4848),i=t(8453);const r={},s="Read-only Variables",o={id:"detectors/ReadOnlyVariables",title:"Read-only Variables",description:"A detector that identifies read-only variables and fields.",source:"@site/versioned_docs/version-0.2.1/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/ReadOnlyVariables.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Never-accessed Variables",permalink:"/tools/misti/docs/0.2.1/detectors/NeverAccessedVariables"},next:{title:"Unbound Loops",permalink:"/tools/misti/docs/0.2.1/detectors/UnboundLoops"}},l={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"read-only-variables",children:"Read-only Variables"}),"\n",(0,a.jsx)(n.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,a.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,a.jsx)(n.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,a.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"Use instead:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the linter highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>o});var a=t(6540);const i={},r=a.createContext(i);function s(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4f2bb7ce.0a476d8d.js b/assets/js/4f2bb7ce.0a476d8d.js new file mode 100644 index 000000000..d8a5608d9 --- /dev/null +++ b/assets/js/4f2bb7ce.0a476d8d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6156],{8867:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var i=n(4848),o=n(8453);const r={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.3.1/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/0.3.1/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/hacking/custom-detector.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Tools",permalink:"/tools/misti/docs/0.3.1/hacking/tools"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Creating a Detector",id:"creating-a-detector",level:2},{value:"Testing the detector",id:"testing-the-detector",level:3},{value:"Saving the configuration",id:"saving-the-configuration",level:3},{value:"Example Detectors",id:"example-detectors",level:2}];function h(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,i.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,i.jsx)(t.h2,{id:"creating-a-detector",children:"Creating a Detector"}),"\n",(0,i.jsxs)(t.p,{children:["You can create a new custom detector by executing Misti with the ",(0,i.jsx)(t.code,{children:"--new-detector"})," option: ",(0,i.jsx)(t.code,{children:"npx misti --new-detector implicitInit"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["This will create the ",(0,i.jsx)(t.code,{children:"implicitInit.ts"})," file, which contains the template code for writing your own custom detector logic leveraging the Misti API."]}),"\n",(0,i.jsx)(t.p,{children:"Here's an example of how to implement a custom detector using Misti API:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-typescript",children:'import { Detector } from "@nowarp/misti/dist/detectors/detector";\nimport { CompilationUnit } from "@nowarp/misti/dist/internals/ir";\nimport {\n MistiTactWarning,\n Severity,\n} from "@nowarp/misti/dist/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that doesn\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends Detector {\n async check(cu: CompilationUnit): Promise {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = this.makeError(\n `Contract ${contract.name} doesn\'t define an init function`,\n Severity.INFO,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactWarning[]);\n }\n}\n'})}),"\n",(0,i.jsx)(t.h3,{id:"testing-the-detector",children:"Testing the detector"}),"\n",(0,i.jsxs)(t.p,{children:["To run Misti with only your new detector, use the ",(0,i.jsx)(t.code,{children:"--detectors"})," option, specifying the path to the detector and the Detector class name: ",(0,i.jsx)(t.code,{children:"npx misti path/to/your/tact.config.json --detectors path/to/implicitInit.ts:ImplicitInit"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["That's a good way to test the detector on the first run. You could also use the ",(0,i.jsx)(t.code,{children:"--verbose"})," CLI option and set the environment variable ",(0,i.jsx)(t.code,{children:"MISTI_TRACE=1"})," to facilitate debugging."]}),"\n",(0,i.jsx)(t.h3,{id:"saving-the-configuration",children:"Saving the configuration"}),"\n",(0,i.jsx)(t.p,{children:"After testing the detector, you can specify it in your configuration to enable it in future runs. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'{\n "detectors": [\n // Other detectors...\n { "className": "ImplicitInit", "modulePath": "ImplicitInit.ts" }\n ],\n}\n'})}),"\n",(0,i.jsxs)(t.p,{children:["After this, you could run Misti specifying a path to a custom configuration ",(0,i.jsx)(t.code,{children:"npx misti --config path/to/misti.config.json path/to/your/tact.config.json"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,i.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var i=n(6540);const o={},r=i.createContext(o);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/4fd06f05.45b0f688.js b/assets/js/4fd06f05.45b0f688.js new file mode 100644 index 000000000..95cb00a08 --- /dev/null +++ b/assets/js/4fd06f05.45b0f688.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6948],{7402:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>u});var i=e(4848),o=e(8453);const s={},r="Integrating Misti into CI/CD",c={id:"tutorial/ci-cd",title:"Integrating Misti into CI/CD",description:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.",source:"@site/versioned_docs/version-0.2.0/tutorial/ci-cd.md",sourceDirName:"tutorial",slug:"/tutorial/ci-cd",permalink:"/tools/misti/docs/0.2.0/tutorial/ci-cd",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/tutorial/ci-cd.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Getting Started",permalink:"/tools/misti/docs/0.2.0/tutorial/getting-started"},next:{title:"Configuration",permalink:"/tools/misti/docs/0.2.0/tutorial/configuration"}},a={},u=[{value:"GitHub Actions",id:"github-actions",level:2}];function l(t){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"integrating-misti-into-cicd",children:"Integrating Misti into CI/CD"}),"\n",(0,i.jsx)(n.p,{children:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle."}),"\n",(0,i.jsx)(n.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(n.p,{children:"To integrate Misti into your GitHub Actions workflow, you need to add a command that runs Misti as part of your CI process. Here's how you can do it:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"1. Open your GitHub repository"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"2. Create or edit the GitHub Actions workflow YAML file"})}),"\n",(0,i.jsxs)(n.p,{children:["It could be located at e.g., ",(0,i.jsx)(n.code,{children:".github/workflows/main.yml"}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"3. Add the step to run Misti to your YAML file"})}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"name: Run Misti\non: [push, pull_request]\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n\n - name: Install dependencies\n run: npm install\n\n - name: Run Misti\n run: npx misti /path/to/your/tact.config.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"npx misti /path/to/your/tact.config.json"})," command will run Misti against your project. If Misti detects any issues that are not suppressed by your configuration, it will return a non-zero exit code, causing the CI pipeline to fail."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"4. Adjusting the Misti Configuration"})}),"\n",(0,i.jsxs)(n.p,{children:["If you find that Misti is too noisy (e.g., detecting issues that are not relevant to your project), you can adjust your Misti configuration file to suppress those warnings. Refer to the ",(0,i.jsx)(n.a,{href:"./configuration",children:"Configuration"})," section for more details on how to customize your settings."]})]})}function d(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(l,{...t})}):l(t)}},8453:(t,n,e)=>{e.d(n,{R:()=>r,x:()=>c});var i=e(6540);const o={},s=i.createContext(o);function r(t){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function c(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:r(t.components),i.createElement(s.Provider,{value:n},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/51fe41a6.efba011c.js b/assets/js/51fe41a6.efba011c.js new file mode 100644 index 000000000..a274a7062 --- /dev/null +++ b/assets/js/51fe41a6.efba011c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8290],{723:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="NeverAccessedVariables",o={id:"detectors/NeverAccessedVariables",title:"NeverAccessedVariables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.4.0/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/NeverAccessedVariables.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/0.4.0/detectors/InheritedStateMutation"},next:{title:"OptimalMathFunction",permalink:"/tools/misti/docs/0.4.0/detectors/OptimalMathFunction"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"neveraccessedvariables",children:"NeverAccessedVariables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the analyzer highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/53023ca8.611e95e8.js b/assets/js/53023ca8.611e95e8.js new file mode 100644 index 000000000..99273eb42 --- /dev/null +++ b/assets/js/53023ca8.611e95e8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2712],{4228:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="NeverAccessedVariables",o={id:"detectors/NeverAccessedVariables",title:"NeverAccessedVariables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.5/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/NeverAccessedVariables.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/detectors/InheritedStateMutation"},next:{title:"OptimalMathFunction",permalink:"/tools/misti/docs/detectors/OptimalMathFunction"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"neveraccessedvariables",children:"NeverAccessedVariables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the analyzer highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/54df6b9c.ab93266a.js b/assets/js/54df6b9c.ab93266a.js new file mode 100644 index 000000000..bf3d59452 --- /dev/null +++ b/assets/js/54df6b9c.ab93266a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8962],{7852:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>d,toc:()=>a});var i=n(4848),o=n(8453);const s={},r="DuplicatedCondition",d={id:"detectors/DuplicatedCondition",title:"DuplicatedCondition",description:"A detector that finds duplicated conditions appearing in conditional expressions.",source:"@site/versioned_docs/version-0.5/detectors/DuplicatedCondition.md",sourceDirName:"detectors",slug:"/detectors/DuplicatedCondition",permalink:"/tools/misti/docs/detectors/DuplicatedCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/DuplicatedCondition.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpIsUsed",permalink:"/tools/misti/docs/detectors/DumpIsUsed"},next:{title:"EnsurePrgSeed",permalink:"/tools/misti/docs/detectors/EnsurePrgSeed"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"duplicatedcondition",children:"DuplicatedCondition"}),"\n",(0,i.jsx)(t.p,{children:"A detector that finds duplicated conditions appearing in conditional expressions."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsx)(t.p,{children:"Typically, these cases are developer errors caused by copy-pasting code, leading\nto unreachable code."}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"fun test(a: Int): Int {\n if (a < 1) { return 1; }\n else if (a > 4) { return 2; }\n // Bad: A developer copy-pasted the condition\n else if (a > 4) { return 3; }\n return 4;\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"fun test(a: Int): Int {\n if (a < 1) { return 1; }\n else if (a > 4) { return 2; }\n // OK: Fixed\n else if (a < x) { return 3; }\n return 4;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>d});var i=n(6540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/55e1201d.f5805772.js b/assets/js/55e1201d.f5805772.js new file mode 100644 index 000000000..45d35104f --- /dev/null +++ b/assets/js/55e1201d.f5805772.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8422],{2165:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>r,toc:()=>l});var i=n(4848),s=n(8453);const a={},o="OptimalMathFunction",r={id:"detectors/OptimalMathFunction",title:"OptimalMathFunction",description:"A detector that highlights standard library math function calls that have more gas-efficient alternatives.",source:"@site/docs/detectors/OptimalMathFunction.md",sourceDirName:"detectors",slug:"/detectors/OptimalMathFunction",permalink:"/tools/misti/docs/next/detectors/OptimalMathFunction",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/OptimalMathFunction.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/next/detectors/NeverAccessedVariables"},next:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/next/detectors/PreferAugmentedAssign"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"optimalmathfunction",children:"OptimalMathFunction"}),"\n",(0,i.jsx)(t.p,{children:"A detector that highlights standard library math function calls that have more gas-efficient alternatives."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Tact supports ",(0,i.jsx)(t.code,{children:"log2"}),"/",(0,i.jsx)(t.code,{children:"pow2"})," functions, which are more gas-efficient than ",(0,i.jsx)(t.code,{children:"log(x, 2)"}),"/",(0,i.jsx)(t.code,{children:"pow(x, 2)"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"log(x, 2);\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"log2(x)\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>r});var i=n(6540);const s={},a=i.createContext(s);function o(e){const t=i.useContext(a);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5604.07bdff8a.js b/assets/js/5604.07bdff8a.js new file mode 100644 index 000000000..2bb23b69a --- /dev/null +++ b/assets/js/5604.07bdff8a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5604],{5604:(t,e,r)=>{r.d(e,{zyo:()=>v});var n=r(6540),o={color:void 0,size:void 0,className:void 0,style:void 0,attr:void 0},i=n.createContext&&n.createContext(o),c=["attr","size","title"];function a(t,e){if(null==t)return{};var r,n,o=function(t,e){if(null==t)return{};var r={};for(var n in t)if(Object.prototype.hasOwnProperty.call(t,n)){if(e.indexOf(n)>=0)continue;r[n]=t[n]}return r}(t,e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);for(n=0;n =0||Object.prototype.propertyIsEnumerable.call(t,r)&&(o[r]=t[r])}return o}function l(){return l=Object.assign?Object.assign.bind():function(t){for(var e=1;e n.createElement(t.tag,s({key:e},t.attr),p(t.child))))}function b(t){return e=>n.createElement(y,l({attr:s({},t.attr)},e),p(t.child))}function y(t){var e=e=>{var r,{attr:o,size:i,title:u}=t,f=a(t,c),p=i||e.size||"1em";return e.className&&(r=e.className),t.className&&(r=(r?r+" ":"")+t.className),n.createElement("svg",l({stroke:"currentColor",fill:"currentColor",strokeWidth:"0"},e.attr,o,f,{className:r,style:s(s({color:t.color||e.color},e.style),t.style),height:p,width:p,xmlns:"http://www.w3.org/2000/svg"}),u&&n.createElement("title",null,u),t.children)};return void 0!==i?n.createElement(i.Consumer,null,(t=>e(t))):e(o)}function v(t){return b({tag:"svg",attr:{viewBox:"0 0 448 512"},child:[{tag:"path",attr:{d:"M446.7 98.6l-67.6 318.8c-5.1 22.5-18.4 28.1-37.3 17.5l-103-75.9-49.7 47.8c-5.5 5.5-10.1 10.1-20.7 10.1l7.4-104.9 190.9-172.5c8.3-7.4-1.8-11.5-12.9-4.1L117.8 284 16.2 252.2c-22.1-6.9-22.5-22.1 4.6-32.7L418.2 66.4c18.4-6.9 34.5 4.1 28.5 32.2z"},child:[]}]})(t)}}}]); \ No newline at end of file diff --git a/assets/js/563af34e.29a0e834.js b/assets/js/563af34e.29a0e834.js new file mode 100644 index 000000000..93a903964 --- /dev/null +++ b/assets/js/563af34e.29a0e834.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3890],{1410:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var n=t(4848),s=t(8453);const i={},o="StringReceiversOverlap",a={id:"detectors/StringReceiversOverlap",title:"StringReceiversOverlap",description:"A detector that finds overlapping messages between general string receivers and string receivers.",source:"@site/versioned_docs/version-0.3.0/detectors/StringReceiversOverlap.md",sourceDirName:"detectors",slug:"/detectors/StringReceiversOverlap",permalink:"/tools/misti/docs/0.3.0/detectors/StringReceiversOverlap",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/StringReceiversOverlap.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/0.3.0/detectors/ReadOnlyVariables"},next:{title:"UnboundLoops",permalink:"/tools/misti/docs/0.3.0/detectors/UnboundLoops"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const r={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h1,{id:"stringreceiversoverlap",children:"StringReceiversOverlap"}),"\n",(0,n.jsx)(r.p,{children:"A detector that finds overlapping messages between general string receivers and string receivers."}),"\n",(0,n.jsx)(r.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(r.p,{children:"Constant string receivers and general string receivers can have overlapping messages\nin which case the constant string receiver always takes precedence."}),"\n",(0,n.jsx)(r.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {\n if (msg == "foobar") { throw(1043) } // Bad: Dead code\n }\n}\n'})}),"\n",(0,n.jsx)(r.p,{children:"Use instead:"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {}\n}\n'})})]})}function p(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,r,t)=>{t.d(r,{R:()=>o,x:()=>a});var n=t(6540);const s={},i=n.createContext(s);function o(e){const r=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/566d8483.942257c5.js b/assets/js/566d8483.942257c5.js new file mode 100644 index 000000000..87fc358f6 --- /dev/null +++ b/assets/js/566d8483.942257c5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6551],{5437:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.2.2/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/0.2.2/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/index.md",tags:[],version:"0.2.2",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/0.2.2/tutorial/getting-started"}},c={},d=[{value:"Use Cases",id:"use-cases",level:2},{value:"Funding",id:"funding",level:2}];function l(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.4.4 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been ",(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"funded"})," by ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"}),". This support has enabled us to develop and maintain the tool."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5815e0d3.36349d47.js b/assets/js/5815e0d3.36349d47.js new file mode 100644 index 000000000..822600a38 --- /dev/null +++ b/assets/js/5815e0d3.36349d47.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[186],{9644:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var t=n(4848),s=n(8453);const o={},r="Configuration",l={id:"tutorial/configuration",title:"Configuration",description:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.",source:"@site/versioned_docs/version-0.2.0/tutorial/configuration.md",sourceDirName:"tutorial",slug:"/tutorial/configuration",permalink:"/tools/misti/docs/0.2.0/tutorial/configuration",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/tutorial/configuration.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.2.0/tutorial/ci-cd"},next:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.2.0/detectors"}},a={},c=[{value:"Configuration Options",id:"configuration-options",level:3},{value:"Running Misti with Configuration",id:"running-misti-with-configuration",level:2},{value:"Default Configuration File",id:"default-configuration-file",level:2},{value:"Getting Help",id:"getting-help",level:2}];function d(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(i.h1,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsx)(i.p,{children:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set."}),"\n",(0,t.jsx)(i.h3,{id:"configuration-options",children:"Configuration Options"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"detectors"}),": List of detectors to run. Each detector can be specified with a ",(0,t.jsx)(i.code,{children:"className"})," and optionally a ",(0,t.jsx)(i.code,{children:"modulePath"})," if it\u2019s a custom detector."]}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"className"})," (string, required): The class name of the detector."]}),"\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"modulePath"})," (string, optional): The file path of the detector module."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"ignored_projects"})," (array of strings, optional): List of Tact projects to ignore during analysis."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"soufflePath"})," (string, optional): Directory to save generated Souffl\xe9 files which is helpful for debugging purposes. If not set, a temporary directory will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"tactStdlibPath"})," (string, optional): Path to Tact standard library. If not set, the default stdlib from the actual Tact setup will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"unusedPrefix"}),' (string, default: "_"): Identifiers starting with this prefix won\'t be reported as unused by built-in detectors.']}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"verbosity"})," (string, optional): Verbosity level of the logs. Possible values are ",(0,t.jsx)(i.code,{children:"quiet"}),", ",(0,t.jsx)(i.code,{children:"debug"}),", and ",(0,t.jsx)(i.code,{children:"default"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(i.h2,{id:"running-misti-with-configuration",children:"Running Misti with Configuration"}),"\n",(0,t.jsx)(i.p,{children:"To run Misti with the specified configuration file, use the following command:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --config path/to/mistiConfig.json test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsx)(i.p,{children:"This command tells Misti to use the provided configuration file to analyze the specified Tact project configuration."}),"\n",(0,t.jsx)(i.h2,{id:"default-configuration-file",children:"Default Configuration File"}),"\n",(0,t.jsx)(i.p,{children:"By default, Misti enables all built-in detectors. Below is an example of the default configuration file:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-json",children:'{\n "detectorsEnabled": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n { "className": "BranchDuplicate" },\n { "className": "FieldDoubleInit" },\n { "className": "PreferAugmentedAssign" }\n ],\n "ignoredProjects": [],\n "unusedPrefix": "_",\n "verbosity": "default"\n}\n'})}),"\n",(0,t.jsxs)(i.p,{children:["All the built-in detectors are enabled by default. You can find the complete configuration schema and default configuration file on GitHub: ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/blob/master/configSchema.json",children:"configSchema.json"}),"."]}),"\n",(0,t.jsxs)(i.p,{children:["You can always dump the Misti configuration file in use by passing the ",(0,t.jsx)(i.code,{children:"--dump-config"})," option in the CLI:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --dump-config test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsxs)(i.p,{children:["If there is no Misti config in the ",(0,t.jsx)(i.code,{children:"simple"})," directory, Misti dumps the default config. This can be used to adjust it, e.g., adding or suppressing some detectors."]}),"\n",(0,t.jsx)(i.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,t.jsxs)(i.p,{children:["If you need assistance or encounter any issues, please create an issue on GitHub at ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/issues",children:"nowarp/misti"})," or ask in the ",(0,t.jsx)(i.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function u(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>l});var t=n(6540);const s={},o=t.createContext(s);function r(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/59016342.8f602791.js b/assets/js/59016342.8f602791.js new file mode 100644 index 000000000..fcd8d0764 --- /dev/null +++ b/assets/js/59016342.8f602791.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6751],{9027:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=t(4848),o=t(8453);const i={},a="UnusedOptional",r={id:"detectors/UnusedOptional",title:"UnusedOptional",description:"A detector variables and fields with unused optional modifier.",source:"@site/versioned_docs/version-0.4.0/detectors/UnusedOptional.md",sourceDirName:"detectors",slug:"/detectors/UnusedOptional",permalink:"/tools/misti/docs/0.4.0/detectors/UnusedOptional",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/UnusedOptional.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"UnboundLoops",permalink:"/tools/misti/docs/0.4.0/detectors/UnboundLoops"},next:{title:"ZeroAddress",permalink:"/tools/misti/docs/0.4.0/detectors/ZeroAddress"}},d={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"unusedoptional",children:"UnusedOptional"}),"\n",(0,s.jsx)(n.p,{children:"A detector variables and fields with unused optional modifier."}),"\n",(0,s.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"Optional"})," is a nullable value that has a special ",(0,s.jsx)(n.code,{children:"null"})," value indicating the absence\nof a value. If a developer creates an optional variable or field, he should leverage\nits functionality by accessing the ",(0,s.jsx)(n.code,{children:"null"})," value somewhere in his code. Otherwise,\nthe optional type should be removed to simplify and optimize the code."]}),"\n",(0,s.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-tact",children:"contract Test {\n a: Int?; // Bad: null value is never accessed\n init() { self.a = 42; }\n get fun getA(): Int { return self.a!!; }\n}\n"})}),"\n",(0,s.jsx)(n.p,{children:"Use instead:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-tact",children:"contract Test {\n a: Int = 42; // OK: Removed optional\n get fun getA(): Int { return self.a; }\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>r});var s=t(6540);const o={},i=s.createContext(o);function a(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5a7ecd5b.08c83086.js b/assets/js/5a7ecd5b.08c83086.js new file mode 100644 index 000000000..cb04054d9 --- /dev/null +++ b/assets/js/5a7ecd5b.08c83086.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1417],{26:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var n=t(4848),o=t(8453);const r={},d="ZeroAddress",i={id:"detectors/ZeroAddress",title:"ZeroAddress",description:"A detector that identifies uses of the zero address.",source:"@site/versioned_docs/version-0.3.0/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/0.3.0/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/ZeroAddress.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"UnboundLoops",permalink:"/tools/misti/docs/0.3.0/detectors/UnboundLoops"},next:{title:"Contributing",permalink:"/tools/misti/docs/0.3.0/hacking/contributing"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"zeroaddress",children:"ZeroAddress"}),"\n",(0,n.jsx)(s.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(s.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(s.p,{children:"Use instead:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initialization.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>d,x:()=>i});var n=t(6540);const o={},r=n.createContext(o);function d(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5c07db7d.dbb32bd9.js b/assets/js/5c07db7d.dbb32bd9.js new file mode 100644 index 000000000..e8b854c60 --- /dev/null +++ b/assets/js/5c07db7d.dbb32bd9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4575],{342:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=n(4848),a=n(8453);const r={},s="InheritedStateMutation",o={id:"detectors/InheritedStateMutation",title:"InheritedStateMutation",description:"An optional detector that highlights all instances where inherited trait variables",source:"@site/versioned_docs/version-0.5/detectors/InheritedStateMutation.md",sourceDirName:"detectors",slug:"/detectors/InheritedStateMutation",permalink:"/tools/misti/docs/detectors/InheritedStateMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/InheritedStateMutation.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/detectors/FieldDoubleInit"},next:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/detectors/NeverAccessedVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"inheritedstatemutation",children:"InheritedStateMutation"}),"\n",(0,i.jsx)(t.p,{children:"An optional detector that highlights all instances where inherited trait variables\nare directly modified."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Traits should provide setter methods to ensure that invariants related to their\nstate are preserved. Directly modifying trait variables (e.g., ",(0,i.jsx)(t.code,{children:"self.traitVar = 42"}),")\ncan violate these invariants, leading to potential bugs or security vulnerabilities.\nThis detector warns when such direct modifications occur, prompting further review\nby auditors."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"trait T {\n balance: Int;\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.balance = 100; // Suspicious: Highlighted by the detector\n }\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:'trait T {\n balance: Int;\n fun setBalance(newBalance: Int) {\n require(newBalance > 0, "balance cannot be negative"); // Invariant check\n self.balance = newBalance;\n }\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.setBalance(100); // OK: Invariant preserved\n }\n}\n'})})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var i=n(6540);const a={},r=i.createContext(a);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/5e95c892.0afa16e4.js b/assets/js/5e95c892.0afa16e4.js new file mode 100644 index 000000000..50422e8a1 --- /dev/null +++ b/assets/js/5e95c892.0afa16e4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9647],{7121:(e,r,s)=>{s.r(r),s.d(r,{default:()=>o});s(6540);var u=s(4164),a=s(1003),n=s(7559),t=s(2831),c=s(781),i=s(4848);function o(e){return(0,i.jsx)(a.e3,{className:(0,u.A)(n.G.wrapper.docsPages),children:(0,i.jsx)(c.A,{children:(0,t.v)(e.route.routes)})})}}}]); \ No newline at end of file diff --git a/assets/js/5ec2195c.a723ab4e.js b/assets/js/5ec2195c.a723ab4e.js new file mode 100644 index 000000000..779980d03 --- /dev/null +++ b/assets/js/5ec2195c.a723ab4e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9708],{1484:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="Constant Address",a={id:"detectors/ConstantAddress",title:"Constant Address",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/versioned_docs/version-0.2.1/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/0.2.1/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/ConstantAddress.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Zero Address",permalink:"/tools/misti/docs/0.2.1/detectors/ZeroAddress"},next:{title:"Branch Duplicate",permalink:"/tools/misti/docs/0.2.1/detectors/BranchDuplicate"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constant-address",children:"Constant Address"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/602c5d84.e34a6ec9.js b/assets/js/602c5d84.e34a6ec9.js new file mode 100644 index 000000000..db395cdb5 --- /dev/null +++ b/assets/js/602c5d84.e34a6ec9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4719],{8930:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var n=i(4848),o=i(8453);const s={},a="FieldDoubleInit",l={id:"detectors/FieldDoubleInit",title:"FieldDoubleInit",description:"A detector that highlights cases where a field is initialized both in the",source:"@site/versioned_docs/version-0.4.0/detectors/FieldDoubleInit.md",sourceDirName:"detectors",slug:"/detectors/FieldDoubleInit",permalink:"/tools/misti/docs/0.4.0/detectors/FieldDoubleInit",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/FieldDoubleInit.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"FalseCondition",permalink:"/tools/misti/docs/0.4.0/detectors/FalseCondition"},next:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/0.4.0/detectors/InheritedStateMutation"}},r={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"fielddoubleinit",children:"FieldDoubleInit"}),"\n",(0,n.jsxs)(t.p,{children:["A detector that highlights cases where a field is initialized both in the\n",(0,n.jsx)(t.code,{children:"init"})," function and at the point of definition."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["Double initialization of fields can either be a programmer's mistake or simply\na waste of gas. It is always preferred to initialize values in the field declaration\nif they have a compile-time evaluatable default value, or in the ",(0,n.jsx)(t.code,{children:"init"})," function if\nthey must be initialized dynamically."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 0; // Bad\n init(x: Int) { self.a = x }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int; // Fixed\n init(x: Int) { self.a = x }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>l});var n=i(6540);const o={},s=n.createContext(o);function a(e){const t=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),n.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/61c19607.94c232da.js b/assets/js/61c19607.94c232da.js new file mode 100644 index 000000000..5fee2f5e6 --- /dev/null +++ b/assets/js/61c19607.94c232da.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5794],{8628:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=n(4848),s=n(8453);const r={},l="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/versioned_docs/version-0.2.2/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/0.2.2/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/tutorial/getting-started.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/0.2.2/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.2.2/tutorial/ci-cd"}},a={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,i.jsx)(t.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,i.jsx)(t.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsx)(t.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Git"}),"\n",(0,i.jsx)(t.li,{children:"Yarn"}),"\n",(0,i.jsx)(t.li,{children:"Node.js"}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsxs)(t.p,{children:["Misti is distributed via npm and should be added to your Tact project ",(0,i.jsx)(t.a,{href:"https://github.com/tact-lang/tact?tab=readme-ov-file#installation",children:"in the same way"})," as Tact itself:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"yarn add @nowarp/misti\n"})}),"\n",(0,i.jsx)(t.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,i.jsx)(t.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,i.jsx)(t.p,{children:"To install the latest development version you should:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:["Clone Misti: ",(0,i.jsx)(t.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,i.jsxs)(t.li,{children:["Build it: ",(0,i.jsx)(t.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,i.jsxs)(t.li,{children:["Use it in your Tact project: ",(0,i.jsx)(t.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,i.jsx)(t.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"npx misti test/projects/simple/tactConfig.json\n"})}),"\n",(0,i.jsx)(t.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,i.jsxs)(t.p,{children:["You can also add a script to your ",(0,i.jsx)(t.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "npx misti test/projects/simple/tactConfig.json"\n }\n}\n'})}),"\n",(0,i.jsx)(t.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsxs)(t.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,i.jsx)(t.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>l,x:()=>o});var i=n(6540);const s={},r=i.createContext(s);function l(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6362ac9f.fb178849.js b/assets/js/6362ac9f.fb178849.js new file mode 100644 index 000000000..4c24e1e70 --- /dev/null +++ b/assets/js/6362ac9f.fb178849.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9431],{2219:(t,e,i)=>{i.r(e),i.d(e,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var n=i(4848),s=i(8453);const r={},o="Using Misti with Blueprint",l={id:"tutorial/blueprint",title:"Using Misti with Blueprint",description:"Blueprint is a platform to compile, test, and deploy contracts on the TON blockchain. It is quite similar to Hardhat and Truffle for Ethereum.",source:"@site/versioned_docs/version-0.4.0/tutorial/blueprint.md",sourceDirName:"tutorial",slug:"/tutorial/blueprint",permalink:"/tools/misti/docs/0.4.0/tutorial/blueprint",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/tutorial/blueprint.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Configuration",permalink:"/tools/misti/docs/0.4.0/tutorial/configuration"},next:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.4.0/detectors"}},a={},c=[{value:"Getting Started",id:"getting-started",level:2},{value:"Usage",id:"usage",level:2}];function d(t){const e={a:"a",code:"code",h1:"h1",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",...(0,s.R)(),...t.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"using-misti-with-blueprint",children:"Using Misti with Blueprint"}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.a,{href:"https://github.com/ton-org/blueprint/",children:"Blueprint"})," is a platform to compile, test, and deploy contracts on the TON blockchain. It is quite similar to Hardhat and Truffle for Ethereum."]}),"\n",(0,n.jsxs)(e.p,{children:["There is a ",(0,n.jsx)(e.a,{href:"https://github.com/nowarp/blueprint-misti",children:"blueprint-misti"})," plugin that can be added to a Blueprint configuration. It adds the ",(0,n.jsx)(e.code,{children:"blueprint misti"})," command, which runs the static analyzer over the selected Blueprint project."]}),"\n",(0,n.jsx)(e.p,{children:"This page describes how to use it."}),"\n",(0,n.jsx)(e.h2,{id:"getting-started",children:"Getting Started"}),"\n",(0,n.jsxs)(e.ol,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.a,{href:"https://souffle-lang.github.io/install",children:"Install Souffl\xe9"})," to use all detectors provided by Misti."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsx)(e.p,{children:"Add this plugin as a dependency of your Blueprint project:"}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"yarn add @tact-lang/compiler\nyarn add @nowarp/blueprint-misti\n"})}),"\n",(0,n.jsxs)(e.ol,{start:"3",children:["\n",(0,n.jsxs)(e.li,{children:["Add this configuration to ",(0,n.jsx)(e.code,{children:"blueprint.config.ts"}),":"]}),"\n"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-ts",children:"import { MistiPlugin } from '@nowarp/blueprint-misti';\nexport const config = {\n plugins: [\n new MistiPlugin(),\n ],\n};\n"})}),"\n",(0,n.jsx)(e.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"Run the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"yarn blueprint misti\n"})}),"\n",(0,n.jsx)(e.p,{children:"It will run the analysis of the available project, if there is one, or show an interactive window to select a project:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"img",src:i(1547).A+"",width:"493",height:"96"})}),"\n",(0,n.jsxs)(e.p,{children:["You could also pass the ",(0,n.jsx)(e.a,{href:"/tools/misti/docs/0.4.0/tutorial/cli",children:"supported CLI options"})," for Misti, for example:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"yarn blueprint misti --all-detectors\n"})}),"\n",(0,n.jsx)(e.p,{children:"Or you can even pass the path to the contract directly:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"yarn blueprint misti path/to/my/contract.tact\n"})}),"\n",(0,n.jsxs)(e.p,{children:["If you have any problems, feel free to reach out to us in the ",(0,n.jsx)(e.a,{href:"https://t.me/misti_dev",children:"Misti discussion group"}),"."]})]})}function h(t={}){const{wrapper:e}={...(0,s.R)(),...t.components};return e?(0,n.jsx)(e,{...t,children:(0,n.jsx)(d,{...t})}):d(t)}},1547:(t,e,i)=>{i.d(e,{A:()=>n});const n=i.p+"assets/images/blueprint-select-project-b8656fa4266c0c7923d6b67c7f5950e6.png"},8453:(t,e,i)=>{i.d(e,{R:()=>o,x:()=>l});var n=i(6540);const s={},r=n.createContext(s);function o(t){const e=n.useContext(r);return n.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function l(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(s):t.components||s:o(t.components),n.createElement(r.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/63a541b5.cf91b4ad.js b/assets/js/63a541b5.cf91b4ad.js new file mode 100644 index 000000000..5d00abc01 --- /dev/null +++ b/assets/js/63a541b5.cf91b4ad.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5122],{1105:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=n(4848),o=n(8453);const i={},a="ArgCopyMutation",r={id:"detectors/ArgCopyMutation",title:"ArgCopyMutation",description:"A detector that highlights cases where function argument mutations are ineffective",source:"@site/versioned_docs/version-0.3.1/detectors/ArgCopyMutation.md",sourceDirName:"detectors",slug:"/detectors/ArgCopyMutation",permalink:"/tools/misti/docs/0.3.1/detectors/ArgCopyMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/ArgCopyMutation.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.3.1/detectors"},next:{title:"AsmIsUsed",permalink:"/tools/misti/docs/0.3.1/detectors/AsmIsUsed"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"argcopymutation",children:"ArgCopyMutation"}),"\n",(0,s.jsx)(t.p,{children:"A detector that highlights cases where function argument mutations are ineffective\ndue to call-by-value semantics in Tact."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"In Tact, function arguments are passed by value, meaning that any mutations applied\nto these arguments will only affect the local copy of the variable within the function.\nSuch mutations are unobservable outside the function, except for potentially\nincreasing gas consumption or causing exceptions."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun addEntry(m: map ) {\n m.set(1, 10); // Bad: Mutating the copy\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun addEntry() {\n self.m.set(1, 10); // OK: Changing contract's state\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Alternatively, you could redesign the method:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun generateNewValue(): Int {\n // ... produce new value for the map\n return self.nextValue + 1;\n}\n\nm.set(self.nextKey, self.generateNewValue()); // OK\n"})})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var s=n(6540);const o={},i=s.createContext(o);function a(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/63bb535a.d93af67f.js b/assets/js/63bb535a.d93af67f.js new file mode 100644 index 000000000..4675c9dff --- /dev/null +++ b/assets/js/63bb535a.d93af67f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3684],{3494:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>d,metadata:()=>o,toc:()=>l});var r=n(4848),s=n(8453);const d={},i="PreferredStdlibApi",o={id:"detectors/PreferredStdlibApi",title:"PreferredStdlibApi",description:"An optional detector that flags the use of advanced functions from the standard library.",source:"@site/versioned_docs/version-0.4.0/detectors/PreferredStdlibApi.md",sourceDirName:"detectors",slug:"/detectors/PreferredStdlibApi",permalink:"/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/PreferredStdlibApi.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign"},next:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables"}},a={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"preferredstdlibapi",children:"PreferredStdlibApi"}),"\n",(0,r.jsx)(t.p,{children:"An optional detector that flags the use of advanced functions from the standard library."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"Auditors should pay extra attention to these functions, as incorrect usage can\nlead to subtle bugs. Safer stdlib alternatives should be preferred in the code."}),"\n",(0,r.jsx)(t.p,{children:"Supported functions:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:["Use ",(0,r.jsx)(t.code,{children:"send"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativesendmessage",children:(0,r.jsx)(t.code,{children:"nativeSendMessage"})})]}),"\n",(0,r.jsxs)(t.li,{children:["Prefer ",(0,r.jsx)(t.code,{children:"randomInt"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativerandom",children:(0,r.jsx)(t.code,{children:"nativeRandom"})})]}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"let pkg: Slice = msg.transfer;\nlet _seqno: Int = pkg.loadInt(32);\nlet mode: Int = pkg.loadInt(8);\nlet body: Cell = pkg.loadRef();\n// Bad: prefer `send` to avoid low-level manipulation of Slice\nnativeSendMessage(body, mode);\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// Safer: More explicit definition of the send operation\nsend(SendParameters{ value: amount,\n to: self.owner,\n mode: mode,\n body: beginCell().endCell() });\n"})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(6540);const s={},d=r.createContext(s);function i(e){const t=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(d.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6696f09b.57cd0d6b.js b/assets/js/6696f09b.57cd0d6b.js new file mode 100644 index 000000000..2f7b7493f --- /dev/null +++ b/assets/js/6696f09b.57cd0d6b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9417],{1469:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>d,default:()=>g,frontMatter:()=>l,metadata:()=>a,toc:()=>r});var n=t(4848),s=t(8453);const l={},d="DumpCfg",a={id:"tools/DumpCfg",title:"DumpCfg",description:"Misti provides a feature to dump the Control Flow Graph (CFG) in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts.",source:"@site/versioned_docs/version-0.4.0/tools/DumpCfg.md",sourceDirName:"tools",slug:"/tools/DumpCfg",permalink:"/tools/misti/docs/0.4.0/tools/DumpCfg",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/tools/DumpCfg.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpAst",permalink:"/tools/misti/docs/0.4.0/tools/DumpAst"},next:{title:"DumpConfig",permalink:"/tools/misti/docs/0.4.0/tools/DumpConfig"}},o={},r=[{value:"Usage",id:"usage",level:2},{value:"Working with Mermaid",id:"working-with-mermaid",level:2},{value:"Working with Graphviz",id:"working-with-graphviz",level:2},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function I(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"dumpcfg",children:"DumpCfg"}),"\n",(0,n.jsxs)(e.p,{children:["Misti provides a feature to dump the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Control-flow_graph",children:"Control Flow Graph (CFG)"})," in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts."]}),"\n",(0,n.jsx)(e.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Mermaid format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti -t "DumpCfg:format=mmd" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Graphviz DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti -t "DumpCfg:format=dot" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti -t "DumpCfg:format=json" \n'})}),"\n",(0,n.jsxs)(e.p,{children:["You could also include Tact standard library functions to the dump adding ",(0,n.jsx)(e.code,{children:"dumpStdlib=true"})," to the ",(0,n.jsx)(e.code,{children:"DumpCfg"})," options."]}),"\n",(0,n.jsx)(e.h2,{id:"working-with-mermaid",children:"Working with Mermaid"}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.a,{href:"https://mermaid.js.org",children:"Mermaid"})," is a JavaScript-based diagramming and charting tool that allows you to create dynamic visualizations, such as flowcharts and sequence diagrams, using a simple syntax. It is integrated into various platforms, including Visual Studio Code."]}),"\n",(0,n.jsxs)(e.p,{children:["To view Mermaid diagrams in Visual Studio Code, you can use the ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid",children:"Markdown Preview Mermaid Support"})," extension. You can also use the ",(0,n.jsx)(e.a,{href:"https://mermaid.live",children:"Mermaid Live Editor"})," to preview your diagrams online."]}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Mermaid format using Misti, run the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti -t "DumpCfg:format=mermaid" \n'})}),"\n",(0,n.jsx)(e.p,{children:"The output can be viewed directly in the VS Code plugin or the online editor."}),"\n",(0,n.jsx)(e.h2,{id:"working-with-graphviz",children:"Working with Graphviz"}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti -t "DumpCfg:format=dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-tact",children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allow you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for understanding the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"Mermaid Dumps"}),": The Mermaid format allows you to generate flowcharts that are easy to read and share. They offer a convenient way to visualize the CFG without requiring additional tools, as they can be directly embedded in markdown files or viewed in the Mermaid Live Editor."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function g(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(I,{...i})}):I(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>d,x:()=>a});var n=t(6540);const s={},l=n.createContext(s);function d(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function a(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:d(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/6934ebe4.7bcf9574.js b/assets/js/6934ebe4.7bcf9574.js new file mode 100644 index 000000000..e85bbde5d --- /dev/null +++ b/assets/js/6934ebe4.7bcf9574.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3175],{4919:(t,n,e)=>{e.r(n),e.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>u});var i=e(4848),o=e(8453);const s={},r="Integrating Misti into CI/CD",c={id:"tutorial/ci-cd",title:"Integrating Misti into CI/CD",description:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.",source:"@site/versioned_docs/version-0.3.0/tutorial/ci-cd.md",sourceDirName:"tutorial",slug:"/tutorial/ci-cd",permalink:"/tools/misti/docs/0.3.0/tutorial/ci-cd",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/tutorial/ci-cd.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Getting Started",permalink:"/tools/misti/docs/0.3.0/tutorial/getting-started"},next:{title:"Command-Line Interface",permalink:"/tools/misti/docs/0.3.0/tutorial/cli"}},a={},u=[{value:"GitHub Actions",id:"github-actions",level:2}];function l(t){const n={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,o.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"integrating-misti-into-cicd",children:"Integrating Misti into CI/CD"}),"\n",(0,i.jsx)(n.p,{children:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle."}),"\n",(0,i.jsx)(n.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(n.p,{children:"To integrate Misti into your GitHub Actions workflow, you need to add a command that runs Misti as part of your CI process. Here's how you can do it:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"1. Open your GitHub repository"})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"2. Create or edit the GitHub Actions workflow YAML file"})}),"\n",(0,i.jsxs)(n.p,{children:["It could be located at e.g., ",(0,i.jsx)(n.code,{children:".github/workflows/main.yml"}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"3. Add the step to run Misti to your YAML file"})}),"\n",(0,i.jsx)(n.p,{children:"For example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"name: Run Misti\non: [push, pull_request]\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n\n - name: Install dependencies\n run: npm install\n\n - name: Run Misti\n run: npx misti /path/to/your/tact.config.json\n"})}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"npx misti /path/to/your/tact.config.json"})," command will run Misti against your project. If Misti detects any issues that are not suppressed by your configuration, it will return a non-zero exit code, causing the CI pipeline to fail."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"4. Adjusting the Misti Configuration"})}),"\n",(0,i.jsxs)(n.p,{children:["If you find that Misti is too noisy (e.g., detecting issues that are not relevant to your project), you can adjust your Misti configuration file to suppress those warnings. Refer to the ",(0,i.jsx)(n.a,{href:"./configuration",children:"Configuration"})," section for more details on how to customize your settings."]})]})}function d(t={}){const{wrapper:n}={...(0,o.R)(),...t.components};return n?(0,i.jsx)(n,{...t,children:(0,i.jsx)(l,{...t})}):l(t)}},8453:(t,n,e)=>{e.d(n,{R:()=>r,x:()=>c});var i=e(6540);const o={},s=i.createContext(o);function r(t){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(n):{...n,...t}}),[n,t])}function c(t){let n;return n=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:r(t.components),i.createElement(s.Provider,{value:n},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/693ffdbc.20a90ba4.js b/assets/js/693ffdbc.20a90ba4.js new file mode 100644 index 000000000..d6d50b426 --- /dev/null +++ b/assets/js/693ffdbc.20a90ba4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1204],{7567:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.2.2/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.2.2/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/hacking/souffle.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.2.2/hacking/design"},next:{title:"Tools",permalink:"/tools/misti/docs/0.2.2/hacking/tools"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is detailed ",(0,t.jsx)(n.a,{href:"https://nowarp.github.io/docs/misti/api/modules/internals_souffle.html",children:"here"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6afbdc7c.8a6b1736.js b/assets/js/6afbdc7c.8a6b1736.js new file mode 100644 index 000000000..2ca92d475 --- /dev/null +++ b/assets/js/6afbdc7c.8a6b1736.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4701],{6400:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var n=i(4848),o=i(8453);const r={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.5/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/hacking/custom-detector.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Developing Misti",permalink:"/tools/misti/docs/hacking/developing-misti"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Creating a Detector",id:"creating-a-detector",level:2},{value:"Testing the detector",id:"testing-the-detector",level:3},{value:"Saving the configuration",id:"saving-the-configuration",level:3},{value:"Example Detectors",id:"example-detectors",level:2}];function h(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,n.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,n.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,n.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,n.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,n.jsx)(t.h2,{id:"creating-a-detector",children:"Creating a Detector"}),"\n",(0,n.jsxs)(t.p,{children:["You can create a new custom detector by executing Misti with the ",(0,n.jsx)(t.code,{children:"--new-detector"})," option: ",(0,n.jsx)(t.code,{children:"misti --new-detector implicitInit"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["This will create the ",(0,n.jsx)(t.code,{children:"implicitInit.ts"})," file, which contains the template code for writing your own custom detector logic leveraging the Misti API."]}),"\n",(0,n.jsx)(t.p,{children:"Here's an example of how to implement a custom detector using Misti API:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-typescript",children:'import { ASTDetector } from "@nowarp/misti/dist/detectors/detector";\nimport { CompilationUnit } from "@nowarp/misti/dist/internals/ir";\nimport {\n MistiTactWarning,\n Severity,\n} from "@nowarp/misti/dist/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that doesn\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends ASTDetector {\n severity = Severity.INFO;\n\n async check(cu: CompilationUnit): Promise {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = this.makeWarning(\n `Contract ${contract.name} doesn\'t define an init function`,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactWarning[]);\n }\n}\n\n'})}),"\n",(0,n.jsx)(t.h3,{id:"testing-the-detector",children:"Testing the detector"}),"\n",(0,n.jsxs)(t.p,{children:["To run Misti with only your new detector, use the ",(0,n.jsx)(t.code,{children:"--detectors"})," option, specifying the path to the detector and the Detector class name: ",(0,n.jsx)(t.code,{children:"misti path/to/your/tact.config.json --detectors path/to/implicitInit.ts:ImplicitInit"}),"."]}),"\n",(0,n.jsxs)(t.p,{children:["That's a good way to test the detector on the first run. You could also use the ",(0,n.jsx)(t.code,{children:"--verbose"})," CLI option and set the environment variable ",(0,n.jsx)(t.code,{children:"MISTI_TRACE=1"})," to facilitate debugging."]}),"\n",(0,n.jsx)(t.h3,{id:"saving-the-configuration",children:"Saving the configuration"}),"\n",(0,n.jsx)(t.p,{children:"After testing the detector, you can specify it in your configuration to enable it in future runs. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{children:'{\n "detectors": [\n // Other detectors...\n { "className": "ImplicitInit", "modulePath": "ImplicitInit.ts" }\n ],\n}\n'})}),"\n",(0,n.jsxs)(t.p,{children:["After this, you could run Misti specifying a path to a custom configuration ",(0,n.jsx)(t.code,{children:"misti --config path/to/misti.config.json path/to/your/tact.config.json"}),"."]}),"\n",(0,n.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,n.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,n.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(h,{...e})}):h(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>c});var n=i(6540);const o={},r=n.createContext(o);function s(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6bb9ad58.94c990fe.js b/assets/js/6bb9ad58.94c990fe.js new file mode 100644 index 000000000..51f337ced --- /dev/null +++ b/assets/js/6bb9ad58.94c990fe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9448],{693:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>c});var s=i(4848),l=i(8453);const t={},o="Command-Line Interface",r={id:"tutorial/cli",title:"Command-Line Interface",description:"CLI Options",source:"@site/versioned_docs/version-0.5/tutorial/cli.md",sourceDirName:"tutorial",slug:"/tutorial/cli",permalink:"/tools/misti/docs/tutorial/cli",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tutorial/cli.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"CI/CD Integration",permalink:"/tools/misti/docs/tutorial/ci-cd"},next:{title:"Configuration",permalink:"/tools/misti/docs/tutorial/configuration"}},d={},c=[{value:"CLI Options",id:"cli-options",level:2},{value:" -t, --tools <className[:key=value...]>
",id:"-t---tools-classnamekeyvalue",level:3},{value:"--output-path <PATH>
",id:"--output-path-path",level:3},{value:"--list-tools
",id:"--list-tools",level:3},{value:"-o, --output-format <json|plain>
",id:"-o---output-format-jsonplain",level:3},{value:"-C, --no-colors
",id:"-c---no-colors",level:3},{value:"--souffle-binary <PATH>
",id:"--souffle-binary-path",level:3},{value:"--souffle-path <PATH>
",id:"--souffle-path-path",level:3},{value:"--souffle-verbose
",id:"--souffle-verbose",level:3},{value:"--tact-stdlib-path <PATH>
",id:"--tact-stdlib-path-path",level:3},{value:"-v, --verbose
",id:"-v---verbose",level:3},{value:"-q, --quiet
",id:"-q---quiet",level:3},{value:"-m, --min-severity <info|low|medium|high|critical>
",id:"-m---min-severity-infolowmediumhighcritical",level:3},{value:"-de, --enabled-detectors <name|path:name>
",id:"-de---enabled-detectors-namepathname",level:3},{value:"-dd, --disabled-detectors <names>
",id:"-dd---disabled-detectors-names",level:3},{value:"-A, --all-detectors
",id:"-a---all-detectors",level:3},{value:"-c, --config <PATH>
",id:"-c---config-path",level:3},{value:"--new-detector <PATH>
",id:"--new-detector-path",level:3},{value:"Exit Codes",id:"exit-codes",level:2}];function a(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"command-line-interface",children:"Command-Line Interface"}),"\n",(0,s.jsx)(n.h2,{id:"cli-options",children:"CLI Options"}),"\n",(0,s.jsx)(n.p,{children:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each."}),"\n",(0,s.jsx)(n.h3,{id:"-t---tools-classnamekeyvalue",children:(0,s.jsx)(n.code,{children:"-t, --tools"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Specifies a tool to enable with optional configuration. This option can be used multiple times."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Example"}),": ",(0,s.jsx)(n.code,{children:'-t "DumpCfg:format=dot"'})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--output-path-path",children:(0,s.jsx)(n.code,{children:"--output-path "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Specifies the directory to save warnings or output generated by tools. If ",(0,s.jsx)(n.code,{children:" "})," is ",(0,s.jsx)(n.code,{children:"-"}),", then the output is sent to stdout."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"-"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--list-tools",children:(0,s.jsx)(n.code,{children:"--list-tools"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Lists available tools and their configuration options."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-o---output-format-jsonplain",children:(0,s.jsx)(n.code,{children:"-o, --output-format "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Sets the output format for all tools and warnings (either JSON or plain text)."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"plain"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-c---no-colors",children:(0,s.jsx)(n.code,{children:"-C, --no-colors"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Disables ANSI colors in the output."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--souffle-binary-path",children:(0,s.jsx)(n.code,{children:"--souffle-binary "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Specifies the path to the Souffl\xe9 binary."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:'"souffle"'})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--souffle-path-path",children:(0,s.jsx)(n.code,{children:"--souffle-path "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Specifies the directory to save generated Souffl\xe9 files."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:'"/tmp/misti/souffle"'})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--souffle-verbose",children:(0,s.jsx)(n.code,{children:"--souffle-verbose"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Generates human-readable, more verbose Souffl\xe9 files."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--tact-stdlib-path-path",children:(0,s.jsx)(n.code,{children:"--tact-stdlib-path "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Specifies the path to the Tact standard library."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-v---verbose",children:(0,s.jsx)(n.code,{children:"-v, --verbose"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Enables verbose output."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-q---quiet",children:(0,s.jsx)(n.code,{children:"-q, --quiet"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Suppresses all output."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-m---min-severity-infolowmediumhighcritical",children:(0,s.jsx)(n.code,{children:"-m, --min-severity "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Sets the minimum level of severity to report."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"info"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-de---enabled-detectors-namepathname",children:(0,s.jsx)(n.code,{children:"-de, --enabled-detectors "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": A comma-separated list of detectors to enable."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Argument Validation"}),": Requires a non-empty list of detector names."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-dd---disabled-detectors-names",children:(0,s.jsx)(n.code,{children:"-dd, --disabled-detectors "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": A comma-separated list of detector names to disable."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Argument Validation"}),": Requires a non-empty list of detector names."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-a---all-detectors",children:(0,s.jsx)(n.code,{children:"-A, --all-detectors"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Enables all available built-in detectors."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"-c---config-path",children:(0,s.jsx)(n.code,{children:"-c, --config "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Specifies the path to the Misti configuration file."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"--new-detector-path",children:(0,s.jsx)(n.code,{children:"--new-detector "})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Description"}),": Creates a new custom detector at the specified path."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"exit-codes",children:"Exit Codes"}),"\n",(0,s.jsx)(n.p,{children:"Misti returns different exit codes depending on the execution result:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"0"}),": Successful execution with no warnings or errors."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"1"}),": Warnings were reported."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"2"}),": Execution failed due to an internal or execution error."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>r});var s=i(6540);const l={},t=s.createContext(l);function o(e){const n=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:o(e.components),s.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6bfbb660.67f004b0.js b/assets/js/6bfbb660.67f004b0.js new file mode 100644 index 000000000..d634815ee --- /dev/null +++ b/assets/js/6bfbb660.67f004b0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5173],{2963:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={},r="Integrating Misti into CI/CD",a={id:"tutorial/ci-cd",title:"Integrating Misti into CI/CD",description:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.",source:"@site/versioned_docs/version-0.5/tutorial/ci-cd.md",sourceDirName:"tutorial",slug:"/tutorial/ci-cd",permalink:"/tools/misti/docs/tutorial/ci-cd",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tutorial/ci-cd.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Getting Started",permalink:"/tools/misti/docs/tutorial/getting-started"},next:{title:"Command-Line Interface",permalink:"/tools/misti/docs/tutorial/cli"}},c={},l=[{value:"Using Tact Template",id:"using-tact-template",level:2},{value:"GitHub Actions",id:"github-actions",level:2},{value:"Integration with Blueprint Projects",id:"integration-with-blueprint-projects",level:2}];function u(t){const e={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"integrating-misti-into-cicd",children:"Integrating Misti into CI/CD"}),"\n",(0,i.jsx)(e.p,{children:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle."}),"\n",(0,i.jsx)(e.h2,{id:"using-tact-template",children:"Using Tact Template"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.a,{href:"https://github.com/tact-lang/tact-template",children:(0,i.jsx)(e.code,{children:"tact-template"})})," is a template project for Tact. If you started your project from this template, Misti is already installed in ",(0,i.jsx)(e.a,{href:"https://github.com/tact-lang/tact-template/tree/main/.github/workflows",children:"the CI"}),". You also have the ",(0,i.jsx)(e.code,{children:"yarn lint"})," command available in your ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsx)(e.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(e.p,{children:"To integrate Misti into your GitHub Actions workflow, you need to add a command that runs Misti as part of your CI process. Here's how you can do it:"}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"1. Open your GitHub repository"})}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"2. Create or edit the GitHub Actions workflow YAML file"})}),"\n",(0,i.jsxs)(e.p,{children:["It could be located at e.g., ",(0,i.jsx)(e.code,{children:".github/workflows/ci.yml"}),"."]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"3. Add the step to run Misti to your YAML file"})}),"\n",(0,i.jsx)(e.p,{children:"For example:"}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-yaml",children:'name: CI\n\non:\n push:\n branches: [ "main" ]\n pull_request:\n branches: [ "main" ]\n workflow_dispatch:\n\njobs:\n test:\n strategy:\n fail-fast: false\n matrix:\n node-version: [22]\n os: [ubuntu-latest]\n runs-on: ${{ matrix.os }}\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n\n - name: Install Souffl\xe9 on Ubuntu\n if: matrix.os == \'ubuntu-latest\'\n run: |\n sudo wget https://souffle-lang.github.io/ppa/souffle-key.public -O /usr/share/keyrings/souffle-archive-keyring.gpg\n echo "deb [signed-by=/usr/share/keyrings/souffle-archive-keyring.gpg] https://souffle-lang.github.io/ppa/ubuntu/ stable main" | sudo tee /etc/apt/sources.list.d/souffle.list\n sudo apt update\n sudo apt install souffle\n\n - name: Setup Node.js\n uses: actions/setup-node@v3\n with:\n node-version: ${{ matrix.node-version }}\n\n - name: Install dependencies\n run: yarn install\n\n - name: Run Misti\n run: yarn misti --min-severity medium /path/to/your/tact.config.json\n'})}),"\n",(0,i.jsxs)(e.p,{children:["The ",(0,i.jsx)(e.code,{children:"yarn misti --min-severity medium /path/to/your/tact.config.json"})," command will run Misti against your project. If Misti detects any issues that are not suppressed by your configuration, it will return a non-zero exit code, causing the CI pipeline to fail."]}),"\n",(0,i.jsxs)(e.p,{children:["The ",(0,i.jsx)(e.code,{children:"--min-severity medium"})," will filter out low-priority warnings. You can always run Misti with all the detectors enabled locally in order to get the most comprehensive warnings output: ",(0,i.jsx)(e.code,{children:"yarn misti --all-detectors /path/to/your/tact.config.json"})]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"4. Adjusting the Misti Configuration"})}),"\n",(0,i.jsxs)(e.p,{children:["If you find that Misti is too noisy (e.g., detecting issues that are not relevant to your project), you can adjust your Misti configuration file to suppress those warnings. Refer to the ",(0,i.jsx)(e.a,{href:"./configuration",children:"Configuration"})," section for more details on how to customize your settings."]}),"\n",(0,i.jsx)(e.h2,{id:"integration-with-blueprint-projects",children:"Integration with Blueprint Projects"}),"\n",(0,i.jsx)(e.p,{children:"To add Misti to the CI for your Blueprint project, follow these steps:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.a,{href:"/tools/misti/docs/tutorial/blueprint",children:["Install ",(0,i.jsx)(e.code,{children:"blueprint-misti"})]}),"."]}),"\n",(0,i.jsxs)(e.li,{children:["Follow the steps to set up the GitHub action above, but replace the ",(0,i.jsx)(e.code,{children:"yarn misti"})," command with ",(0,i.jsx)(e.code,{children:"npx blueprint misti --blueprint-project "}),", where ",(0,i.jsx)(e.code,{children:" "})," is the name of the project displayed when you run ",(0,i.jsx)(e.code,{children:"npx blueprint build"}),"."]}),"\n"]})]})}function d(t={}){const{wrapper:e}={...(0,s.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(u,{...t})}):u(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(t){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(s):t.components||s:r(t.components),i.createElement(o.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/6f277b0e.89006761.js b/assets/js/6f277b0e.89006761.js new file mode 100644 index 000000000..37aa85745 --- /dev/null +++ b/assets/js/6f277b0e.89006761.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6340],{701:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var t=o(4848),s=o(8453);const i={},r="Unbound Loops",a={id:"detectors/UnboundLoops",title:"Unbound Loops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.2.2/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.2.2/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/UnboundLoops.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables"},next:{title:"Zero Address",permalink:"/tools/misti/docs/0.2.2/detectors/ZeroAddress"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"unbound-loops",children:"Unbound Loops"}),"\n",(0,t.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,t.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,t.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Unexpected Behavior: Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."}),"\n",(0,t.jsx)(n.li,{children:"Out-of-gas Attacks: Continuous looping without termination can lead to out-of-gas attacks."}),"\n",(0,t.jsx)(n.li,{children:"DoS Attacks: Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Use instead:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var t=o(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/6f60ccd2.91c6f358.js b/assets/js/6f60ccd2.91c6f358.js new file mode 100644 index 000000000..ec4a38093 --- /dev/null +++ b/assets/js/6f60ccd2.91c6f358.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4861],{3316:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>d});var r=n(4848),i=n(8453);const a={},s="ReadOnlyVariables",l={id:"detectors/ReadOnlyVariables",title:"ReadOnlyVariables",description:"A detector that identifies read-only variables and fields.",source:"@site/versioned_docs/version-0.3.1/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/ReadOnlyVariables.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi"},next:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap"}},o={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"readonlyvariables",children:"ReadOnlyVariables"}),"\n",(0,r.jsx)(t.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the analyzer highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var r=n(6540);const i={},a=r.createContext(i);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/719e5d48.46b8f441.js b/assets/js/719e5d48.46b8f441.js new file mode 100644 index 000000000..3d653748e --- /dev/null +++ b/assets/js/719e5d48.46b8f441.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[106],{4878:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>p,frontMatter:()=>a,metadata:()=>l,toc:()=>d});var r=n(4848),i=n(8453);const a={},s="ReadOnlyVariables",l={id:"detectors/ReadOnlyVariables",title:"ReadOnlyVariables",description:"A detector that identifies read-only variables and fields.",source:"@site/versioned_docs/version-0.4.0/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/ReadOnlyVariables.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi"},next:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap"}},o={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"readonlyvariables",children:"ReadOnlyVariables"}),"\n",(0,r.jsx)(t.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the analyzer highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var r=n(6540);const i={},a=r.createContext(i);function s(e){const t=r.useContext(a);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),r.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/72b7ad48.f6676fe3.js b/assets/js/72b7ad48.f6676fe3.js new file mode 100644 index 000000000..5361aff47 --- /dev/null +++ b/assets/js/72b7ad48.f6676fe3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2378],{6878:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var t=o(4848),s=o(8453);const i={},r="Unbound Loops",a={id:"detectors/UnboundLoops",title:"Unbound Loops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.2.1/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.2.1/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/UnboundLoops.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables"},next:{title:"Zero Address",permalink:"/tools/misti/docs/0.2.1/detectors/ZeroAddress"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"unbound-loops",children:"Unbound Loops"}),"\n",(0,t.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,t.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,t.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Unexpected Behavior: Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."}),"\n",(0,t.jsx)(n.li,{children:"Out-of-gas Attacks: Continuous looping without termination can lead to out-of-gas attacks."}),"\n",(0,t.jsx)(n.li,{children:"DoS Attacks: Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Use instead:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var t=o(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/740c342d.44a80203.js b/assets/js/740c342d.44a80203.js new file mode 100644 index 000000000..9ae50a7a0 --- /dev/null +++ b/assets/js/740c342d.44a80203.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4910],{8670:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>a,contentTitle:()=>r,default:()=>l,frontMatter:()=>s,metadata:()=>u,toc:()=>c});var o=n(4848),i=n(8453);const s={},r="DumpConfig",u={id:"tools/DumpConfig",title:"DumpConfig",description:"The DumpConfig tool in Misti allows you to print the current configuration file used by the analyzer. This is useful for obtaining the default configuration to use as a starting point for your custom setup or to inspect and understand the existing configuration in use.",source:"@site/versioned_docs/version-0.5/tools/DumpConfig.md",sourceDirName:"tools",slug:"/tools/DumpConfig",permalink:"/tools/misti/docs/tools/DumpConfig",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tools/DumpConfig.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpCfg",permalink:"/tools/misti/docs/tools/DumpCfg"},next:{title:"DumpImports",permalink:"/tools/misti/docs/tools/DumpImports"}},a={},c=[{value:"Usage",id:"usage",level:2},{value:"Understanding the Output",id:"understanding-the-output",level:2}];function d(t){const e={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...t.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(e.h1,{id:"dumpconfig",children:"DumpConfig"}),"\n",(0,o.jsxs)(e.p,{children:["The ",(0,o.jsx)(e.code,{children:"DumpConfig"})," tool in Misti allows you to print the current configuration file used by the analyzer. This is useful for obtaining the default configuration to use as a starting point for your custom setup or to inspect and understand the existing configuration in use."]}),"\n",(0,o.jsx)(e.h2,{id:"usage",children:"Usage"}),"\n",(0,o.jsx)(e.p,{children:"To dump the configuration file, use the following command:"}),"\n",(0,o.jsx)(e.pre,{children:(0,o.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpConfig" \n'})}),"\n",(0,o.jsx)(e.h2,{id:"understanding-the-output",children:"Understanding the Output"}),"\n",(0,o.jsx)(e.p,{children:"The output provides an overview of all the configurations and settings applied to your project. This can help you quickly identify the default settings, make adjustments to fit your specific needs, and ensure that your custom detectors are running under the correct configurations."})]})}function l(t={}){const{wrapper:e}={...(0,i.R)(),...t.components};return e?(0,o.jsx)(e,{...t,children:(0,o.jsx)(d,{...t})}):d(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>u});var o=n(6540);const i={},s=o.createContext(i);function r(t){const e=o.useContext(s);return o.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function u(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(i):t.components||i:r(t.components),o.createElement(s.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/743bfbca.ba311b0c.js b/assets/js/743bfbca.ba311b0c.js new file mode 100644 index 000000000..e05e411c9 --- /dev/null +++ b/assets/js/743bfbca.ba311b0c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[121],{3372:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var o=n(4848),r=n(8453);const i={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.1.2/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/0.1.2/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/hacking/custom-detector.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Tools",permalink:"/tools/misti/docs/0.1.2/hacking/tools"},next:{title:"CHANGELOG",permalink:"/tools/misti/docs/0.1.2/hacking/CHANGELOG"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Writing a Detector",id:"writing-a-detector",level:2},{value:"Example Detectors",id:"example-detectors",level:2}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,o.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,o.jsx)(t.a,{href:"./api/",children:"Misti API Reference"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,o.jsx)(t.a,{href:"./api/classes/detectors_detector.Detector.html",children:(0,o.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,o.jsx)(t.h2,{id:"writing-a-detector",children:"Writing a Detector"}),"\n",(0,o.jsx)(t.p,{children:"To write a custom detector, create a TypeScript file using the Misti API. Here's an example of how to implement a custom detector:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-typescript",children:'import { Detector } from "../../src/detectors/detector";\nimport { MistiContext } from "../../src/internals/context";\nimport { CompilationUnit } from "../../src/internals/ir";\nimport {\n createError,\n MistiTactError,\n Severity,\n} from "../../src/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that don\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends Detector {\n check(ctx: MistiContext, cu: CompilationUnit): MistiTactError[] {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = createError(\n ctx,\n `contract ${contract.name} doesn\'t define an init function`,\n Severity.INFO,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactError[]);\n }\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"After creating a detector, you need to specify it in your configuration. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:'{\n "detectors": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n\n { "className": "ImplicitInit", "modulePath": "/path/to/implicitInit.ts" }\n ],\n "ignored_projects": [],\n "verbosity": "default"\n}\n\n'})}),"\n",(0,o.jsxs)(t.p,{children:["After this, you could run the created detector specifying a path to it: ",(0,o.jsx)(t.code,{children:"--config path/to/mistiConfig.json test/projects/simple/tactConfig.json"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,o.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,o.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var o=n(6540);const r={},i=o.createContext(r);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7499c02a.591c6669.js b/assets/js/7499c02a.591c6669.js new file mode 100644 index 000000000..b6ba23ffa --- /dev/null +++ b/assets/js/7499c02a.591c6669.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3150],{4019:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="BranchDuplicate",o={id:"detectors/BranchDuplicate",title:"BranchDuplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.4.0/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/0.4.0/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/BranchDuplicate.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"AsmIsUsed",permalink:"/tools/misti/docs/0.4.0/detectors/AsmIsUsed"},next:{title:"ConstantAddress",permalink:"/tools/misti/docs/0.4.0/detectors/ConstantAddress"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branchduplicate",children:"BranchDuplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/754ccd45.c7633e79.js b/assets/js/754ccd45.c7633e79.js new file mode 100644 index 000000000..558f29610 --- /dev/null +++ b/assets/js/754ccd45.c7633e79.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3304],{1643:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>l});var s=n(4848),i=n(8453);const r={},c="Developing Misti",o={id:"hacking/developing-misti",title:"Developing Misti",description:"Prerequisites",source:"@site/docs/hacking/developing-misti.md",sourceDirName:"hacking",slug:"/hacking/developing-misti",permalink:"/tools/misti/docs/next/hacking/developing-misti",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/hacking/developing-misti.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/next/hacking/contributing"},next:{title:"Writing Custom Detectors",permalink:"/tools/misti/docs/next/hacking/custom-detector"}},a={},l=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Cloning the Repository",id:"cloning-the-repository",level:2},{value:"Building the Project",id:"building-the-project",level:2},{value:"Running the Analyzer",id:"running-the-analyzer",level:2},{value:"Adding Backtraces to the Logger",id:"adding-backtraces-to-the-logger",level:2},{value:"Updating Expected Outputs of Tests",id:"updating-expected-outputs-of-tests",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"developing-misti",children:"Developing Misti"}),"\n",(0,s.jsx)(t.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsxs)(t.p,{children:["Before you begin, please refer to the ",(0,s.jsx)(t.a,{href:"https://nowarp.io/tools/misti/docs/next/tutorial/getting-started",children:"Getting Started documentation"})," for the required system dependencies."]}),"\n",(0,s.jsx)(t.h2,{id:"cloning-the-repository",children:"Cloning the Repository"}),"\n",(0,s.jsx)(t.p,{children:"Clone the Misti repository:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"git clone 'https://github.com/nowarp/misti'\n"})}),"\n",(0,s.jsx)(t.h2,{id:"building-the-project",children:"Building the Project"}),"\n",(0,s.jsx)(t.p,{children:"Navigate to the project directory, install dependencies, generate necessary files, and build the project:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"cd misti && yarn install && yarn gen && yarn build\n"})}),"\n",(0,s.jsx)(t.h2,{id:"running-the-analyzer",children:"Running the Analyzer"}),"\n",(0,s.jsx)(t.p,{children:"During development, you can run the analyzer using:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"yarn misti\n"})}),"\n",(0,s.jsx)(t.p,{children:"For example, to run it for tests:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"yarn misti test/detectors/NeverAccessedVariables.tact\n"})}),"\n",(0,s.jsx)(t.h2,{id:"adding-backtraces-to-the-logger",children:"Adding Backtraces to the Logger"}),"\n",(0,s.jsxs)(t.p,{children:["To add debug traces to all log messages, set the ",(0,s.jsx)(t.code,{children:"MISTI_TRACE"})," environment variable to ",(0,s.jsx)(t.code,{children:"1"}),":"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"MISTI_TRACE=1 yarn misti test/detectors/NeverAccessedVariables.tact\n"})}),"\n",(0,s.jsx)(t.h2,{id:"updating-expected-outputs-of-tests",children:"Updating Expected Outputs of Tests"}),"\n",(0,s.jsxs)(t.p,{children:["To update the expected outputs of tests, set the ",(0,s.jsx)(t.code,{children:"BLESS"})," environment variable and run the tests:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test\n"})}),"\n",(0,s.jsx)(t.p,{children:"You can also run a single test or update its expected output when working with a specific test file:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test test/tactIR.spec.ts tests/detectors/NeverAccessedVariables.tact\n"})}),"\n",(0,s.jsx)(t.p,{children:"And for another specific test:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test test/builtinDetectors.spec.ts test/detectors/BranchDuplicate.tact\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/76268162.332975fc.js b/assets/js/76268162.332975fc.js new file mode 100644 index 000000000..f4f39d806 --- /dev/null +++ b/assets/js/76268162.332975fc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7005],{1943:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var t=o(4848),s=o(8453);const i={},r="Unbound Loops",a={id:"detectors/UnboundLoops",title:"Unbound Loops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.2.0/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.2.0/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/UnboundLoops.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.2.0/detectors/ReadOnlyVariables"},next:{title:"Zero Address",permalink:"/tools/misti/docs/0.2.0/detectors/ZeroAddress"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"unbound-loops",children:"Unbound Loops"}),"\n",(0,t.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,t.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,t.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Unexpected Behavior: Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."}),"\n",(0,t.jsx)(n.li,{children:"Out-of-gas Attacks: Continuous looping without termination can lead to out-of-gas attacks."}),"\n",(0,t.jsx)(n.li,{children:"DoS Attacks: Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Use instead:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var t=o(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/770027e6.28c96dd7.js b/assets/js/770027e6.28c96dd7.js new file mode 100644 index 000000000..26dcc9898 --- /dev/null +++ b/assets/js/770027e6.28c96dd7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7709],{4951:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>l,frontMatter:()=>i,metadata:()=>d,toc:()=>c});var n=s(4848),o=s(8453);const i={},r="UnusedExpressionResult",d={id:"detectors/UnusedExpressionResult",title:"UnusedExpressionResult",description:"A detector that identifies expression statements whose result is unused.",source:"@site/versioned_docs/version-0.5/detectors/UnusedExpressionResult.md",sourceDirName:"detectors",slug:"/detectors/UnusedExpressionResult",permalink:"/tools/misti/docs/detectors/UnusedExpressionResult",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/UnusedExpressionResult.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"UnboundMap",permalink:"/tools/misti/docs/detectors/UnboundMap"},next:{title:"UnusedOptional",permalink:"/tools/misti/docs/detectors/UnusedOptional"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function u(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"unusedexpressionresult",children:"UnusedExpressionResult"}),"\n",(0,n.jsx)(t.p,{children:"A detector that identifies expression statements whose result is unused."}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Expression statements that don't alter the contract's state and whose results are not used\ncan lead to inefficiency, dead code, and potential confusion. They add unnecessary complexity\nwithout contributing to the logic or state of the contract."}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"self.foo == 3; // Warning: unused boolean expression\ninc(a); // Warning: unused return value\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"self.foo = 3; // Fixed: corrected assignment\nnewValue = inc(a); // OK: result is now used\nlet _ = inc(a); // OK: explicitly ignored\n"})})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>d});var n=s(6540);const o={},i=n.createContext(o);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/773c7ee4.d71f2dd0.js b/assets/js/773c7ee4.d71f2dd0.js new file mode 100644 index 000000000..bce954227 --- /dev/null +++ b/assets/js/773c7ee4.d71f2dd0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1564],{9113:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.2.0/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.2.0/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/hacking/souffle.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.2.0/hacking/design"},next:{title:"Tools",permalink:"/tools/misti/docs/0.2.0/hacking/tools"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is detailed ",(0,t.jsx)(n.a,{href:"https://nowarp.github.io/docs/misti/api/modules/internals_souffle.html",children:"here"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/775287ab.a34207ca.js b/assets/js/775287ab.a34207ca.js new file mode 100644 index 000000000..0e1b07912 --- /dev/null +++ b/assets/js/775287ab.a34207ca.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8342],{1402:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var t=i(4848),s=i(8453);const o={},r="Contributing Guide",a={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/versioned_docs/version-0.1.2/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/0.1.2/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/hacking/contributing.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Zero Address",permalink:"/tools/misti/docs/0.1.2/detectors/ZeroAddress"},next:{title:"Design Overview",permalink:"/tools/misti/docs/0.1.2/hacking/design"}},c={},d=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["All guidelines and additional hacking tips are available in the repo. For low-level details not present in the docs, refer to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/HACKING.md",children:"HACKING.md"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>a});var t=i(6540);const s={},o=t.createContext(s);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/776efca7.78ead050.js b/assets/js/776efca7.78ead050.js new file mode 100644 index 000000000..6ddb6e691 --- /dev/null +++ b/assets/js/776efca7.78ead050.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7151],{1883:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var n=t(4848),s=t(8453);const i={},o="StringReceiversOverlap",a={id:"detectors/StringReceiversOverlap",title:"StringReceiversOverlap",description:"A detector that finds overlapping messages between general string receivers and string receivers.",source:"@site/versioned_docs/version-0.3.1/detectors/StringReceiversOverlap.md",sourceDirName:"detectors",slug:"/detectors/StringReceiversOverlap",permalink:"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/StringReceiversOverlap.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables"},next:{title:"UnboundLoops",permalink:"/tools/misti/docs/0.3.1/detectors/UnboundLoops"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const r={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h1,{id:"stringreceiversoverlap",children:"StringReceiversOverlap"}),"\n",(0,n.jsx)(r.p,{children:"A detector that finds overlapping messages between general string receivers and string receivers."}),"\n",(0,n.jsx)(r.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(r.p,{children:"Constant string receivers and general string receivers can have overlapping messages\nin which case the constant string receiver always takes precedence."}),"\n",(0,n.jsx)(r.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {\n if (msg == "foobar") { throw(1043) } // Bad: Dead code\n }\n}\n'})}),"\n",(0,n.jsx)(r.p,{children:"Use instead:"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {}\n}\n'})})]})}function p(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,r,t)=>{t.d(r,{R:()=>o,x:()=>a});var n=t(6540);const s={},i=n.createContext(s);function o(e){const r=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/7b5b3cc2.90aa7fd2.js b/assets/js/7b5b3cc2.90aa7fd2.js new file mode 100644 index 000000000..b3a4a5f06 --- /dev/null +++ b/assets/js/7b5b3cc2.90aa7fd2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6612],{8962:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=n(4848),a=n(8453);const r={},s="InheritedStateMutation",o={id:"detectors/InheritedStateMutation",title:"InheritedStateMutation",description:"An optional detector that highlights all instances where inherited trait variables",source:"@site/versioned_docs/version-0.3.0/detectors/InheritedStateMutation.md",sourceDirName:"detectors",slug:"/detectors/InheritedStateMutation",permalink:"/tools/misti/docs/0.3.0/detectors/InheritedStateMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/InheritedStateMutation.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/0.3.0/detectors/FieldDoubleInit"},next:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"inheritedstatemutation",children:"InheritedStateMutation"}),"\n",(0,i.jsx)(t.p,{children:"An optional detector that highlights all instances where inherited trait variables\nare directly modified."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Traits should provide setter methods to ensure that invariants related to their\nstate are preserved. Directly modifying trait variables (e.g., ",(0,i.jsx)(t.code,{children:"self.traitVar = 42"}),")\ncan violate these invariants, leading to potential bugs or security vulnerabilities.\nThis detector warns when such direct modifications occur, prompting further review\nby auditors."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"trait T {\n balance: Int;\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.balance = 100; // Suspicious: Highlighted by the detector\n }\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:'trait T {\n balance: Int;\n fun setBalance(newBalance: Int) {\n require(newBalance > 0, "balance cannot be negative"); // Invariant check\n self.balance = newBalance;\n }\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.setBalance(100); // OK: Invariant preserved\n }\n}\n'})})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var i=n(6540);const a={},r=i.createContext(a);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8078ad78.72d8805b.js b/assets/js/8078ad78.72d8805b.js new file mode 100644 index 000000000..bba14e859 --- /dev/null +++ b/assets/js/8078ad78.72d8805b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6208],{210:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var o=n(4848),i=n(8453);const s={},r="FalseCondition",a={id:"detectors/FalseCondition",title:"FalseCondition",description:"A detector that highlights conditions that evaluate to a constant true or false",source:"@site/versioned_docs/version-0.5/detectors/FalseCondition.md",sourceDirName:"detectors",slug:"/detectors/FalseCondition",permalink:"/tools/misti/docs/detectors/FalseCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/FalseCondition.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"EnsurePrgSeed",permalink:"/tools/misti/docs/detectors/EnsurePrgSeed"},next:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/detectors/FieldDoubleInit"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"falsecondition",children:"FalseCondition"}),"\n",(0,o.jsxs)(t.p,{children:["A detector that highlights conditions that evaluate to a constant ",(0,o.jsx)(t.code,{children:"true"})," or ",(0,o.jsx)(t.code,{children:"false"}),"\nin ",(0,o.jsx)(t.code,{children:"if"}),", ",(0,o.jsx)(t.code,{children:"while"}),", or ",(0,o.jsx)(t.code,{children:"until"})," statements, and zero iterations in ",(0,o.jsx)(t.code,{children:"repeat"})," statements."]}),"\n",(0,o.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsxs)(t.p,{children:["Conditions that always evaluate to a constant ",(0,o.jsx)(t.code,{children:"true"})," or ",(0,o.jsx)(t.code,{children:"false"})," are likely the result of a typo\nor logic error. Such conditions can lead to unintended behavior, dead code, or incorrect control flow.\nThis detector helps identify these cases so they can be corrected, improving the code's reliability."]}),"\n",(0,o.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-tact",children:"const FALSE: Bool = false;\n// Bad: Always false because of operator precedence\nif ((param | value) & FALSE) {\n // ... never executed\n}\n"})}),"\n",(0,o.jsx)(t.p,{children:"Use instead:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-tact",children:"const FALSE: Bool = false;\n// OK: Fixed after the analyzer highlighted this\nif (param) {}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var o=n(6540);const i={},s=o.createContext(i);function r(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/81087c81.7da41d03.js b/assets/js/81087c81.7da41d03.js new file mode 100644 index 000000000..f769ead53 --- /dev/null +++ b/assets/js/81087c81.7da41d03.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6869],{2140:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var i=n(4848),o=n(8453);const r={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.3.0/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/0.3.0/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/hacking/custom-detector.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Tools",permalink:"/tools/misti/docs/0.3.0/hacking/tools"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Creating a Detector",id:"creating-a-detector",level:2},{value:"Testing the detector",id:"testing-the-detector",level:3},{value:"Saving the configuration",id:"saving-the-configuration",level:3},{value:"Example Detectors",id:"example-detectors",level:2}];function h(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,i.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,i.jsx)(t.h2,{id:"creating-a-detector",children:"Creating a Detector"}),"\n",(0,i.jsxs)(t.p,{children:["You can create a new custom detector by executing Misti with the ",(0,i.jsx)(t.code,{children:"--new-detector"})," option: ",(0,i.jsx)(t.code,{children:"npx misti --new-detector implicitInit"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["This will create the ",(0,i.jsx)(t.code,{children:"implicitInit.ts"})," file, which contains the template code for writing your own custom detector logic leveraging the Misti API."]}),"\n",(0,i.jsx)(t.p,{children:"Here's an example of how to implement a custom detector using Misti API:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-typescript",children:'import { Detector } from "@nowarp/misti/dist/detectors/detector";\nimport { CompilationUnit } from "@nowarp/misti/dist/internals/ir";\nimport {\n MistiTactWarning,\n Severity,\n} from "@nowarp/misti/dist/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that doesn\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends Detector {\n async check(cu: CompilationUnit): Promise {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = this.makeError(\n `Contract ${contract.name} doesn\'t define an init function`,\n Severity.INFO,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactWarning[]);\n }\n}\n'})}),"\n",(0,i.jsx)(t.h3,{id:"testing-the-detector",children:"Testing the detector"}),"\n",(0,i.jsxs)(t.p,{children:["To run Misti with only your new detector, use the ",(0,i.jsx)(t.code,{children:"--detectors"})," option, specifying the path to the detector and the Detector class name: ",(0,i.jsx)(t.code,{children:"npx misti path/to/your/tact.config.json --detectors path/to/implicitInit.ts:ImplicitInit"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["That's a good way to test the detector on the first run. You could also use the ",(0,i.jsx)(t.code,{children:"--verbose"})," CLI option and set the environment variable ",(0,i.jsx)(t.code,{children:"MISTI_TRACE=1"})," to facilitate debugging."]}),"\n",(0,i.jsx)(t.h3,{id:"saving-the-configuration",children:"Saving the configuration"}),"\n",(0,i.jsx)(t.p,{children:"After testing the detector, you can specify it in your configuration to enable it in future runs. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'{\n "detectors": [\n // Other detectors...\n { "className": "ImplicitInit", "modulePath": "ImplicitInit.ts" }\n ],\n}\n'})}),"\n",(0,i.jsxs)(t.p,{children:["After this, you could run Misti specifying a path to a custom configuration ",(0,i.jsx)(t.code,{children:"npx misti --config path/to/misti.config.json path/to/your/tact.config.json"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,i.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var i=n(6540);const o={},r=i.createContext(o);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8272dc48.d9a84b38.js b/assets/js/8272dc48.d9a84b38.js new file mode 100644 index 000000000..ed5f14c5e --- /dev/null +++ b/assets/js/8272dc48.d9a84b38.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1529],{2184:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>I,default:()=>c,frontMatter:()=>l,metadata:()=>d,toc:()=>g});var n=t(4848),s=t(8453);const l={},I="Tools Guide",d={id:"hacking/tools",title:"Tools Guide",description:"This page describes the internal analyzer tools available in Misti to aid in development and debugging.",source:"@site/versioned_docs/version-0.2.0/hacking/tools.md",sourceDirName:"hacking",slug:"/hacking/tools",permalink:"/tools/misti/docs/0.2.0/hacking/tools",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/hacking/tools.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.2.0/hacking/souffle"},next:{title:"Custom Detectors",permalink:"/tools/misti/docs/0.2.0/hacking/custom-detector"}},o={},g=[{value:"CFG Dump",id:"cfg-dump",level:2},{value:"Usage",id:"usage",level:3},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function a(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"tools-guide",children:"Tools Guide"}),"\n",(0,n.jsx)(e.p,{children:"This page describes the internal analyzer tools available in Misti to aid in development and debugging."}),"\n",(0,n.jsx)(e.h2,{id:"cfg-dump",children:"CFG Dump"}),"\n",(0,n.jsx)(e.p,{children:"Misti provides a feature to dump the Control Flow Graph (CFG) in both JSON and DOT formats. This is essential for understanding the internal representation (IR) of the code and analyzing the control flow within contracts."}),"\n",(0,n.jsx)(e.h3,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="json" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" \n'})}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, you can save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allows you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for gaining a better understanding of the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function c(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(a,{...i})}):a(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>I,x:()=>d});var n=t(6540);const s={},l=n.createContext(s);function I(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function d(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:I(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/8306354c.0e912fc3.js b/assets/js/8306354c.0e912fc3.js new file mode 100644 index 000000000..6f591d1df --- /dev/null +++ b/assets/js/8306354c.0e912fc3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7877],{9164:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var s=n(4848),r=n(8453);const i={},o="PreferAugmentedAssign",a={id:"detectors/PreferAugmentedAssign",title:"PreferAugmentedAssign",description:"Detects non-idiomatic statements that can be written using augmented assignment",source:"@site/versioned_docs/version-0.4.0/detectors/PreferAugmentedAssign.md",sourceDirName:"detectors",slug:"/detectors/PreferAugmentedAssign",permalink:"/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/PreferAugmentedAssign.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"OptimalMathFunction",permalink:"/tools/misti/docs/0.4.0/detectors/OptimalMathFunction"},next:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"preferaugmentedassign",children:"PreferAugmentedAssign"}),"\n",(0,s.jsxs)(t.p,{children:["Detects non-idiomatic statements that can be written using augmented assignment\noperators like ",(0,s.jsx)(t.code,{children:"+="}),", ",(0,s.jsx)(t.code,{children:"-="}),", etc."]}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Using augmented assignment operations improves the readability of the source code\nand reduces the risk of mistakes, such as those that occur during copy-pasting\nand refactoring code."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue = (msgValue - ctx.readForwardFee());\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue -= ctx.readForwardFee());\n"})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/844f22a2.2f80fdcf.js b/assets/js/844f22a2.2f80fdcf.js new file mode 100644 index 000000000..b4d82e564 --- /dev/null +++ b/assets/js/844f22a2.2f80fdcf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5316],{9095:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=i(4848),s=i(8453);const l={},r="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/versioned_docs/version-0.3.0/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/0.3.0/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/tutorial/getting-started.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/0.3.0/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.3.0/tutorial/ci-cd"}},a={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"More usage examples",id:"more-usage-examples",level:2},{value:"Suppressing Specific Detectors",id:"suppressing-specific-detectors",level:3},{value:"Enabling All Detectors",id:"enabling-all-detectors",level:3},{value:"Running in Quiet Mode",id:"running-in-quiet-mode",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,t.jsx)(n.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsx)(n.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Git"}),"\n",(0,t.jsx)(n.li,{children:"Yarn"}),"\n",(0,t.jsx)(n.li,{children:"Node.js version 22 or higher"}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,t.jsxs)(n.p,{children:["Misti is distributed via npm and should be added to your Tact project ",(0,t.jsx)(n.a,{href:"https://github.com/tact-lang/tact?tab=readme-ov-file#installation",children:"in the same way"})," as Tact itself:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @nowarp/misti\n"})}),"\n",(0,t.jsx)(n.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,t.jsx)(n.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,t.jsx)(n.p,{children:"To install the latest development version you should:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Clone Misti: ",(0,t.jsx)(n.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,t.jsxs)(n.li,{children:["Build it: ",(0,t.jsx)(n.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,t.jsxs)(n.li,{children:["Use it in your Tact project: ",(0,t.jsx)(n.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,t.jsx)(n.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"npx misti path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,t.jsxs)(n.p,{children:["You can also add a script to your ",(0,t.jsx)(n.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "npx misti path/to/tact.config.json"\n }\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"more-usage-examples",children:"More usage examples"}),"\n",(0,t.jsxs)(n.p,{children:["Below are a few usage examples for common scenarios when using ",(0,t.jsxs)(n.a,{href:"/tools/misti/docs/0.3.0/tutorial/cli",children:["the ",(0,t.jsx)(n.code,{children:"misti"})," CLI"]}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"suppressing-specific-detectors",children:"Suppressing Specific Detectors"}),"\n",(0,t.jsxs)(n.p,{children:["To run ",(0,t.jsx)(n.code,{children:"misti"})," while suppressing specific detectors, such as ",(0,t.jsx)(n.code,{children:"ReadOnlyVariables"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --suppress ReadOnlyVariables path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enabling-all-detectors",children:"Enabling All Detectors"}),"\n",(0,t.jsxs)(n.p,{children:["Running ",(0,t.jsx)(n.code,{children:"misti"})," with all available built-in detectors enabled:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --all-detectors path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"It is recommended to do that when auditing the project."}),"\n",(0,t.jsx)(n.h3,{id:"running-in-quiet-mode",children:"Running in Quiet Mode"}),"\n",(0,t.jsxs)(n.p,{children:["To suppress all output while running ",(0,t.jsx)(n.code,{children:"misti"})," getting just a return code:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --quiet path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"This might be useful in scripts and CI/CD."}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,t.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>o});var t=i(6540);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/866ed13d.d4edfa4a.js b/assets/js/866ed13d.d4edfa4a.js new file mode 100644 index 000000000..3eed53997 --- /dev/null +++ b/assets/js/866ed13d.d4edfa4a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6974],{9515:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var n=s(4848),r=s(8453);const o={},d="ZeroAddress",i={id:"detectors/ZeroAddress",title:"ZeroAddress",description:"A detector that identifies uses of the zero address.",source:"@site/docs/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/next/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/ZeroAddress.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"UnusedOptional",permalink:"/tools/misti/docs/next/detectors/UnusedOptional"},next:{title:"Overview",permalink:"/tools/misti/docs/next/tools"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"zeroaddress",children:"ZeroAddress"}),"\n",(0,n.jsx)(t.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initialization.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>d,x:()=>i});var n=s(6540);const r={},o=n.createContext(r);function d(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8685a76e.8943dfe3.js b/assets/js/8685a76e.8943dfe3.js new file mode 100644 index 000000000..19c695218 --- /dev/null +++ b/assets/js/8685a76e.8943dfe3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3583],{3950:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.5/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/hacking/souffle.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/hacking/design"},next:{title:"Contributing",permalink:"/tools/misti/docs/hacking/contributing"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is implemented in the ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/souffle.js",children:"Souffle.js library"}),". See the ",(0,t.jsx)(n.a,{href:"https://nowarp.io/lib/souffle-js/api/",children:"Souffle.js API reference"})," for more detailed information."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/86d22c3d.7c8fbb6b.js b/assets/js/86d22c3d.7c8fbb6b.js new file mode 100644 index 000000000..d290eb76c --- /dev/null +++ b/assets/js/86d22c3d.7c8fbb6b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1407],{5012:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"0.5","label":"0.5","banner":null,"badge":true,"noIndex":false,"className":"docs-version-0.5","isLast":true,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"CI/CD Integration","href":"/tools/misti/docs/tutorial/ci-cd","docId":"tutorial/ci-cd","unlisted":false},{"type":"link","label":"Command-Line Interface","href":"/tools/misti/docs/tutorial/cli","docId":"tutorial/cli","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/tutorial/configuration","docId":"tutorial/configuration","unlisted":false},{"type":"link","label":"Using with Blueprint","href":"/tools/misti/docs/tutorial/blueprint","docId":"tutorial/blueprint","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"html","value":"
"},{"type":"html","value":" "},{"type":"link","label":"Overview","href":"/tools/misti/docs/detectors","docId":"detectors","unlisted":false},{"type":"category","label":"Built-in Detectors","items":[{"type":"link","label":"ArgCopyMutation","href":"/tools/misti/docs/detectors/ArgCopyMutation","docId":"detectors/ArgCopyMutation","unlisted":false},{"type":"link","label":"AsmIsUsed","href":"/tools/misti/docs/detectors/AsmIsUsed","docId":"detectors/AsmIsUsed","unlisted":false},{"type":"link","label":"BranchDuplicate","href":"/tools/misti/docs/detectors/BranchDuplicate","docId":"detectors/BranchDuplicate","unlisted":false},{"type":"link","label":"CellOverflow","href":"/tools/misti/docs/detectors/CellOverflow","docId":"detectors/CellOverflow","unlisted":false},{"type":"link","label":"ConstantAddress","href":"/tools/misti/docs/detectors/ConstantAddress","docId":"detectors/ConstantAddress","unlisted":false},{"type":"link","label":"DivideBeforeMultiply","href":"/tools/misti/docs/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"DumpIsUsed","href":"/tools/misti/docs/detectors/DumpIsUsed","docId":"detectors/DumpIsUsed","unlisted":false},{"type":"link","label":"DuplicatedCondition","href":"/tools/misti/docs/detectors/DuplicatedCondition","docId":"detectors/DuplicatedCondition","unlisted":false},{"type":"link","label":"EnsurePrgSeed","href":"/tools/misti/docs/detectors/EnsurePrgSeed","docId":"detectors/EnsurePrgSeed","unlisted":false},{"type":"link","label":"FalseCondition","href":"/tools/misti/docs/detectors/FalseCondition","docId":"detectors/FalseCondition","unlisted":false},{"type":"link","label":"FieldDoubleInit","href":"/tools/misti/docs/detectors/FieldDoubleInit","docId":"detectors/FieldDoubleInit","unlisted":false},{"type":"link","label":"InheritedStateMutation","href":"/tools/misti/docs/detectors/InheritedStateMutation","docId":"detectors/InheritedStateMutation","unlisted":false},{"type":"link","label":"NeverAccessedVariables","href":"/tools/misti/docs/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"OptimalMathFunction","href":"/tools/misti/docs/detectors/OptimalMathFunction","docId":"detectors/OptimalMathFunction","unlisted":false},{"type":"link","label":"PreferAugmentedAssign","href":"/tools/misti/docs/detectors/PreferAugmentedAssign","docId":"detectors/PreferAugmentedAssign","unlisted":false},{"type":"link","label":"PreferredStdlibApi","href":"/tools/misti/docs/detectors/PreferredStdlibApi","docId":"detectors/PreferredStdlibApi","unlisted":false},{"type":"link","label":"ReadOnlyVariables","href":"/tools/misti/docs/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"SendInLoop","href":"/tools/misti/docs/detectors/SendInLoop","docId":"detectors/SendInLoop","unlisted":false},{"type":"link","label":"StringReceiversOverlap","href":"/tools/misti/docs/detectors/StringReceiversOverlap","docId":"detectors/StringReceiversOverlap","unlisted":false},{"type":"link","label":"SuspiciousMessageMode","href":"/tools/misti/docs/detectors/SuspiciousMessageMode","docId":"detectors/SuspiciousMessageMode","unlisted":false},{"type":"link","label":"UnboundLoop","href":"/tools/misti/docs/detectors/UnboundLoop","docId":"detectors/UnboundLoop","unlisted":false},{"type":"link","label":"UnboundMap","href":"/tools/misti/docs/detectors/UnboundMap","docId":"detectors/UnboundMap","unlisted":false},{"type":"link","label":"UnusedExpressionResult","href":"/tools/misti/docs/detectors/UnusedExpressionResult","docId":"detectors/UnusedExpressionResult","unlisted":false},{"type":"link","label":"UnusedOptional","href":"/tools/misti/docs/detectors/UnusedOptional","docId":"detectors/UnusedOptional","unlisted":false},{"type":"link","label":"ZeroAddress","href":"/tools/misti/docs/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"html","value":"
"},{"type":"html","value":" "},{"type":"link","label":"Overview","href":"/tools/misti/docs/tools","docId":"tools","unlisted":false},{"type":"category","label":"Built-in Tools","items":[{"type":"link","label":"DumpAst","href":"/tools/misti/docs/tools/DumpAst","docId":"tools/DumpAst","unlisted":false},{"type":"link","label":"DumpCfg","href":"/tools/misti/docs/tools/DumpCfg","docId":"tools/DumpCfg","unlisted":false},{"type":"link","label":"DumpConfig","href":"/tools/misti/docs/tools/DumpConfig","docId":"tools/DumpConfig","unlisted":false},{"type":"link","label":"DumpImports","href":"/tools/misti/docs/tools/DumpImports","docId":"tools/DumpImports","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"html","value":"
"},{"type":"html","value":" "},{"type":"category","label":"Misti Design","items":[{"type":"link","label":"Design Overview","href":"/tools/misti/docs/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/hacking/souffle","docId":"hacking/souffle","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Developing Misti","href":"/tools/misti/docs/hacking/developing-misti","docId":"hacking/developing-misti","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Writing Custom Detectors","href":"/tools/misti/docs/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false}]},"docs":{"detectors":{"id":"detectors","title":"Detectors Overview","description":"Built-in Detectors","sidebar":"sidebar"},"detectors/ArgCopyMutation":{"id":"detectors/ArgCopyMutation","title":"ArgCopyMutation","description":"A detector that highlights cases where function argument mutations are ineffective","sidebar":"sidebar"},"detectors/AsmIsUsed":{"id":"detectors/AsmIsUsed","title":"AsmIsUsed","description":"An optional detector that highlights all the asm functions.","sidebar":"sidebar"},"detectors/BranchDuplicate":{"id":"detectors/BranchDuplicate","title":"BranchDuplicate","description":"Detector that reports duplicated code in conditional branches.","sidebar":"sidebar"},"detectors/CellOverflow":{"id":"detectors/CellOverflow","title":"CellOverflow","description":"A detector that identifies cell overflow problems.","sidebar":"sidebar"},"detectors/ConstantAddress":{"id":"detectors/ConstantAddress","title":"ConstantAddress","description":"An optional detector that highlights all the constant addresses appearing in the source code.","sidebar":"sidebar"},"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"DivideBeforeMultiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/DumpIsUsed":{"id":"detectors/DumpIsUsed","title":"DumpIsUsed","description":"An optional detector that highlights all the dump debug prints.","sidebar":"sidebar"},"detectors/DuplicatedCondition":{"id":"detectors/DuplicatedCondition","title":"DuplicatedCondition","description":"A detector that finds duplicated conditions appearing in conditional expressions.","sidebar":"sidebar"},"detectors/EnsurePrgSeed":{"id":"detectors/EnsurePrgSeed","title":"EnsurePrgSeed","description":"A detector that identifies all calls to nativeRandom and nativeRandomInterval","sidebar":"sidebar"},"detectors/FalseCondition":{"id":"detectors/FalseCondition","title":"FalseCondition","description":"A detector that highlights conditions that evaluate to a constant true or false","sidebar":"sidebar"},"detectors/FieldDoubleInit":{"id":"detectors/FieldDoubleInit","title":"FieldDoubleInit","description":"A detector that highlights cases where a field is initialized both in the","sidebar":"sidebar"},"detectors/InheritedStateMutation":{"id":"detectors/InheritedStateMutation","title":"InheritedStateMutation","description":"An optional detector that highlights all instances where inherited trait variables","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"NeverAccessedVariables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/OptimalMathFunction":{"id":"detectors/OptimalMathFunction","title":"OptimalMathFunction","description":"A detector that highlights standard library math function calls that have more gas-efficient alternatives.","sidebar":"sidebar"},"detectors/PreferAugmentedAssign":{"id":"detectors/PreferAugmentedAssign","title":"PreferAugmentedAssign","description":"Detects non-idiomatic statements that can be written using augmented assignment","sidebar":"sidebar"},"detectors/PreferredStdlibApi":{"id":"detectors/PreferredStdlibApi","title":"PreferredStdlibApi","description":"An optional detector that flags the use of advanced functions from the standard library.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"ReadOnlyVariables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/SendInLoop":{"id":"detectors/SendInLoop","title":"SendInLoop","description":"An optional detector that identifies send functions being called inside loops.","sidebar":"sidebar"},"detectors/StringReceiversOverlap":{"id":"detectors/StringReceiversOverlap","title":"StringReceiversOverlap","description":"A detector that finds overlapping messages between general string receivers and string receivers.","sidebar":"sidebar"},"detectors/SuspiciousMessageMode":{"id":"detectors/SuspiciousMessageMode","title":"SuspiciousMessageMode","description":"Detects suspicious usage of the mode field in SendParameters struct instances.","sidebar":"sidebar"},"detectors/UnboundLoop":{"id":"detectors/UnboundLoop","title":"UnboundLoop","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/UnboundMap":{"id":"detectors/UnboundMap","title":"UnboundMap","description":"An optional detector that highlights cases where a map field allows inserting","sidebar":"sidebar"},"detectors/UnusedExpressionResult":{"id":"detectors/UnusedExpressionResult","title":"UnusedExpressionResult","description":"A detector that identifies expression statements whose result is unused.","sidebar":"sidebar"},"detectors/UnusedOptional":{"id":"detectors/UnusedOptional","title":"UnusedOptional","description":"A detector variables and fields with unused optional modifier.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"ZeroAddress","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/developing-misti":{"id":"hacking/developing-misti","title":"Developing Misti","description":"Prerequisites","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tools":{"id":"tools","title":"Tools Overview","description":"Misti Tools are additional modules designed to work alongside detectors, enabling various tasks beyond code analysis.","sidebar":"sidebar"},"tools/DumpAst":{"id":"tools/DumpAst","title":"DumpAst","description":"The DumpAst tool in Misti enables users to output the Abstract Syntax Tree (AST) of project modules in JSON format. This is particularly useful when writing custom detectors, as it helps understand the structure and components of the code.","sidebar":"sidebar"},"tools/DumpCfg":{"id":"tools/DumpCfg","title":"DumpCfg","description":"Misti provides a feature to dump the Control Flow Graph (CFG) in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts.","sidebar":"sidebar"},"tools/DumpConfig":{"id":"tools/DumpConfig","title":"DumpConfig","description":"The DumpConfig tool in Misti allows you to print the current configuration file used by the analyzer. This is useful for obtaining the default configuration to use as a starting point for your custom setup or to inspect and understand the existing configuration in use.","sidebar":"sidebar"},"tools/DumpImports":{"id":"tools/DumpImports","title":"DumpImports","description":"Misti provides a feature to dump the Import Graph of your Tact code in JSON, DOT, and Mermaid formats. This tool helps you understand the dependencies between different files and modules in your project, including how contracts import each other and use the standard library.","sidebar":"sidebar"},"tutorial/blueprint":{"id":"tutorial/blueprint","title":"Using Misti with Blueprint","description":"Blueprint is a platform to compile, test, and deploy contracts on the TON blockchain. It is quite similar to Hardhat and Truffle for Ethereum.","sidebar":"sidebar"},"tutorial/ci-cd":{"id":"tutorial/ci-cd","title":"Integrating Misti into CI/CD","description":"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.","sidebar":"sidebar"},"tutorial/cli":{"id":"tutorial/cli","title":"Command-Line Interface","description":"CLI Options","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/86d70222.91cb640f.js b/assets/js/86d70222.91cb640f.js new file mode 100644 index 000000000..8674ae3c3 --- /dev/null +++ b/assets/js/86d70222.91cb640f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3812],{2759:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var o=n(4848),r=n(8453);const i={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.2.0/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/0.2.0/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/hacking/custom-detector.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Tools",permalink:"/tools/misti/docs/0.2.0/hacking/tools"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Writing a Detector",id:"writing-a-detector",level:2},{value:"Example Detectors",id:"example-detectors",level:2}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,o.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,o.jsx)(t.a,{href:"https://nowarp.github.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,o.jsx)(t.a,{href:"https://nowarp.github.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,o.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,o.jsx)(t.h2,{id:"writing-a-detector",children:"Writing a Detector"}),"\n",(0,o.jsx)(t.p,{children:"To write a custom detector, create a TypeScript file using the Misti API. Here's an example of how to implement a custom detector:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-typescript",children:'import { Detector } from "../../src/detectors/detector";\nimport { MistiContext } from "../../src/internals/context";\nimport { CompilationUnit } from "../../src/internals/ir";\nimport {\n createError,\n MistiTactError,\n Severity,\n} from "../../src/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that don\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends Detector {\n check(ctx: MistiContext, cu: CompilationUnit): MistiTactError[] {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = createError(\n ctx,\n `contract ${contract.name} doesn\'t define an init function`,\n Severity.INFO,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactError[]);\n }\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"After creating a detector, you need to specify it in your configuration. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:'{\n "detectors": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n\n { "className": "ImplicitInit", "modulePath": "/path/to/implicitInit.ts" }\n ],\n "ignored_projects": [],\n "verbosity": "default"\n}\n\n'})}),"\n",(0,o.jsxs)(t.p,{children:["After this, you could run the created detector specifying a path to it: ",(0,o.jsx)(t.code,{children:"--config path/to/mistiConfig.json test/projects/simple/tactConfig.json"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,o.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,o.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var o=n(6540);const r={},i=o.createContext(r);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/87ce9660.55512f80.js b/assets/js/87ce9660.55512f80.js new file mode 100644 index 000000000..aad3f6d5b --- /dev/null +++ b/assets/js/87ce9660.55512f80.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7495],{7049:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var n=t(4848),o=t(8453);const r={},d="Zero Address",i={id:"detectors/ZeroAddress",title:"Zero Address",description:"A detector that identifies uses of the zero address.",source:"@site/versioned_docs/version-0.2.0/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/0.2.0/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/ZeroAddress.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Unbound Loops",permalink:"/tools/misti/docs/0.2.0/detectors/UnboundLoops"},next:{title:"Constant Address",permalink:"/tools/misti/docs/0.2.0/detectors/ConstantAddress"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"zero-address",children:"Zero Address"}),"\n",(0,n.jsx)(s.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(s.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(s.p,{children:"Use instead:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initializaiton.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>d,x:()=>i});var n=t(6540);const o={},r=n.createContext(o);function d(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/883df8cc.ec17e966.js b/assets/js/883df8cc.ec17e966.js new file mode 100644 index 000000000..fca20bab1 --- /dev/null +++ b/assets/js/883df8cc.ec17e966.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7238],{6395:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var i=n(4848),s=n(8453);const r={},o="DivideBeforeMultiply",l={id:"detectors/DivideBeforeMultiply",title:"DivideBeforeMultiply",description:"A detector that identifies and corrects instances of division before multiplication to",source:"@site/docs/detectors/DivideBeforeMultiply.md",sourceDirName:"detectors",slug:"/detectors/DivideBeforeMultiply",permalink:"/tools/misti/docs/next/detectors/DivideBeforeMultiply",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/DivideBeforeMultiply.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"ConstantAddress",permalink:"/tools/misti/docs/next/detectors/ConstantAddress"},next:{title:"DumpIsUsed",permalink:"/tools/misti/docs/next/detectors/DumpIsUsed"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function a(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"dividebeforemultiply",children:"DivideBeforeMultiply"}),"\n",(0,i.jsx)(t.p,{children:"A detector that identifies and corrects instances of division before multiplication to\nensure accurate mathematical operations."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsx)(t.p,{children:"Performing division before multiplication can lead to unexpected results due to precision loss and rounding errors:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Precision Loss:"})," Dividing first can result in significant precision loss, especially when dealing with integers or fixed-point numbers."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Rounding Errors:"})," Early division might cause rounding errors that propagate through subsequent calculations."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Unexpected Behavior:"})," Incorrectly ordered operations can lead to incorrect outcomes, making debugging and maintenance more challenging."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Bad: Division before multiplication\nlet result: Int = a / b * c;\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Correct: Multiplication before division\nlet result: Int = a * c / b;\n"})})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>l});var i=n(6540);const s={},r=i.createContext(s);function o(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/888071ca.8652ec85.js b/assets/js/888071ca.8652ec85.js new file mode 100644 index 000000000..3b017ad60 --- /dev/null +++ b/assets/js/888071ca.8652ec85.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9187],{903:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>c,toc:()=>d});var i=n(4848),o=n(8453);const s={},r="ShortCircuitCondition",c={id:"detectors/ShortCircuitCondition",title:"ShortCircuitCondition",description:"A detector that suggests optimizing boolean expressions to leverage short-circuit evaluation.",source:"@site/docs/detectors/ShortCircuitCondition.md",sourceDirName:"detectors",slug:"/detectors/ShortCircuitCondition",permalink:"/tools/misti/docs/next/detectors/ShortCircuitCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/ShortCircuitCondition.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"SendInLoop",permalink:"/tools/misti/docs/next/detectors/SendInLoop"},next:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/next/detectors/StringReceiversOverlap"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"shortcircuitcondition",children:"ShortCircuitCondition"}),"\n",(0,i.jsx)(t.p,{children:"A detector that suggests optimizing boolean expressions to leverage short-circuit evaluation."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["TVM supports short-circuit operations. When using logical AND (",(0,i.jsx)(t.code,{children:"&&"}),") or logical OR (",(0,i.jsx)(t.code,{children:"||"}),") operations,\nplacing constant or cheaper conditions first can prevent unnecessary execution\nof expensive operations when the result is already determined."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"// Bad: Expensive operation is always executed\nif (expensive_function() && constant_false) {\n // ...\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"// Good: Expensive operation is skipped when constant_false is false\nif (constant_false && expensive_function()) {\n // ...\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>c});var i=n(6540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8c01191f.93ad2656.js b/assets/js/8c01191f.93ad2656.js new file mode 100644 index 000000000..5de748bc2 --- /dev/null +++ b/assets/js/8c01191f.93ad2656.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[494],{1017:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="Never-accessed Variables",o={id:"detectors/NeverAccessedVariables",title:"Never-accessed Variables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.2.0/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/0.2.0/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/NeverAccessedVariables.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Divide before Multiply",permalink:"/tools/misti/docs/0.2.0/detectors/DivideBeforeMultiply"},next:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.2.0/detectors/ReadOnlyVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"never-accessed-variables",children:"Never-accessed Variables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the linter highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8c0243db.7de6da6a.js b/assets/js/8c0243db.7de6da6a.js new file mode 100644 index 000000000..303ed81d8 --- /dev/null +++ b/assets/js/8c0243db.7de6da6a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7839],{9520:(e,i,t)=>{t.r(i),t.d(i,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>l,toc:()=>a});var n=t(4848),o=t(8453);const r={},s="Divide before Multiply",l={id:"detectors/DivideBeforeMultiply",title:"Divide before Multiply",description:"A detector that identifies and corrects instances of division before multiplication to",source:"@site/versioned_docs/version-0.1.2/detectors/DivideBeforeMultiply.md",sourceDirName:"detectors",slug:"/detectors/DivideBeforeMultiply",permalink:"/tools/misti/docs/0.1.2/detectors/DivideBeforeMultiply",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/detectors/DivideBeforeMultiply.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Configuration",permalink:"/tools/misti/docs/0.1.2/tutorial/configuration"},next:{title:"Never-accessed Variables",permalink:"/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const i={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"divide-before-multiply",children:"Divide before Multiply"}),"\n",(0,n.jsx)(i.p,{children:"A detector that identifies and corrects instances of division before multiplication to\nensure accurate mathematical operations."}),"\n",(0,n.jsx)(i.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(i.p,{children:"Performing division before multiplication can lead to unexpected results due to precision loss and rounding errors:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:"Precision Loss: Dividing first can result in significant precision loss, especially when dealing with integers or fixed-point numbers."}),"\n",(0,n.jsx)(i.li,{children:"Rounding Errors: Early division might cause rounding errors that propagate through subsequent calculations."}),"\n",(0,n.jsx)(i.li,{children:"Unexpected Behavior: Incorrectly ordered operations can lead to incorrect outcomes, making debugging and maintenance more challenging."}),"\n"]}),"\n",(0,n.jsx)(i.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Bad: Division before multiplication\nlet result: Int = a / b * c;\n"})}),"\n",(0,n.jsx)(i.p,{children:"Use instead:"}),"\n",(0,n.jsx)(i.pre,{children:(0,n.jsx)(i.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Correct: Multiplication before division\nlet result: Int = a * c / b;\n"})})]})}function u(e={}){const{wrapper:i}={...(0,o.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,i,t)=>{t.d(i,{R:()=>s,x:()=>l});var n=t(6540);const o={},r=n.createContext(o);function s(e){const i=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),n.createElement(r.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8c74c05e.09164805.js b/assets/js/8c74c05e.09164805.js new file mode 100644 index 000000000..2ca455e14 --- /dev/null +++ b/assets/js/8c74c05e.09164805.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9198],{8981:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var s=n(4848),t=n(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.2.0/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.2.0/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/hacking/design.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.2.0/hacking/contributing"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.2.0/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const t={},a=s.createContext(t);function o(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8c9dd45b.c7a96e3d.js b/assets/js/8c9dd45b.c7a96e3d.js new file mode 100644 index 000000000..6e8ca768e --- /dev/null +++ b/assets/js/8c9dd45b.c7a96e3d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6286],{7579:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var s=n(4848),t=n(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.2.2/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.2.2/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/hacking/design.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.2.2/hacking/contributing"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.2.2/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const t={},a=s.createContext(t);function o(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8cf7c613.47582d2c.js b/assets/js/8cf7c613.47582d2c.js new file mode 100644 index 000000000..7ab97fd1e --- /dev/null +++ b/assets/js/8cf7c613.47582d2c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6274],{2234:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=i(4848),s=i(8453);const l={},r="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/versioned_docs/version-0.3.1/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/0.3.1/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/tutorial/getting-started.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/0.3.1/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.3.1/tutorial/ci-cd"}},a={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"More usage examples",id:"more-usage-examples",level:2},{value:"Suppressing Specific Detectors",id:"suppressing-specific-detectors",level:3},{value:"Enabling All Detectors",id:"enabling-all-detectors",level:3},{value:"Running in Quiet Mode",id:"running-in-quiet-mode",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,t.jsx)(n.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsx)(n.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Git"}),"\n",(0,t.jsx)(n.li,{children:"Yarn"}),"\n",(0,t.jsx)(n.li,{children:"Node.js version 22 or higher"}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,t.jsxs)(n.p,{children:["Misti is distributed via npm and should be added to your Tact project ",(0,t.jsx)(n.a,{href:"https://github.com/tact-lang/tact?tab=readme-ov-file#installation",children:"in the same way"})," as Tact itself:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @nowarp/misti\n"})}),"\n",(0,t.jsx)(n.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,t.jsx)(n.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,t.jsx)(n.p,{children:"To install the latest development version you should:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Clone Misti: ",(0,t.jsx)(n.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,t.jsxs)(n.li,{children:["Build it: ",(0,t.jsx)(n.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,t.jsxs)(n.li,{children:["Use it in your Tact project: ",(0,t.jsx)(n.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,t.jsx)(n.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"npx misti path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,t.jsxs)(n.p,{children:["You can also add a script to your ",(0,t.jsx)(n.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "npx misti path/to/tact.config.json"\n }\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"more-usage-examples",children:"More usage examples"}),"\n",(0,t.jsxs)(n.p,{children:["Below are a few usage examples for common scenarios when using ",(0,t.jsxs)(n.a,{href:"/tools/misti/docs/0.3.1/tutorial/cli",children:["the ",(0,t.jsx)(n.code,{children:"misti"})," CLI"]}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"suppressing-specific-detectors",children:"Suppressing Specific Detectors"}),"\n",(0,t.jsxs)(n.p,{children:["To run ",(0,t.jsx)(n.code,{children:"misti"})," while suppressing specific detectors, such as ",(0,t.jsx)(n.code,{children:"ReadOnlyVariables"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --suppress ReadOnlyVariables path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enabling-all-detectors",children:"Enabling All Detectors"}),"\n",(0,t.jsxs)(n.p,{children:["Running ",(0,t.jsx)(n.code,{children:"misti"})," with all available built-in detectors enabled:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --all-detectors path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"It is recommended to do that when auditing the project."}),"\n",(0,t.jsx)(n.h3,{id:"running-in-quiet-mode",children:"Running in Quiet Mode"}),"\n",(0,t.jsxs)(n.p,{children:["To suppress all output while running ",(0,t.jsx)(n.code,{children:"misti"})," getting just a return code:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --quiet path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"This might be useful in scripts and CI/CD."}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,t.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>o});var t=i(6540);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8d6fa39c.f2faae22.js b/assets/js/8d6fa39c.f2faae22.js new file mode 100644 index 000000000..ccc634ae7 --- /dev/null +++ b/assets/js/8d6fa39c.f2faae22.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2187],{453:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="Constant Address",a={id:"detectors/ConstantAddress",title:"Constant Address",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/versioned_docs/version-0.2.2/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/0.2.2/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/ConstantAddress.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Zero Address",permalink:"/tools/misti/docs/0.2.2/detectors/ZeroAddress"},next:{title:"Branch Duplicate",permalink:"/tools/misti/docs/0.2.2/detectors/BranchDuplicate"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constant-address",children:"Constant Address"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8d91c04d.ef1dbebb.js b/assets/js/8d91c04d.ef1dbebb.js new file mode 100644 index 000000000..0da6ba324 --- /dev/null +++ b/assets/js/8d91c04d.ef1dbebb.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4024],{2850:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var o=t(4848),s=t(8453);const i={},r="UnboundLoops",a={id:"detectors/UnboundLoops",title:"UnboundLoops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.3.0/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.3.0/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/UnboundLoops.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/0.3.0/detectors/StringReceiversOverlap"},next:{title:"ZeroAddress",permalink:"/tools/misti/docs/0.3.0/detectors/ZeroAddress"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"unboundloops",children:"UnboundLoops"}),"\n",(0,o.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,o.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Unexpected Behavior: Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."}),"\n",(0,o.jsx)(n.li,{children:"Out-of-gas Attacks: Continuous looping without termination can lead to out-of-gas attacks."}),"\n",(0,o.jsx)(n.li,{children:"DoS Attacks: Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Use instead:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var o=t(6540);const s={},i=o.createContext(s);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8df82fb6.5a9830a2.js b/assets/js/8df82fb6.5a9830a2.js new file mode 100644 index 000000000..f58baff0e --- /dev/null +++ b/assets/js/8df82fb6.5a9830a2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[301],{2964:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="Never-accessed Variables",o={id:"detectors/NeverAccessedVariables",title:"Never-accessed Variables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.2.1/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/0.2.1/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/NeverAccessedVariables.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Divide before Multiply",permalink:"/tools/misti/docs/0.2.1/detectors/DivideBeforeMultiply"},next:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"never-accessed-variables",children:"Never-accessed Variables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the linter highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8e426e62.f6ea35a1.js b/assets/js/8e426e62.f6ea35a1.js new file mode 100644 index 000000000..7cdd95dd7 --- /dev/null +++ b/assets/js/8e426e62.f6ea35a1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2991],{8966:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>a});var n=s(4848),i=s(8453);const o={},d="DumpIsUsed",r={id:"detectors/DumpIsUsed",title:"DumpIsUsed",description:"An optional detector that highlights all the dump debug prints.",source:"@site/versioned_docs/version-0.4.0/detectors/DumpIsUsed.md",sourceDirName:"detectors",slug:"/detectors/DumpIsUsed",permalink:"/tools/misti/docs/0.4.0/detectors/DumpIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/DumpIsUsed.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply"},next:{title:"DuplicatedCondition",permalink:"/tools/misti/docs/0.4.0/detectors/DuplicatedCondition"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dumpisused",children:"DumpIsUsed"}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"dump"})," debug prints."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"dump"})," function is a debug print that shouldn't be in the final code.\nEven though the compiler removes it in production, its presence suggests the\ndeveloper was debugging something. This can flag areas where issues might exist,\nso auditors should take a closer look at these parts of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = (RANDOM_SEED >> half_shift) &\n (MAGIC_CONSTANT << DIVIDE_BY_TWO) ^ shift_mask;\n dump(combined); // Suspicious: Highlighted by the detector\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = this.seed ^ shift_mask\n // OK: The code was reviewed and simplified; `dump` was removed\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>d,x:()=>r});var n=s(6540);const i={},o=n.createContext(i);function d(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/8e8fe4d7.7a82fd74.js b/assets/js/8e8fe4d7.7a82fd74.js new file mode 100644 index 000000000..8f99ce6e8 --- /dev/null +++ b/assets/js/8e8fe4d7.7a82fd74.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9924],{2917:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>l,toc:()=>d});var n=i(4848),o=i(8453);const r={},s="DivideBeforeMultiply",l={id:"detectors/DivideBeforeMultiply",title:"DivideBeforeMultiply",description:"A detector that identifies and corrects instances of division before multiplication to",source:"@site/versioned_docs/version-0.3.1/detectors/DivideBeforeMultiply.md",sourceDirName:"detectors",slug:"/detectors/DivideBeforeMultiply",permalink:"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/DivideBeforeMultiply.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"ConstantAddress",permalink:"/tools/misti/docs/0.3.1/detectors/ConstantAddress"},next:{title:"DumpIsUsed",permalink:"/tools/misti/docs/0.3.1/detectors/DumpIsUsed"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function a(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dividebeforemultiply",children:"DivideBeforeMultiply"}),"\n",(0,n.jsx)(t.p,{children:"A detector that identifies and corrects instances of division before multiplication to\nensure accurate mathematical operations."}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Performing division before multiplication can lead to unexpected results due to precision loss and rounding errors:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Precision Loss: Dividing first can result in significant precision loss, especially when dealing with integers or fixed-point numbers."}),"\n",(0,n.jsx)(t.li,{children:"Rounding Errors: Early division might cause rounding errors that propagate through subsequent calculations."}),"\n",(0,n.jsx)(t.li,{children:"Unexpected Behavior: Incorrectly ordered operations can lead to incorrect outcomes, making debugging and maintenance more challenging."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Bad: Division before multiplication\nlet result: Int = a / b * c;\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Correct: Multiplication before division\nlet result: Int = a * c / b;\n"})})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>l});var n=i(6540);const o={},r=n.createContext(o);function s(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9016a10e.f412061d.js b/assets/js/9016a10e.f412061d.js new file mode 100644 index 000000000..8ee2e58a3 --- /dev/null +++ b/assets/js/9016a10e.f412061d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2906],{7216:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>l,frontMatter:()=>i,metadata:()=>d,toc:()=>c});var s=n(4848),o=n(8453);const i={},r="UnusedExpressionResult",d={id:"detectors/UnusedExpressionResult",title:"UnusedExpressionResult",description:"A detector that identifies expression statements whose result is unused.",source:"@site/docs/detectors/UnusedExpressionResult.md",sourceDirName:"detectors",slug:"/detectors/UnusedExpressionResult",permalink:"/tools/misti/docs/next/detectors/UnusedExpressionResult",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/UnusedExpressionResult.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"UnboundMap",permalink:"/tools/misti/docs/next/detectors/UnboundMap"},next:{title:"UnusedOptional",permalink:"/tools/misti/docs/next/detectors/UnusedOptional"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function u(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"unusedexpressionresult",children:"UnusedExpressionResult"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies expression statements whose result is unused."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Expression statements that don't alter the contract's state and whose results are not used\ncan lead to inefficiency, dead code, and potential confusion. They add unnecessary complexity\nwithout contributing to the logic or state of the contract."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"self.foo == 3; // Warning: unused boolean expression\ninc(a); // Warning: unused return value\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"self.foo = 3; // Fixed: corrected assignment\nnewValue = inc(a); // OK: result is now used\nlet _ = inc(a); // OK: explicitly ignored\n"})})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(u,{...e})}):u(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>d});var s=n(6540);const o={},i=s.createContext(o);function r(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9081c3e5.771bfadf.js b/assets/js/9081c3e5.771bfadf.js new file mode 100644 index 000000000..354bf47b8 --- /dev/null +++ b/assets/js/9081c3e5.771bfadf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6805],{1445:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>d,metadata:()=>o,toc:()=>l});var r=n(4848),s=n(8453);const d={},i="PreferredStdlibApi",o={id:"detectors/PreferredStdlibApi",title:"PreferredStdlibApi",description:"An optional detector that flags the use of advanced functions from the standard library.",source:"@site/versioned_docs/version-0.5/detectors/PreferredStdlibApi.md",sourceDirName:"detectors",slug:"/detectors/PreferredStdlibApi",permalink:"/tools/misti/docs/detectors/PreferredStdlibApi",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/PreferredStdlibApi.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/detectors/PreferAugmentedAssign"},next:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/detectors/ReadOnlyVariables"}},a={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"preferredstdlibapi",children:"PreferredStdlibApi"}),"\n",(0,r.jsx)(t.p,{children:"An optional detector that flags the use of advanced functions from the standard library."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"Auditors should pay extra attention to these functions, as incorrect usage can\nlead to subtle bugs. Safer stdlib alternatives should be preferred in the code."}),"\n",(0,r.jsx)(t.p,{children:"Supported functions:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:["Use ",(0,r.jsx)(t.code,{children:"send"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativesendmessage",children:(0,r.jsx)(t.code,{children:"nativeSendMessage"})})]}),"\n",(0,r.jsxs)(t.li,{children:["Prefer ",(0,r.jsx)(t.code,{children:"randomInt"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativerandom",children:(0,r.jsx)(t.code,{children:"nativeRandom"})})]}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"let pkg: Slice = msg.transfer;\nlet _seqno: Int = pkg.loadInt(32);\nlet mode: Int = pkg.loadInt(8);\nlet body: Cell = pkg.loadRef();\n// Bad: prefer `send` to avoid low-level manipulation of Slice\nnativeSendMessage(body, mode);\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// Safer: More explicit definition of the send operation\nsend(SendParameters{ value: amount,\n to: self.owner,\n mode: mode,\n body: beginCell().endCell() });\n"})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(6540);const s={},d=r.createContext(s);function i(e){const t=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(d.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/90b5d830.c162588e.js b/assets/js/90b5d830.c162588e.js new file mode 100644 index 000000000..279f1db66 --- /dev/null +++ b/assets/js/90b5d830.c162588e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4318],{7230:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>n,metadata:()=>c,toc:()=>l});var s=r(4848),i=r(8453);const n={id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},o="Detectors Overview",c={id:"detectors",title:"Detectors Overview",description:"Here's a list of all the detectors:",source:"@site/versioned_docs/version-0.2.2/detectors.md",sourceDirName:".",slug:"/detectors",permalink:"/tools/misti/docs/0.2.2/detectors",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors.md",tags:[],version:"0.2.2",frontMatter:{id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},sidebar:"sidebar",previous:{title:"Using with Blueprint",permalink:"/tools/misti/docs/0.2.2/tutorial/blueprint"},next:{title:"Divide before Multiply",permalink:"/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply"}},d={},l=[];function a(e){const t={a:"a",code:"code",h1:"h1",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"detectors-overview",children:"Detectors Overview"}),"\n",(0,s.jsx)(t.p,{children:"Here's a list of all the detectors:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/DivideBeforeMultiply",children:"Divide before Multiply"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/NeverAccessedVariables",children:"Never-accessed Variables"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/ReadOnlyVariables",children:"Read-only Variables"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/UnboundLoops",children:"Unbound Loops"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/ZeroAddress",children:"Zero Address"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/ConstantAddress",children:"Constant Address"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/BranchDuplicate",children:"Branch Duplicate"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsxs)(t.a,{href:"./detectors/DumpIsUsed",children:[(0,s.jsx)(t.code,{children:"dump"})," Is Used"]})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/FieldDoubleInit",children:"Field Initialized Twice"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/PreferAugmentedAssign",children:"Prefer Augmented Assignment"})}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"Each detector is designed to catch specific issues in your code. Click on any of them to learn more."})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>o,x:()=>c});var s=r(6540);const i={},n=s.createContext(i);function o(e){const t=s.useContext(n);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/91acf703.e9b6829a.js b/assets/js/91acf703.e9b6829a.js new file mode 100644 index 000000000..d84c339c8 --- /dev/null +++ b/assets/js/91acf703.e9b6829a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3291],{7619:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>o,metadata:()=>i,toc:()=>c});var n=t(4848),r=t(8453);const o={},d="ZeroAddress",i={id:"detectors/ZeroAddress",title:"ZeroAddress",description:"A detector that identifies uses of the zero address.",source:"@site/versioned_docs/version-0.4.0/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/0.4.0/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/ZeroAddress.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"UnusedOptional",permalink:"/tools/misti/docs/0.4.0/detectors/UnusedOptional"},next:{title:"Tools Overview",permalink:"/tools/misti/docs/0.4.0/tools"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"zeroaddress",children:"ZeroAddress"}),"\n",(0,n.jsx)(s.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(s.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(s.p,{children:"Use instead:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initialization.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:s}={...(0,r.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>d,x:()=>i});var n=t(6540);const r={},o=n.createContext(r);function d(e){const s=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),n.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/91ee281c.f53980f2.js b/assets/js/91ee281c.f53980f2.js new file mode 100644 index 000000000..b2914edbe --- /dev/null +++ b/assets/js/91ee281c.f53980f2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2397],{3505:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>o});var i=s(4848),l=s(8453);const t={},d="Command-Line Interface",r={id:"tutorial/cli",title:"Command-Line Interface",description:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each.",source:"@site/versioned_docs/version-0.3.0/tutorial/cli.md",sourceDirName:"tutorial",slug:"/tutorial/cli",permalink:"/tools/misti/docs/0.3.0/tutorial/cli",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/tutorial/cli.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.3.0/tutorial/ci-cd"},next:{title:"Configuration",permalink:"/tools/misti/docs/0.3.0/tutorial/configuration"}},c={},o=[{value:"--dump-cfg <json|dot>
",id:"--dump-cfg-jsondot",level:3},{value:"--dump-ast
",id:"--dump-ast",level:3},{value:"--dump-output <PATH>
",id:"--dump-output-path",level:3},{value:"--dump-include-stdlib
",id:"--dump-include-stdlib",level:3},{value:"--dump-config
",id:"--dump-config",level:3},{value:"--souffle-binary <PATH>
",id:"--souffle-binary-path",level:3},{value:"--souffle-path <PATH>
",id:"--souffle-path-path",level:3},{value:"--souffle-verbose
",id:"--souffle-verbose",level:3},{value:"--tact-stdlib-path <PATH>
",id:"--tact-stdlib-path-path",level:3},{value:"--verbose
",id:"--verbose",level:3},{value:"--quiet
",id:"--quiet",level:3},{value:"--detectors <name|path:name>
",id:"--detectors-namepathname",level:3},{value:"--suppress <names>
",id:"--suppress-names",level:3},{value:"--all-detectors
",id:"--all-detectors",level:3},{value:"--config <PATH>
",id:"--config-path",level:3},{value:"--new-detector <PATH>
",id:"--new-detector-path",level:3}];function a(e){const n={code:"code",h1:"h1",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"command-line-interface",children:"Command-Line Interface"}),"\n",(0,i.jsx)(n.p,{children:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each."}),"\n",(0,i.jsx)(n.h3,{id:"--dump-cfg-jsondot",children:(0,i.jsx)(n.code,{children:"--dump-cfg"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Dumps the Control Flow Graph (CFG) in the requested format: JSON or Graphviz Dot."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-ast",children:(0,i.jsx)(n.code,{children:"--dump-ast"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Dumps the Abstract Syntax Tree (AST) in JSON format."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-output-path",children:(0,i.jsx)(n.code,{children:"--dump-output "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Specifies the directory to save the AST/CFG dump. If ",(0,i.jsx)(n.code,{children:" "})," is ",(0,i.jsx)(n.code,{children:"-"}),", then the output is sent to stdout."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": Value of ",(0,i.jsx)(n.code,{children:"DUMP_STDOUT_PATH"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-include-stdlib",children:(0,i.jsx)(n.code,{children:"--dump-include-stdlib"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Includes standard library components in the AST/CFG dump."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-config",children:(0,i.jsx)(n.code,{children:"--dump-config"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Dumps the Misti JSON configuration file in use."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--souffle-binary-path",children:(0,i.jsx)(n.code,{children:"--souffle-binary "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Path to the Souffl\xe9 binary."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:'"souffle"'})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--souffle-path-path",children:(0,i.jsx)(n.code,{children:"--souffle-path "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Directory to save the generated Souffl\xe9 files."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:'"/tmp/misti/souffle"'})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--souffle-verbose",children:(0,i.jsx)(n.code,{children:"--souffle-verbose"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Generates human-readable, but more verbose, Souffl\xe9 files."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--tact-stdlib-path-path",children:(0,i.jsx)(n.code,{children:"--tact-stdlib-path "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Path to the Tact standard library."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--verbose",children:(0,i.jsx)(n.code,{children:"--verbose"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Enables verbose output."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--quiet",children:(0,i.jsx)(n.code,{children:"--quiet"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Suppresses all output."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--detectors-namepathname",children:(0,i.jsx)(n.code,{children:"--detectors "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": A comma-separated list of detectors to enable."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Argument Validation"}),": Requires a non-empty list of detector names."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--suppress-names",children:(0,i.jsx)(n.code,{children:"--suppress "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": A comma-separated list of detector names to suppress."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Argument Validation"}),": Requires a non-empty list of detector names."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--all-detectors",children:(0,i.jsx)(n.code,{children:"--all-detectors"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Enables all the available built-in detectors."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--config-path",children:(0,i.jsx)(n.code,{children:"--config "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Path to the Misti configuration file."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--new-detector-path",children:(0,i.jsx)(n.code,{children:"--new-detector "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Creates a new custom detector at the specified path."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>d,x:()=>r});var i=s(6540);const l={},t=i.createContext(l);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/926d5e8d.9358cd7a.js b/assets/js/926d5e8d.9358cd7a.js new file mode 100644 index 000000000..7a9cd697e --- /dev/null +++ b/assets/js/926d5e8d.9358cd7a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2526],{2737:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>p,frontMatter:()=>i,metadata:()=>r,toc:()=>a});var o=t(4848),s=t(8453);const i={},d="SendInLoop",r={id:"detectors/SendInLoop",title:"SendInLoop",description:"An optional detector that identifies send functions being called inside loops.",source:"@site/versioned_docs/version-0.5/detectors/SendInLoop.md",sourceDirName:"detectors",slug:"/detectors/SendInLoop",permalink:"/tools/misti/docs/detectors/SendInLoop",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/SendInLoop.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/detectors/ReadOnlyVariables"},next:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/detectors/StringReceiversOverlap"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"sendinloop",children:"SendInLoop"}),"\n",(0,o.jsx)(n.p,{children:"An optional detector that identifies send functions being called inside loops."}),"\n",(0,o.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsx)(n.p,{children:"Calling send functions inside loops can lead to unintended consequences, such as\nexcessive message sending, increased gas consumption, and potential race conditions.\nLoops with send calls should be refactored to avoid these issues. This detector helps\nflag such code, prompting the developer to reconsider the design."}),"\n",(0,o.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"fun exampleWhileLoop(limit: Int, owner: Address) {\n let i = 0;\n while (i < limit) {\n send(SendParameters{ // Highlighted: An auditor should review the loop\n to: owner,\n value: 0,\n bounce: false,\n body: Msg{ a: i }.toCell()\n });\n i += 1;\n }\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>d,x:()=>r});var o=t(6540);const s={},i=o.createContext(s);function d(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:d(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/94d07e36.7f27f910.js b/assets/js/94d07e36.7f27f910.js new file mode 100644 index 000000000..6db9b0258 --- /dev/null +++ b/assets/js/94d07e36.7f27f910.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8235],{2345:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var i=t(4848),r=t(8453);const o={},a="EnsurePrgSeed",s={id:"detectors/EnsurePrgSeed",title:"EnsurePrgSeed",description:"A detector that identifies all calls to nativeRandom and nativeRandomInterval",source:"@site/versioned_docs/version-0.4.0/detectors/EnsurePrgSeed.md",sourceDirName:"detectors",slug:"/detectors/EnsurePrgSeed",permalink:"/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/EnsurePrgSeed.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"DuplicatedCondition",permalink:"/tools/misti/docs/0.4.0/detectors/DuplicatedCondition"},next:{title:"FalseCondition",permalink:"/tools/misti/docs/0.4.0/detectors/FalseCondition"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"ensureprgseed",children:"EnsurePrgSeed"}),"\n",(0,i.jsxs)(n.p,{children:["A detector that identifies all calls to ",(0,i.jsx)(n.code,{children:"nativeRandom"})," and ",(0,i.jsx)(n.code,{children:"nativeRandomInterval"}),"\nwithout a preceding PRG seed initialization."]}),"\n",(0,i.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(n.p,{children:["Using ",(0,i.jsx)(n.code,{children:"nativeRandom"})," or ",(0,i.jsx)(n.code,{children:"nativeRandomInterval"})," without first initializing the PRG seed via\n",(0,i.jsx)(n.code,{children:"nativePrepareRandom"}),", ",(0,i.jsx)(n.code,{children:"nativeRandomize"}),", or ",(0,i.jsx)(n.code,{children:"nativeRandomizeLt"})," may lead to unintended behavior\nor weak random number generation. This detector ensures that PRG seed initialization\nis always performed before any use of random functions, enhancing contract security."]}),"\n",(0,i.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"// Bad: `nativeRandom` is used without prior PRG seed initialization\nfun generateRandomValue(): Int {\n return nativeRandom()\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Use instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"fun test(): Int {\n nativePrepareRandom();\n}\n\n// OK: PRG has been initialized somewhere in the contract\nfun generateRandomValue(): Int {\n return nativeRandom()\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>s});var i=t(6540);const r={},o=i.createContext(r);function a(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/96e77fcb.3fb77893.js b/assets/js/96e77fcb.3fb77893.js new file mode 100644 index 000000000..27ed8fc6d --- /dev/null +++ b/assets/js/96e77fcb.3fb77893.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5922],{7021:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>d,toc:()=>c});var s=n(4848),r=n(8453);const i={},o="PreferAugmentedAssign",d={id:"detectors/PreferAugmentedAssign",title:"PreferAugmentedAssign",description:"Detects non-idiomatic statements that can be written using augmented assignment",source:"@site/versioned_docs/version-0.3.0/detectors/PreferAugmentedAssign.md",sourceDirName:"detectors",slug:"/detectors/PreferAugmentedAssign",permalink:"/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/PreferAugmentedAssign.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables"},next:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/0.3.0/detectors/PreferredStdlibApi"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"preferaugmentedassign",children:"PreferAugmentedAssign"}),"\n",(0,s.jsxs)(t.p,{children:["Detects non-idiomatic statements that can be written using augmented assignment\noperators like ",(0,s.jsx)(t.code,{children:"+="}),", ",(0,s.jsx)(t.code,{children:"-="}),", etc."]}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Using augmented assignment operations improves the readability of the source code\nand reduces the risk of mistakes, such as those that occur during copy-pasting\nand refactoring code."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue = (msgValue - ctx.readForwardFee());\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue -= ctx.readForwardFee());\n"})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>d});var s=n(6540);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/972c9666.e5b493f7.js b/assets/js/972c9666.e5b493f7.js new file mode 100644 index 000000000..dd93657bc --- /dev/null +++ b/assets/js/972c9666.e5b493f7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1179],{590:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var s=n(4848),i=n(8453);const r={},o="Prefer Augmented Assignment",a={id:"detectors/PreferAugmentedAssign",title:"Prefer Augmented Assignment",description:"Detects non-idiomatic statements that can be written using augmented assignment operators like +=, -=, etc.",source:"@site/versioned_docs/version-0.2.0/detectors/PreferAugmentedAssign.md",sourceDirName:"detectors",slug:"/detectors/PreferAugmentedAssign",permalink:"/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/PreferAugmentedAssign.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Field Initialized Twice",permalink:"/tools/misti/docs/0.2.0/detectors/FieldDoubleInit"},next:{title:"Contributing",permalink:"/tools/misti/docs/0.2.0/hacking/contributing"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"prefer-augmented-assignment",children:"Prefer Augmented Assignment"}),"\n",(0,s.jsxs)(t.p,{children:["Detects non-idiomatic statements that can be written using augmented assignment operators like ",(0,s.jsx)(t.code,{children:"+="}),", ",(0,s.jsx)(t.code,{children:"-="}),", etc."]}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Using augmented assignment operations improves the readability of the source code and reduces the risk of mistakes, such as those that occur during copy-pasting and refactoring code."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue = (msgValue - ctx.readForwardFee());\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue -= ctx.readForwardFee());\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const i={},r=s.createContext(i);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/987a8a5d.bdfcfd74.js b/assets/js/987a8a5d.bdfcfd74.js new file mode 100644 index 000000000..0edfc6836 --- /dev/null +++ b/assets/js/987a8a5d.bdfcfd74.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1318],{9490:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var t=o(4848),s=o(8453);const i={},r="Unbound Loops",a={id:"detectors/UnboundLoops",title:"Unbound Loops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.1.2/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.1.2/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/detectors/UnboundLoops.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables"},next:{title:"Zero Address",permalink:"/tools/misti/docs/0.1.2/detectors/ZeroAddress"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"unbound-loops",children:"Unbound Loops"}),"\n",(0,t.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,t.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,t.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Unexpected Behavior: Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."}),"\n",(0,t.jsx)(n.li,{children:"Out-of-gas Attacks: Continuous looping without termination can lead to out-of-gas attacks."}),"\n",(0,t.jsx)(n.li,{children:"DoS Attacks: Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Use instead:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var t=o(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/988b076a.3beed1a8.js b/assets/js/988b076a.3beed1a8.js new file mode 100644 index 000000000..79670be66 --- /dev/null +++ b/assets/js/988b076a.3beed1a8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9758],{2426:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var t=i(4848),s=i(8453);const o={},r="Contributing Guide",a={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/versioned_docs/version-0.3.0/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/0.3.0/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/hacking/contributing.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"ZeroAddress",permalink:"/tools/misti/docs/0.3.0/detectors/ZeroAddress"},next:{title:"Design Overview",permalink:"/tools/misti/docs/0.3.0/hacking/design"}},c={},d=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["All guidelines and additional hacking tips are available in the repo. For low-level details not present in the docs, refer to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/HACKING.md",children:"HACKING.md"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>a});var t=i(6540);const s={},o=t.createContext(s);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9983337e.ea12e3f1.js b/assets/js/9983337e.ea12e3f1.js new file mode 100644 index 000000000..e0575f1aa --- /dev/null +++ b/assets/js/9983337e.ea12e3f1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3320],{1337:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>d,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>a});var t=n(4848),i=n(8453);const o={},r="SuspiciousMessageMode",c={id:"detectors/SuspiciousMessageMode",title:"SuspiciousMessageMode",description:"Detects suspicious usage of the mode field in SendParameters struct instances.",source:"@site/versioned_docs/version-0.5/detectors/SuspiciousMessageMode.md",sourceDirName:"detectors",slug:"/detectors/SuspiciousMessageMode",permalink:"/tools/misti/docs/detectors/SuspiciousMessageMode",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/SuspiciousMessageMode.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/detectors/StringReceiversOverlap"},next:{title:"UnboundLoop",permalink:"/tools/misti/docs/detectors/UnboundLoop"}},d={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(s.h1,{id:"suspiciousmessagemode",children:"SuspiciousMessageMode"}),"\n",(0,t.jsxs)(s.p,{children:["Detects suspicious usage of the ",(0,t.jsx)(s.code,{children:"mode"})," field in ",(0,t.jsx)(s.code,{children:"SendParameters"})," struct instances."]}),"\n",(0,t.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,t.jsxs)(s.p,{children:["Incorrect usage of the ",(0,t.jsx)(s.code,{children:"mode"})," field in ",(0,t.jsx)(s.code,{children:"SendParameters"})," can lead to unintended behavior when sending messages,\nsuch as incorrect flags being set, which can cause security vulnerabilities or unexpected contract behavior."]}),"\n",(0,t.jsx)(s.p,{children:(0,t.jsx)(s.strong,{children:"What it checks:"})}),"\n",(0,t.jsxs)(s.ul,{children:["\n",(0,t.jsxs)(s.li,{children:["Ensures that the ",(0,t.jsx)(s.code,{children:"mode"})," expression only uses the bitwise OR operator ",(0,t.jsx)(s.code,{children:"|"}),"."]}),"\n",(0,t.jsx)(s.li,{children:"Warns if integer literals are used instead of symbolic constants."}),"\n",(0,t.jsxs)(s.li,{children:["Warns if the same flag is used multiple times in the ",(0,t.jsx)(s.code,{children:"mode"})," expression."]}),"\n"]}),"\n",(0,t.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,t.jsx)(s.pre,{children:(0,t.jsx)(s.code,{className:"language-tact",children:"// Suspicious usage:\nsend(SendParameters{\n to: recipient,\n value: amount,\n mode: SendRemainingBalance | SendRemainingBalance // Bad: Duplicate flag\n});\n\n// Correct usage:\nsend(SendParameters{\n to: recipient,\n value: amount,\n mode: SendRemainingBalance | SendDestroyIfZero // Ok\n});\n"})})]})}function u(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,t.jsx)(s,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,s,n)=>{n.d(s,{R:()=>r,x:()=>c});var t=n(6540);const i={},o=t.createContext(i);function r(e){const s=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),t.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/9fedf60a.5a24888e.js b/assets/js/9fedf60a.5a24888e.js new file mode 100644 index 000000000..5d29c0eff --- /dev/null +++ b/assets/js/9fedf60a.5a24888e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3388],{9957:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var n=t(4848),o=t(8453);const r={},d="ZeroAddress",i={id:"detectors/ZeroAddress",title:"ZeroAddress",description:"A detector that identifies uses of the zero address.",source:"@site/versioned_docs/version-0.3.1/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/0.3.1/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/ZeroAddress.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"UnboundLoops",permalink:"/tools/misti/docs/0.3.1/detectors/UnboundLoops"},next:{title:"Contributing",permalink:"/tools/misti/docs/0.3.1/hacking/contributing"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"zeroaddress",children:"ZeroAddress"}),"\n",(0,n.jsx)(s.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(s.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(s.p,{children:"Use instead:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initialization.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>d,x:()=>i});var n=t(6540);const o={},r=n.createContext(o);function d(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a291c19d.f1235972.js b/assets/js/a291c19d.f1235972.js new file mode 100644 index 000000000..49d81f028 --- /dev/null +++ b/assets/js/a291c19d.f1235972.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4903],{7937:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=n(4848),a=n(8453);const r={},s="InheritedStateMutation",o={id:"detectors/InheritedStateMutation",title:"InheritedStateMutation",description:"An optional detector that highlights all instances where inherited trait variables",source:"@site/versioned_docs/version-0.4.0/detectors/InheritedStateMutation.md",sourceDirName:"detectors",slug:"/detectors/InheritedStateMutation",permalink:"/tools/misti/docs/0.4.0/detectors/InheritedStateMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/InheritedStateMutation.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/0.4.0/detectors/FieldDoubleInit"},next:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"inheritedstatemutation",children:"InheritedStateMutation"}),"\n",(0,i.jsx)(t.p,{children:"An optional detector that highlights all instances where inherited trait variables\nare directly modified."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Traits should provide setter methods to ensure that invariants related to their\nstate are preserved. Directly modifying trait variables (e.g., ",(0,i.jsx)(t.code,{children:"self.traitVar = 42"}),")\ncan violate these invariants, leading to potential bugs or security vulnerabilities.\nThis detector warns when such direct modifications occur, prompting further review\nby auditors."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"trait T {\n balance: Int;\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.balance = 100; // Suspicious: Highlighted by the detector\n }\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:'trait T {\n balance: Int;\n fun setBalance(newBalance: Int) {\n require(newBalance > 0, "balance cannot be negative"); // Invariant check\n self.balance = newBalance;\n }\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.setBalance(100); // OK: Invariant preserved\n }\n}\n'})})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var i=n(6540);const a={},r=i.createContext(a);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a2e1ac23.ed8d2af3.js b/assets/js/a2e1ac23.ed8d2af3.js new file mode 100644 index 000000000..bd3af6552 --- /dev/null +++ b/assets/js/a2e1ac23.ed8d2af3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9977],{1682:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var o=t(4848),s=t(8453);const i={},r="UnboundLoop",a={id:"detectors/UnboundLoop",title:"UnboundLoop",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/docs/detectors/UnboundLoop.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoop",permalink:"/tools/misti/docs/next/detectors/UnboundLoop",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/UnboundLoop.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"SuspiciousMessageMode",permalink:"/tools/misti/docs/next/detectors/SuspiciousMessageMode"},next:{title:"UnboundMap",permalink:"/tools/misti/docs/next/detectors/UnboundMap"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"unboundloop",children:"UnboundLoop"}),"\n",(0,o.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,o.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Unexpected Behavior:"})," Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Out-of-gas Attacks:"})," Continuous looping without termination can lead to out-of-gas attacks."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"DoS Attacks:"})," Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Use instead:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var o=t(6540);const s={},i=o.createContext(s);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a3df6930.3fd81736.js b/assets/js/a3df6930.3fd81736.js new file mode 100644 index 000000000..33d36ea75 --- /dev/null +++ b/assets/js/a3df6930.3fd81736.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[767],{4152:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var t=i(4848),s=i(8453);const l={},r="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/versioned_docs/version-0.4.0/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/0.4.0/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/tutorial/getting-started.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/0.4.0/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.4.0/tutorial/ci-cd"}},a={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"More usage examples",id:"more-usage-examples",level:2},{value:"Suppressing Specific Detectors",id:"suppressing-specific-detectors",level:3},{value:"Enabling All Detectors",id:"enabling-all-detectors",level:3},{value:"Running in Quiet Mode",id:"running-in-quiet-mode",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,t.jsx)(n.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,t.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,t.jsx)(n.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Git"}),"\n",(0,t.jsx)(n.li,{children:"Yarn"}),"\n",(0,t.jsx)(n.li,{children:"Node.js version 22 or higher"}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,t.jsxs)(n.p,{children:["Misti is distributed via npm and should be added to your Tact project ",(0,t.jsx)(n.a,{href:"https://github.com/tact-lang/tact?tab=readme-ov-file#installation",children:"in the same way"})," as Tact itself:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn add @nowarp/misti\n"})}),"\n",(0,t.jsx)(n.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,t.jsx)(n.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,t.jsx)(n.p,{children:"To install the latest development version you should:"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["Clone Misti: ",(0,t.jsx)(n.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,t.jsxs)(n.li,{children:["Build it: ",(0,t.jsx)(n.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,t.jsxs)(n.li,{children:["Use it in your Tact project: ",(0,t.jsx)(n.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,t.jsx)(n.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"npx misti path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,t.jsxs)(n.p,{children:["You can also add a script to your ",(0,t.jsx)(n.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "npx misti path/to/tact.config.json"\n }\n}\n'})}),"\n",(0,t.jsx)(n.h2,{id:"more-usage-examples",children:"More usage examples"}),"\n",(0,t.jsxs)(n.p,{children:["Below are a few usage examples for common scenarios when using ",(0,t.jsxs)(n.a,{href:"/tools/misti/docs/0.4.0/tutorial/cli",children:["the ",(0,t.jsx)(n.code,{children:"misti"})," CLI"]}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"suppressing-specific-detectors",children:"Suppressing Specific Detectors"}),"\n",(0,t.jsxs)(n.p,{children:["To run ",(0,t.jsx)(n.code,{children:"misti"})," while suppressing specific detectors, such as ",(0,t.jsx)(n.code,{children:"ReadOnlyVariables"}),":"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --suppress ReadOnlyVariables path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.h3,{id:"enabling-all-detectors",children:"Enabling All Detectors"}),"\n",(0,t.jsxs)(n.p,{children:["Running ",(0,t.jsx)(n.code,{children:"misti"})," with all available built-in detectors enabled:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --all-detectors path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"It is recommended to do that when auditing the project."}),"\n",(0,t.jsx)(n.h3,{id:"running-in-quiet-mode",children:"Running in Quiet Mode"}),"\n",(0,t.jsxs)(n.p,{children:["To suppress all output while running ",(0,t.jsx)(n.code,{children:"misti"})," getting just a return code:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"npx misti --quiet path/to/tact.config.json\n"})}),"\n",(0,t.jsx)(n.p,{children:"This might be useful in scripts and CI/CD."}),"\n",(0,t.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,t.jsxs)(n.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,t.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>o});var t=i(6540);const s={},l=t.createContext(s);function r(e){const n=t.useContext(l);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a4516edb.19e6546c.js b/assets/js/a4516edb.19e6546c.js new file mode 100644 index 000000000..9c10ed9e9 --- /dev/null +++ b/assets/js/a4516edb.19e6546c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9415],{1664:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"0.1.2","label":"0.1.2","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-0.1.2","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/0.1.2/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/0.1.2/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/0.1.2/tutorial/configuration","docId":"tutorial/configuration","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Detectors","items":[{"type":"link","label":"Divide before Multiply","href":"/tools/misti/docs/0.1.2/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"Never-accessed Variables","href":"/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"Read-only Variables","href":"/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"Unbound Loops","href":"/tools/misti/docs/0.1.2/detectors/UnboundLoops","docId":"detectors/UnboundLoops","unlisted":false},{"type":"link","label":"Zero Address","href":"/tools/misti/docs/0.1.2/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/0.1.2/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Design Overview","href":"/tools/misti/docs/0.1.2/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/0.1.2/hacking/souffle","docId":"hacking/souffle","unlisted":false},{"type":"link","label":"Tools","href":"/tools/misti/docs/0.1.2/hacking/tools","docId":"hacking/tools","unlisted":false},{"type":"link","label":"Custom Detectors","href":"/tools/misti/docs/0.1.2/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false},{"type":"link","label":"CHANGELOG","href":"/tools/misti/docs/0.1.2/hacking/CHANGELOG","docId":"hacking/CHANGELOG","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"Divide before Multiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"Never-accessed Variables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"Read-only Variables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/UnboundLoops":{"id":"detectors/UnboundLoops","title":"Unbound Loops","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"Zero Address","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/CHANGELOG":{"id":"hacking/CHANGELOG","title":"Changelog","description":"All notable changes to this project are documented in this file.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"hacking/tools":{"id":"hacking/tools","title":"Tools Guide","description":"This page describes the internal analyzer tools available in Misti to aid in development and debugging.","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/a5055d90.d691b43f.js b/assets/js/a5055d90.d691b43f.js new file mode 100644 index 000000000..0f8483250 --- /dev/null +++ b/assets/js/a5055d90.d691b43f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5484],{535:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>l,default:()=>h,frontMatter:()=>a,metadata:()=>o,toc:()=>c});var s=n(4848),t=n(8453);const a={},l="Design Overview",o={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/docs/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/next/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/hacking/design.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpImports",permalink:"/tools/misti/docs/next/tools/DumpImports"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/next/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>l,x:()=>o});var s=n(6540);const t={},a=s.createContext(t);function l(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function o(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:l(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a66f2ff0.c39f76e5.js b/assets/js/a66f2ff0.c39f76e5.js new file mode 100644 index 000000000..e915c4230 --- /dev/null +++ b/assets/js/a66f2ff0.c39f76e5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1332],{5467:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var o=t(4848),s=t(8453);const i={},r="UnboundLoops",a={id:"detectors/UnboundLoops",title:"UnboundLoops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.3.1/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.3.1/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/UnboundLoops.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap"},next:{title:"ZeroAddress",permalink:"/tools/misti/docs/0.3.1/detectors/ZeroAddress"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"unboundloops",children:"UnboundLoops"}),"\n",(0,o.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,o.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Unexpected Behavior: Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."}),"\n",(0,o.jsx)(n.li,{children:"Out-of-gas Attacks: Continuous looping without termination can lead to out-of-gas attacks."}),"\n",(0,o.jsx)(n.li,{children:"DoS Attacks: Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Use instead:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var o=t(6540);const s={},i=o.createContext(s);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a7456010.c6eb9a57.js b/assets/js/a7456010.c6eb9a57.js new file mode 100644 index 000000000..34e25e855 --- /dev/null +++ b/assets/js/a7456010.c6eb9a57.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1235],{8552:e=>{e.exports=JSON.parse('{"name":"docusaurus-plugin-content-pages","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/a7bd4aaa.1b32332e.js b/assets/js/a7bd4aaa.1b32332e.js new file mode 100644 index 000000000..48f57569c --- /dev/null +++ b/assets/js/a7bd4aaa.1b32332e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7098],{4532:(n,e,s)=>{s.r(e),s.d(e,{default:()=>x});s(6540);var r=s(1003),o=s(2967),t=s(2252),i=s(2831),c=s(1463),u=s(4848);function a(n){const{version:e}=n;return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(c.A,{version:e.version,tag:(0,o.tU)(e.pluginId,e.version)}),(0,u.jsx)(r.be,{children:e.noIndex&&(0,u.jsx)("meta",{name:"robots",content:"noindex, nofollow"})})]})}function l(n){const{version:e,route:s}=n;return(0,u.jsx)(r.e3,{className:e.className,children:(0,u.jsx)(t.n,{version:e,children:(0,i.v)(s.routes)})})}function x(n){return(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(a,{...n}),(0,u.jsx)(l,{...n})]})}}}]); \ No newline at end of file diff --git a/assets/js/a7eb4927.90a54648.js b/assets/js/a7eb4927.90a54648.js new file mode 100644 index 000000000..5e726a0e1 --- /dev/null +++ b/assets/js/a7eb4927.90a54648.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8262],{936:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var s=n(4848),t=n(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.3.0/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.3.0/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/hacking/design.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.3.0/hacking/contributing"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.3.0/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const t={},a=s.createContext(t);function o(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a8c496ca.06cbb22b.js b/assets/js/a8c496ca.06cbb22b.js new file mode 100644 index 000000000..01170d4bf --- /dev/null +++ b/assets/js/a8c496ca.06cbb22b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9304],{8812:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var n=s(4848),i=s(8453);const o={},d="DumpIsUsed",r={id:"detectors/DumpIsUsed",title:"DumpIsUsed",description:"An optional detector that highlights all the dump function calls.",source:"@site/versioned_docs/version-0.3.1/detectors/DumpIsUsed.md",sourceDirName:"detectors",slug:"/detectors/DumpIsUsed",permalink:"/tools/misti/docs/0.3.1/detectors/DumpIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/DumpIsUsed.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply"},next:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function a(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dumpisused",children:"DumpIsUsed"}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"dump"})," function calls."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"dump"})," function is a debug print that shouldn't be in the final code.\nEven though the compiler removes it in production, its presence suggests the\ndeveloper was debugging something. This can flag areas where issues might exist,\nso auditors should take a closer look at these parts of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = (RANDOM_SEED >> half_shift) &\n (MAGIC_CONSTANT << DIVIDE_BY_TWO) ^ shift_mask;\n dump(combined); // Suspicious: Highlighted by the detector\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = this.seed ^ shift_mask\n // OK: The code was reviewed and simplified; `dump` was removed\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>d,x:()=>r});var n=s(6540);const i={},o=n.createContext(i);function d(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/a8d7d639.ed43e771.js b/assets/js/a8d7d639.ed43e771.js new file mode 100644 index 000000000..137ba89f6 --- /dev/null +++ b/assets/js/a8d7d639.ed43e771.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6701],{1831:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"0.2.0","label":"0.2.0","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-0.2.0","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/0.2.0/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/0.2.0/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"CI/CD Integration","href":"/tools/misti/docs/0.2.0/tutorial/ci-cd","docId":"tutorial/ci-cd","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/0.2.0/tutorial/configuration","docId":"tutorial/configuration","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Detectors Overview","href":"/tools/misti/docs/0.2.0/detectors","docId":"detectors","unlisted":false},{"type":"category","label":"Detectors","items":[{"type":"link","label":"Divide before Multiply","href":"/tools/misti/docs/0.2.0/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"Never-accessed Variables","href":"/tools/misti/docs/0.2.0/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"Read-only Variables","href":"/tools/misti/docs/0.2.0/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"Unbound Loops","href":"/tools/misti/docs/0.2.0/detectors/UnboundLoops","docId":"detectors/UnboundLoops","unlisted":false},{"type":"link","label":"Zero Address","href":"/tools/misti/docs/0.2.0/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false},{"type":"link","label":"Constant Address","href":"/tools/misti/docs/0.2.0/detectors/ConstantAddress","docId":"detectors/ConstantAddress","unlisted":false},{"type":"link","label":"Branch Duplicate","href":"/tools/misti/docs/0.2.0/detectors/BranchDuplicate","docId":"detectors/BranchDuplicate","unlisted":false},{"type":"link","label":"`dump` Is Used","href":"/tools/misti/docs/0.2.0/detectors/DumpIsUsed","docId":"detectors/DumpIsUsed","unlisted":false},{"type":"link","label":"Field Initialized Twice","href":"/tools/misti/docs/0.2.0/detectors/FieldDoubleInit","docId":"detectors/FieldDoubleInit","unlisted":false},{"type":"link","label":"Prefer Augmented Assignment","href":"/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign","docId":"detectors/PreferAugmentedAssign","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/0.2.0/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Design Overview","href":"/tools/misti/docs/0.2.0/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/0.2.0/hacking/souffle","docId":"hacking/souffle","unlisted":false},{"type":"link","label":"Tools","href":"/tools/misti/docs/0.2.0/hacking/tools","docId":"hacking/tools","unlisted":false},{"type":"link","label":"Custom Detectors","href":"/tools/misti/docs/0.2.0/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"detectors":{"id":"detectors","title":"Detectors Overview","description":"Here\'s a list of all the detectors:","sidebar":"sidebar"},"detectors/BranchDuplicate":{"id":"detectors/BranchDuplicate","title":"Branch Duplicate","description":"Detector that reports duplicated code in conditional branches.","sidebar":"sidebar"},"detectors/ConstantAddress":{"id":"detectors/ConstantAddress","title":"Constant Address","description":"An optional detector that highlights all the constant addresses appearing in the source code.","sidebar":"sidebar"},"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"Divide before Multiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/DumpIsUsed":{"id":"detectors/DumpIsUsed","title":"dump Is Used","description":"An optional detector that highlights all the dump function calls.","sidebar":"sidebar"},"detectors/FieldDoubleInit":{"id":"detectors/FieldDoubleInit","title":"Field Initialized Twice","description":"A detector that highlights cases where a field is initialized both in the init function and at the point of definition.","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"Never-accessed Variables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/PreferAugmentedAssign":{"id":"detectors/PreferAugmentedAssign","title":"Prefer Augmented Assignment","description":"Detects non-idiomatic statements that can be written using augmented assignment operators like +=, -=, etc.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"Read-only Variables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/UnboundLoops":{"id":"detectors/UnboundLoops","title":"Unbound Loops","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"Zero Address","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"hacking/tools":{"id":"hacking/tools","title":"Tools Guide","description":"This page describes the internal analyzer tools available in Misti to aid in development and debugging.","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tutorial/ci-cd":{"id":"tutorial/ci-cd","title":"Integrating Misti into CI/CD","description":"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/a94703ab.9f24e801.js b/assets/js/a94703ab.9f24e801.js new file mode 100644 index 000000000..d81e92f43 --- /dev/null +++ b/assets/js/a94703ab.9f24e801.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9048],{2559:(e,t,n)=>{n.r(t),n.d(t,{default:()=>be});var a=n(6540),o=n(4164),i=n(1003),s=n(7559),l=n(1754),r=n(6588),c=n(1312),d=n(3104),u=n(5062);const m={backToTopButton:"backToTopButton_sjWU",backToTopButtonShow:"backToTopButtonShow_xfvO"};var b=n(4848);function h(){const{shown:e,scrollToTop:t}=function(e){let{threshold:t}=e;const[n,o]=(0,a.useState)(!1),i=(0,a.useRef)(!1),{startScroll:s,cancelScroll:l}=(0,d.gk)();return(0,d.Mq)(((e,n)=>{let{scrollY:a}=e;const s=n?.scrollY;s&&(i.current?i.current=!1:a>=s?(l(),o(!1)):a {e.location.hash&&(i.current=!0,o(!1))})),{shown:n,scrollToTop:()=>s(0)}}({threshold:300});return(0,b.jsx)("button",{"aria-label":(0,c.T)({id:"theme.BackToTopButton.buttonAriaLabel",message:"Scroll back to top",description:"The ARIA label for the back to top button"}),className:(0,o.A)("clean-btn",s.G.common.backToTopButton,m.backToTopButton,e&&m.backToTopButtonShow),type:"button",onClick:t})}var p=n(3109),x=n(6347),f=n(4581),j=n(6342),_=n(3465);function v(e){return(0,b.jsx)("svg",{width:"20",height:"20","aria-hidden":"true",...e,children:(0,b.jsxs)("g",{fill:"#7a7a7a",children:[(0,b.jsx)("path",{d:"M9.992 10.023c0 .2-.062.399-.172.547l-4.996 7.492a.982.982 0 01-.828.454H1c-.55 0-1-.453-1-1 0-.2.059-.403.168-.551l4.629-6.942L.168 3.078A.939.939 0 010 2.528c0-.548.45-.997 1-.997h2.996c.352 0 .649.18.828.45L9.82 9.472c.11.148.172.347.172.55zm0 0"}),(0,b.jsx)("path",{d:"M19.98 10.023c0 .2-.058.399-.168.547l-4.996 7.492a.987.987 0 01-.828.454h-3c-.547 0-.996-.453-.996-1 0-.2.059-.403.168-.551l4.625-6.942-4.625-6.945a.939.939 0 01-.168-.55 1 1 0 01.996-.997h3c.348 0 .649.18.828.45l4.996 7.492c.11.148.168.347.168.55zm0 0"})]})})}const g={collapseSidebarButton:"collapseSidebarButton_PEFL",collapseSidebarButtonIcon:"collapseSidebarButtonIcon_kv0_"};function A(e){let{onClick:t}=e;return(0,b.jsx)("button",{type:"button",title:(0,c.T)({id:"theme.docs.sidebar.collapseButtonTitle",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),"aria-label":(0,c.T)({id:"theme.docs.sidebar.collapseButtonAriaLabel",message:"Collapse sidebar",description:"The title attribute for collapse button of doc sidebar"}),className:(0,o.A)("button button--secondary button--outline",g.collapseSidebarButton),onClick:t,children:(0,b.jsx)(v,{className:g.collapseSidebarButtonIcon})})}var k=n(5041),C=n(9532);const S=Symbol("EmptyContext"),T=a.createContext(S);function N(e){let{children:t}=e;const[n,o]=(0,a.useState)(null),i=(0,a.useMemo)((()=>({expandedItem:n,setExpandedItem:o})),[n]);return(0,b.jsx)(T.Provider,{value:i,children:t})}var I=n(1422),B=n(9169),y=n(8774),w=n(2303);function L(e){let{collapsed:t,categoryLabel:n,onClick:a}=e;return(0,b.jsx)("button",{"aria-label":t?(0,c.T)({id:"theme.DocSidebarItem.expandCategoryAriaLabel",message:"Expand sidebar category '{label}'",description:"The ARIA label to expand the sidebar category"},{label:n}):(0,c.T)({id:"theme.DocSidebarItem.collapseCategoryAriaLabel",message:"Collapse sidebar category '{label}'",description:"The ARIA label to collapse the sidebar category"},{label:n}),"aria-expanded":!t,type:"button",className:"clean-btn menu__caret",onClick:a})}function E(e){let{item:t,onItemClick:n,activePath:i,level:r,index:c,...d}=e;const{items:u,label:m,collapsible:h,className:p,href:x}=t,{docs:{sidebar:{autoCollapseCategories:f}}}=(0,j.p)(),_=function(e){const t=(0,w.A)();return(0,a.useMemo)((()=>e.href&&!e.linkUnlisted?e.href:!t&&e.collapsible?(0,l.Nr)(e):void 0),[e,t])}(t),v=(0,l.w8)(t,i),g=(0,B.ys)(x,i),{collapsed:A,setCollapsed:k}=(0,I.u)({initialState:()=>!!h&&(!v&&t.collapsed)}),{expandedItem:N,setExpandedItem:E}=function(){const e=(0,a.useContext)(T);if(e===S)throw new C.dV("DocSidebarItemsExpandedStateProvider");return e}(),M=function(e){void 0===e&&(e=!A),E(e?null:c),k(e)};return function(e){let{isActive:t,collapsed:n,updateCollapsed:o}=e;const i=(0,C.ZC)(t);(0,a.useEffect)((()=>{t&&!i&&n&&o(!1)}),[t,i,n,o])}({isActive:v,collapsed:A,updateCollapsed:M}),(0,a.useEffect)((()=>{h&&null!=N&&N!==c&&f&&k(!0)}),[h,N,c,k,f]),(0,b.jsxs)("li",{className:(0,o.A)(s.G.docs.docSidebarItemCategory,s.G.docs.docSidebarItemCategoryLevel(r),"menu__list-item",{"menu__list-item--collapsed":A},p),children:[(0,b.jsxs)("div",{className:(0,o.A)("menu__list-item-collapsible",{"menu__list-item-collapsible--active":g}),children:[(0,b.jsx)(y.A,{className:(0,o.A)("menu__link",{"menu__link--sublist":h,"menu__link--sublist-caret":!x&&h,"menu__link--active":v}),onClick:h?e=>{n?.(t),x?M(!1):(e.preventDefault(),M())}:()=>{n?.(t)},"aria-current":g?"page":void 0,role:h&&!x?"button":void 0,"aria-expanded":h&&!x?!A:void 0,href:h?_??"#":_,...d,children:m}),x&&h&&(0,b.jsx)(L,{collapsed:A,categoryLabel:m,onClick:e=>{e.preventDefault(),M()}})]}),(0,b.jsx)(I.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:A,children:(0,b.jsx)(U,{items:u,tabIndex:A?-1:0,onItemClick:n,activePath:i,level:r+1})})]})}var M=n(6654),H=n(3186);const G={menuExternalLink:"menuExternalLink_NmtK"};function W(e){let{item:t,onItemClick:n,activePath:a,level:i,index:r,...c}=e;const{href:d,label:u,className:m,autoAddBaseUrl:h}=t,p=(0,l.w8)(t,a),x=(0,M.A)(d);return(0,b.jsx)("li",{className:(0,o.A)(s.G.docs.docSidebarItemLink,s.G.docs.docSidebarItemLinkLevel(i),"menu__list-item",m),children:(0,b.jsxs)(y.A,{className:(0,o.A)("menu__link",!x&&G.menuExternalLink,{"menu__link--active":p}),autoAddBaseUrl:h,"aria-current":p?"page":void 0,to:d,...x&&{onClick:n?()=>n(t):void 0},...c,children:[u,!x&&(0,b.jsx)(H.A,{})]})},u)}const P={menuHtmlItem:"menuHtmlItem_M9Kj"};function R(e){let{item:t,level:n,index:a}=e;const{value:i,defaultStyle:l,className:r}=t;return(0,b.jsx)("li",{className:(0,o.A)(s.G.docs.docSidebarItemLink,s.G.docs.docSidebarItemLinkLevel(n),l&&[P.menuHtmlItem,"menu__list-item"],r),dangerouslySetInnerHTML:{__html:i}},a)}function D(e){let{item:t,...n}=e;switch(t.type){case"category":return(0,b.jsx)(E,{item:t,...n});case"html":return(0,b.jsx)(R,{item:t,...n});default:return(0,b.jsx)(W,{item:t,...n})}}function F(e){let{items:t,...n}=e;const a=(0,l.Y)(t,n.activePath);return(0,b.jsx)(N,{children:a.map(((e,t)=>(0,b.jsx)(D,{item:e,index:t,...n},t)))})}const U=(0,a.memo)(F),V={menu:"menu_SIkG",menuWithAnnouncementBar:"menuWithAnnouncementBar_GW3s"};function Y(e){let{path:t,sidebar:n,className:i}=e;const l=function(){const{isActive:e}=(0,k.M)(),[t,n]=(0,a.useState)(e);return(0,d.Mq)((t=>{let{scrollY:a}=t;e&&n(0===a)}),[e]),e&&t}();return(0,b.jsx)("nav",{"aria-label":(0,c.T)({id:"theme.docs.sidebar.navAriaLabel",message:"Docs sidebar",description:"The ARIA label for the sidebar navigation"}),className:(0,o.A)("menu thin-scrollbar",V.menu,l&&V.menuWithAnnouncementBar,i),children:(0,b.jsx)("ul",{className:(0,o.A)(s.G.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(U,{items:n,activePath:t,level:1})})})}const K="sidebar_njMd",z="sidebarWithHideableNavbar_wUlq",q="sidebarHidden_VK0M",O="sidebarLogo_isFc";function J(e){let{path:t,sidebar:n,onCollapse:a,isHidden:i}=e;const{navbar:{hideOnScroll:s},docs:{sidebar:{hideable:l}}}=(0,j.p)();return(0,b.jsxs)("div",{className:(0,o.A)(K,s&&z,i&&q),children:[s&&(0,b.jsx)(_.A,{tabIndex:-1,className:O}),(0,b.jsx)(Y,{path:t,sidebar:n}),l&&(0,b.jsx)(A,{onClick:a})]})}const Q=a.memo(J);var X=n(5600),Z=n(9876);const $=e=>{let{sidebar:t,path:n}=e;const a=(0,Z.M)();return(0,b.jsx)("ul",{className:(0,o.A)(s.G.docs.docSidebarMenu,"menu__list"),children:(0,b.jsx)(U,{items:t,activePath:n,onItemClick:e=>{"category"===e.type&&e.href&&a.toggle(),"link"===e.type&&a.toggle()},level:1})})};function ee(e){return(0,b.jsx)(X.GX,{component:$,props:e})}const te=a.memo(ee);function ne(e){const t=(0,f.l)(),n="desktop"===t||"ssr"===t,a="mobile"===t;return(0,b.jsxs)(b.Fragment,{children:[n&&(0,b.jsx)(Q,{...e}),a&&(0,b.jsx)(te,{...e})]})}const ae={expandButton:"expandButton_TmdG",expandButtonIcon:"expandButtonIcon_i1dp"};function oe(e){let{toggleSidebar:t}=e;return(0,b.jsx)("div",{className:ae.expandButton,title:(0,c.T)({id:"theme.docs.sidebar.expandButtonTitle",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),"aria-label":(0,c.T)({id:"theme.docs.sidebar.expandButtonAriaLabel",message:"Expand sidebar",description:"The ARIA label and title attribute for expand button of doc sidebar"}),tabIndex:0,role:"button",onKeyDown:t,onClick:t,children:(0,b.jsx)(v,{className:ae.expandButtonIcon})})}const ie={docSidebarContainer:"docSidebarContainer_YfHR",docSidebarContainerHidden:"docSidebarContainerHidden_DPk8",sidebarViewport:"sidebarViewport_aRkj"};function se(e){let{children:t}=e;const n=(0,r.t)();return(0,b.jsx)(a.Fragment,{children:t},n?.name??"noSidebar")}function le(e){let{sidebar:t,hiddenSidebarContainer:n,setHiddenSidebarContainer:i}=e;const{pathname:l}=(0,x.zy)(),[r,c]=(0,a.useState)(!1),d=(0,a.useCallback)((()=>{r&&c(!1),!r&&(0,p.O)()&&c(!0),i((e=>!e))}),[i,r]);return(0,b.jsx)("aside",{className:(0,o.A)(s.G.docs.docSidebarContainer,ie.docSidebarContainer,n&&ie.docSidebarContainerHidden),onTransitionEnd:e=>{e.currentTarget.classList.contains(ie.docSidebarContainer)&&n&&c(!0)},children:(0,b.jsx)(se,{children:(0,b.jsxs)("div",{className:(0,o.A)(ie.sidebarViewport,r&&ie.sidebarViewportHidden),children:[(0,b.jsx)(ne,{sidebar:t,path:l,onCollapse:d,isHidden:r}),r&&(0,b.jsx)(oe,{toggleSidebar:d})]})})})}const re={docMainContainer:"docMainContainer_TBSr",docMainContainerEnhanced:"docMainContainerEnhanced_lQrH",docItemWrapperEnhanced:"docItemWrapperEnhanced_JWYK"};function ce(e){let{hiddenSidebarContainer:t,children:n}=e;const a=(0,r.t)();return(0,b.jsx)("main",{className:(0,o.A)(re.docMainContainer,(t||!a)&&re.docMainContainerEnhanced),children:(0,b.jsx)("div",{className:(0,o.A)("container padding-top--md padding-bottom--lg",re.docItemWrapper,t&&re.docItemWrapperEnhanced),children:n})})}const de={docRoot:"docRoot_UBD9",docsWrapper:"docsWrapper_hBAB"};function ue(e){let{children:t}=e;const n=(0,r.t)(),[o,i]=(0,a.useState)(!1);return(0,b.jsxs)("div",{className:de.docsWrapper,children:[(0,b.jsx)(h,{}),(0,b.jsxs)("div",{className:de.docRoot,children:[n&&(0,b.jsx)(le,{sidebar:n.items,hiddenSidebarContainer:o,setHiddenSidebarContainer:i}),(0,b.jsx)(ce,{hiddenSidebarContainer:o,children:t})]})]})}var me=n(3363);function be(e){const t=(0,l.B5)(e);if(!t)return(0,b.jsx)(me.A,{});const{docElement:n,sidebarName:a,sidebarItems:c}=t;return(0,b.jsx)(i.e3,{className:(0,o.A)(s.G.page.docsDocPage),children:(0,b.jsx)(r.V,{name:a,items:c,children:(0,b.jsx)(ue,{children:n})})})}},3363:(e,t,n)=>{n.d(t,{A:()=>l});n(6540);var a=n(4164),o=n(1312),i=n(1107),s=n(4848);function l(e){let{className:t}=e;return(0,s.jsx)("main",{className:(0,a.A)("container margin-vert--xl",t),children:(0,s.jsx)("div",{className:"row",children:(0,s.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,s.jsx)(i.A,{as:"h1",className:"hero__title",children:(0,s.jsx)(o.A,{id:"theme.NotFound.title",description:"The title of the 404 page",children:"Page Not Found"})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.A,{id:"theme.NotFound.p1",description:"The first paragraph of the 404 page",children:"We could not find what you were looking for."})}),(0,s.jsx)("p",{children:(0,s.jsx)(o.A,{id:"theme.NotFound.p2",description:"The 2nd paragraph of the 404 page",children:"Please contact the owner of the site that linked you to the original URL and let them know their link is broken."})})]})})})}}}]); \ No newline at end of file diff --git a/assets/js/aac87eb6.6b5bbfc3.js b/assets/js/aac87eb6.6b5bbfc3.js new file mode 100644 index 000000000..793856084 --- /dev/null +++ b/assets/js/aac87eb6.6b5bbfc3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[684],{4646:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="BranchDuplicate",o={id:"detectors/BranchDuplicate",title:"BranchDuplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.3.1/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/0.3.1/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/BranchDuplicate.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"AsmIsUsed",permalink:"/tools/misti/docs/0.3.1/detectors/AsmIsUsed"},next:{title:"ConstantAddress",permalink:"/tools/misti/docs/0.3.1/detectors/ConstantAddress"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branchduplicate",children:"BranchDuplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ab64460a.f029dca5.js b/assets/js/ab64460a.f029dca5.js new file mode 100644 index 000000000..8ee47c194 --- /dev/null +++ b/assets/js/ab64460a.f029dca5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2467],{6083:(e,n,o)=>{o.r(n),o.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>u,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var t=o(4848),s=o(8453);const i={},r="UnboundLoop",a={id:"detectors/UnboundLoop",title:"UnboundLoop",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.5/detectors/UnboundLoop.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoop",permalink:"/tools/misti/docs/detectors/UnboundLoop",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/UnboundLoop.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"SuspiciousMessageMode",permalink:"/tools/misti/docs/detectors/SuspiciousMessageMode"},next:{title:"UnboundMap",permalink:"/tools/misti/docs/detectors/UnboundMap"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"unboundloop",children:"UnboundLoop"}),"\n",(0,t.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,t.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,t.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Unexpected Behavior:"})," Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Out-of-gas Attacks:"})," Continuous looping without termination can lead to out-of-gas attacks."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"DoS Attacks:"})," Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."]}),"\n"]}),"\n",(0,t.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,t.jsx)(n.p,{children:"Use instead:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,o)=>{o.d(n,{R:()=>r,x:()=>a});var t=o(6540);const s={},i=t.createContext(s);function r(e){const n=t.useContext(i);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aba21aa0.d087865c.js b/assets/js/aba21aa0.d087865c.js new file mode 100644 index 000000000..549d21e19 --- /dev/null +++ b/assets/js/aba21aa0.d087865c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5742],{7093:u=>{u.exports=JSON.parse('{"name":"docusaurus-plugin-content-docs","id":"default"}')}}]); \ No newline at end of file diff --git a/assets/js/acef80f0.ccd7a032.js b/assets/js/acef80f0.ccd7a032.js new file mode 100644 index 000000000..faa9e946d --- /dev/null +++ b/assets/js/acef80f0.ccd7a032.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1468],{2492:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var s=n(4848),t=n(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.2.1/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.2.1/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/hacking/design.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.2.1/hacking/contributing"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.2.1/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const t={},a=s.createContext(t);function o(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/aee0b8cc.034e2877.js b/assets/js/aee0b8cc.034e2877.js new file mode 100644 index 000000000..a83a0f1dc --- /dev/null +++ b/assets/js/aee0b8cc.034e2877.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5622],{3023:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>r,default:()=>l,frontMatter:()=>i,metadata:()=>d,toc:()=>c});var n=s(4848),o=s(8453);const i={},r="DumpAst",d={id:"tools/DumpAst",title:"DumpAst",description:"The DumpAst tool in Misti enables users to output the Abstract Syntax Tree (AST) of project modules in JSON format. This is particularly useful when writing custom detectors, as it helps understand the structure and components of the code.",source:"@site/versioned_docs/version-0.4.0/tools/DumpAst.md",sourceDirName:"tools",slug:"/tools/DumpAst",permalink:"/tools/misti/docs/0.4.0/tools/DumpAst",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/tools/DumpAst.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Tools Overview",permalink:"/tools/misti/docs/0.4.0/tools"},next:{title:"DumpCfg",permalink:"/tools/misti/docs/0.4.0/tools/DumpCfg"}},a={},c=[{value:"Usage",id:"usage",level:2},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function u(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dumpast",children:"DumpAst"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"DumpAst"})," tool in Misti enables users to output the ",(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Abstract_syntax_tree",children:"Abstract Syntax Tree (AST)"})," of project modules in JSON format. This is particularly useful when writing custom detectors, as it helps understand the structure and components of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(t.p,{children:"To dump the AST in JSON format, use the following command:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'npx misti -t "DumpAst" \n'})}),"\n",(0,n.jsxs)(t.p,{children:["If you wish to include the standard library in the dump, set ",(0,n.jsx)(t.code,{children:"dumpStdlib"})," to ",(0,n.jsx)(t.code,{children:"true"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'npx misti -t "DumpAst:dumpStdlib=true" \n'})}),"\n",(0,n.jsx)(t.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(t.p,{children:["The AST provides a detailed breakdown of code components, offering insights into its structure. This is essential when creating or debugging ",(0,n.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/hacking/custom-detector",children:"custom detectors"}),", as it allows a deeper understanding of how code is represented internally by the analyzer."]}),"\n",(0,n.jsxs)(t.p,{children:["By leveraging the ",(0,n.jsx)(t.code,{children:"DumpAst"})," tool, developers can more effectively navigate and interpret the project's syntax, supporting the development of accurate and efficient detectors."]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>d});var n=s(6540);const o={},i=n.createContext(o);function r(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b05af762.c54dcfb2.js b/assets/js/b05af762.c54dcfb2.js new file mode 100644 index 000000000..cab741cf9 --- /dev/null +++ b/assets/js/b05af762.c54dcfb2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6670],{6683:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>a,frontMatter:()=>i,metadata:()=>n,toc:()=>l});var r=s(4848),d=s(8453);const i={id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},o="Detectors Overview",n={id:"detectors",title:"Detectors Overview",description:"Misti currently supports 15 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:",source:"@site/versioned_docs/version-0.3.0/detectors.md",sourceDirName:".",slug:"/detectors",permalink:"/tools/misti/docs/0.3.0/detectors",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors.md",tags:[],version:"0.3.0",frontMatter:{id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},sidebar:"sidebar",previous:{title:"Using with Blueprint",permalink:"/tools/misti/docs/0.3.0/tutorial/blueprint"},next:{title:"ArgCopyMutation",permalink:"/tools/misti/docs/0.3.0/detectors/ArgCopyMutation"}},c={},l=[];function h(e){const t={a:"a",code:"code",h1:"h1",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,d.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"detectors-overview",children:"Detectors Overview"}),"\n",(0,r.jsx)(t.p,{children:"Misti currently supports 15 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"#"}),(0,r.jsx)(t.th,{children:"Detector"}),(0,r.jsx)(t.th,{children:"Requires Souffl\xe9"}),(0,r.jsx)(t.th,{children:"Enabled by default"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"1"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/ArgCopyMutation",children:"ArgCopyMutation"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"2"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/AsmIsUsed",children:"AsmIsUsed"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"3"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/BranchDuplicate",children:"BranchDuplicate"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"4"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/ConstantAddress",children:"ConstantAddress"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"5"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/DivideBeforeMultiply",children:"DivideBeforeMultiply"})}),(0,r.jsx)(t.td,{children:"\u2714"}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"6"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/DumpIsUsed",children:"DumpIsUsed"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"7"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/FieldDoubleInit",children:"FieldDoubleInit"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"8"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/InheritedStateMutation",children:"InheritedStateMutation"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"9"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables",children:"NeverAccessedVariables"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"10"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign",children:"PreferAugmentedAssign"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"11"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/PreferredStdlibApi",children:"PreferredStdlibApi"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"12"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/ReadOnlyVariables",children:"ReadOnlyVariables"})}),(0,r.jsx)(t.td,{children:"\u2714"}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"13"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/StringReceiversOverlap",children:"StringReceiversOverlap"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"14"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/UnboundLoops",children:"UnboundLoops"})}),(0,r.jsx)(t.td,{children:"\u2714"}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"15"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/detectors/ZeroAddress",children:"ZeroAddress"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]})]})]}),"\n",(0,r.jsxs)(t.p,{children:["Some of the detectors require ",(0,r.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})," to be installed. If no Souffl\xe9 installation is found, these detectors won't be executed."]}),"\n",(0,r.jsxs)(t.p,{children:["A few detectors are optional and aimed at auditors to help uncover subtle issues in the source code. To enable all detectors, use the ",(0,r.jsx)(t.code,{children:"--all-detectors"})," option. You can find a full list of configuration options on the ",(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.0/tutorial/configuration",children:"configuration page"}),"."]}),"\n",(0,r.jsx)(t.p,{children:"Each detector targets a specific type of problem in your code. Click on the detector name to learn more."})]})}function a(e={}){const{wrapper:t}={...(0,d.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>o,x:()=>n});var r=s(6540);const d={},i=r.createContext(d);function o(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function n(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(d):e.components||d:o(e.components),r.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b12d76e5.d3ad221e.js b/assets/js/b12d76e5.d3ad221e.js new file mode 100644 index 000000000..252b9c857 --- /dev/null +++ b/assets/js/b12d76e5.d3ad221e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9359],{9813:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>d,toc:()=>a});var i=n(4848),o=n(8453);const s={},r="DuplicatedCondition",d={id:"detectors/DuplicatedCondition",title:"DuplicatedCondition",description:"A detector that finds duplicated conditions appearing in conditional expressions.",source:"@site/docs/detectors/DuplicatedCondition.md",sourceDirName:"detectors",slug:"/detectors/DuplicatedCondition",permalink:"/tools/misti/docs/next/detectors/DuplicatedCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/DuplicatedCondition.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpIsUsed",permalink:"/tools/misti/docs/next/detectors/DumpIsUsed"},next:{title:"EnsurePrgSeed",permalink:"/tools/misti/docs/next/detectors/EnsurePrgSeed"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"duplicatedcondition",children:"DuplicatedCondition"}),"\n",(0,i.jsx)(t.p,{children:"A detector that finds duplicated conditions appearing in conditional expressions."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsx)(t.p,{children:"Typically, these cases are developer errors caused by copy-pasting code, leading\nto unreachable code."}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"fun test(a: Int): Int {\n if (a < 1) { return 1; }\n else if (a > 4) { return 2; }\n // Bad: A developer copy-pasted the condition\n else if (a > 4) { return 3; }\n return 4;\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"fun test(a: Int): Int {\n if (a < 1) { return 1; }\n else if (a > 4) { return 2; }\n // OK: Fixed\n else if (a < x) { return 3; }\n return 4;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>d});var i=n(6540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b2b6aa30.3aa9416e.js b/assets/js/b2b6aa30.3aa9416e.js new file mode 100644 index 000000000..ffb7819c2 --- /dev/null +++ b/assets/js/b2b6aa30.3aa9416e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6216],{7828:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={},r="OptimalMathFunction",a={id:"detectors/OptimalMathFunction",title:"OptimalMathFunction",description:"A detector that highlights standard library math function calls that have more gas-efficient alternatives.",source:"@site/versioned_docs/version-0.5/detectors/OptimalMathFunction.md",sourceDirName:"detectors",slug:"/detectors/OptimalMathFunction",permalink:"/tools/misti/docs/detectors/OptimalMathFunction",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/OptimalMathFunction.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/detectors/NeverAccessedVariables"},next:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/detectors/PreferAugmentedAssign"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"optimalmathfunction",children:"OptimalMathFunction"}),"\n",(0,i.jsx)(t.p,{children:"A detector that highlights standard library math function calls that have more gas-efficient alternatives."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Tact supports ",(0,i.jsx)(t.code,{children:"log2"}),"/",(0,i.jsx)(t.code,{children:"pow2"})," functions, which are more gas-efficient than ",(0,i.jsx)(t.code,{children:"log(x, 2)"}),"/",(0,i.jsx)(t.code,{children:"pow(x, 2)"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"log(x, 2);\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"log2(x)\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b3799bec.86c01a35.js b/assets/js/b3799bec.86c01a35.js new file mode 100644 index 000000000..6bee2bf96 --- /dev/null +++ b/assets/js/b3799bec.86c01a35.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8031],{4207:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="Constant Address",a={id:"detectors/ConstantAddress",title:"Constant Address",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/versioned_docs/version-0.2.0/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/0.2.0/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/ConstantAddress.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Zero Address",permalink:"/tools/misti/docs/0.2.0/detectors/ZeroAddress"},next:{title:"Branch Duplicate",permalink:"/tools/misti/docs/0.2.0/detectors/BranchDuplicate"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constant-address",children:"Constant Address"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b64540ae.f5677375.js b/assets/js/b64540ae.f5677375.js new file mode 100644 index 000000000..0e288ff2a --- /dev/null +++ b/assets/js/b64540ae.f5677375.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6412],{8560:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var i=s(4848),t=s(8453);const l={},r="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/docs/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/next/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/tutorial/getting-started.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/next/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/next/tutorial/ci-cd"}},a={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"More usage examples",id:"more-usage-examples",level:2},{value:"Suppressing Warnings",id:"suppressing-warnings",level:3},{value:"Enabling All Detectors",id:"enabling-all-detectors",level:3},{value:"Running in Quiet Mode",id:"running-in-quiet-mode",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,i.jsx)(n.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,i.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsx)(n.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Git"}),"\n",(0,i.jsx)(n.li,{children:"Yarn"}),"\n",(0,i.jsx)(n.li,{children:"Node.js version 22 or higher"}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"npm install -g @nowarp/misti\n"})}),"\n",(0,i.jsx)(n.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,i.jsx)(n.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,i.jsx)(n.p,{children:"To install the latest development version you should:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Clone Misti: ",(0,i.jsx)(n.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,i.jsxs)(n.li,{children:["Build it: ",(0,i.jsx)(n.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use it in your Tact project: ",(0,i.jsx)(n.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,i.jsx)(n.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"misti path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,i.jsxs)(n.p,{children:["You can also add a script to your ",(0,i.jsx)(n.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "misti path/to/tact.config.json"\n }\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"more-usage-examples",children:"More usage examples"}),"\n",(0,i.jsxs)(n.p,{children:["Below are a few usage examples for common scenarios when using ",(0,i.jsxs)(n.a,{href:"/tools/misti/docs/next/tutorial/cli",children:["the ",(0,i.jsx)(n.code,{children:"misti"})," CLI"]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"suppressing-warnings",children:"Suppressing Warnings"}),"\n",(0,i.jsxs)(n.p,{children:["If you want to suppress some warnings in specific places of source code, you should use the ",(0,i.jsx)(n.code,{children:"@misti:suppress"})," annotations in the comment on the previous line, for example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"fun test(): Int {\n // @misti:suppress NeverAccessedVariables\n let sum: Int = 0; // OK: The warning will be suppressed\n return 52;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This syntax also enables you to list a few detectors to be suppressed, including the custom ones, for example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"// @misti:suppress NeverAccessedVariables,MyCustomDetector,ReadOnlyVariables\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Alternatively, you could run ",(0,i.jsx)(n.code,{children:"misti"})," while entirely suppressing specific detectors:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"misti --suppress ReadOnlyVariables path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.h3,{id:"enabling-all-detectors",children:"Enabling All Detectors"}),"\n",(0,i.jsxs)(n.p,{children:["Running ",(0,i.jsx)(n.code,{children:"misti"})," with all available built-in detectors enabled:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"misti --all-detectors path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"It is recommended to do that when auditing the project."}),"\n",(0,i.jsx)(n.h3,{id:"running-in-quiet-mode",children:"Running in Quiet Mode"}),"\n",(0,i.jsxs)(n.p,{children:["To suppress all output while running ",(0,i.jsx)(n.code,{children:"misti"})," getting just a return code:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"misti --quiet path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"This might be useful in scripts and CI/CD."}),"\n",(0,i.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsxs)(n.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,i.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,i.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>o});var i=s(6540);const t={},l=i.createContext(t);function r(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b64aaedd.0b438287.js b/assets/js/b64aaedd.0b438287.js new file mode 100644 index 000000000..5844a13c7 --- /dev/null +++ b/assets/js/b64aaedd.0b438287.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5588],{4913:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var o=n(4848),i=n(8453);const s={},r="FalseCondition",a={id:"detectors/FalseCondition",title:"FalseCondition",description:"A detector that highlights conditions that evaluate to a constant true or false",source:"@site/versioned_docs/version-0.4.0/detectors/FalseCondition.md",sourceDirName:"detectors",slug:"/detectors/FalseCondition",permalink:"/tools/misti/docs/0.4.0/detectors/FalseCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/FalseCondition.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"EnsurePrgSeed",permalink:"/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed"},next:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/0.4.0/detectors/FieldDoubleInit"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"falsecondition",children:"FalseCondition"}),"\n",(0,o.jsxs)(t.p,{children:["A detector that highlights conditions that evaluate to a constant ",(0,o.jsx)(t.code,{children:"true"})," or ",(0,o.jsx)(t.code,{children:"false"}),"\nin ",(0,o.jsx)(t.code,{children:"if"}),", ",(0,o.jsx)(t.code,{children:"while"}),", or ",(0,o.jsx)(t.code,{children:"until"})," statements, and zero iterations in ",(0,o.jsx)(t.code,{children:"repeat"})," statements."]}),"\n",(0,o.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsxs)(t.p,{children:["Conditions that always evaluate to a constant ",(0,o.jsx)(t.code,{children:"true"})," or ",(0,o.jsx)(t.code,{children:"false"})," are likely the result of a typo\nor logic error. Such conditions can lead to unintended behavior, dead code, or incorrect control flow.\nThis detector helps identify these cases so they can be corrected, improving the code's reliability."]}),"\n",(0,o.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-tact",children:"const FALSE: Bool = false;\n// Bad: Always false because of operator precedence\nif ((param | value) & FALSE) {\n // ... never executed\n}\n"})}),"\n",(0,o.jsx)(t.p,{children:"Use instead:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-tact",children:"const FALSE: Bool = false;\n// OK: Fixed after the analyzer highlighted this\nif (param) {}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var o=n(6540);const i={},s=o.createContext(i);function r(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b78952d0.efed39b1.js b/assets/js/b78952d0.efed39b1.js new file mode 100644 index 000000000..031affaeb --- /dev/null +++ b/assets/js/b78952d0.efed39b1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7682],{4428:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var n=i(4848),s=i(8453);const o={},a="FieldDoubleInit",r={id:"detectors/FieldDoubleInit",title:"FieldDoubleInit",description:"A detector that highlights cases where a field is initialized both in the",source:"@site/versioned_docs/version-0.3.1/detectors/FieldDoubleInit.md",sourceDirName:"detectors",slug:"/detectors/FieldDoubleInit",permalink:"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/FieldDoubleInit.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpIsUsed",permalink:"/tools/misti/docs/0.3.1/detectors/DumpIsUsed"},next:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/0.3.1/detectors/InheritedStateMutation"}},d={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"fielddoubleinit",children:"FieldDoubleInit"}),"\n",(0,n.jsxs)(t.p,{children:["A detector that highlights cases where a field is initialized both in the\n",(0,n.jsx)(t.code,{children:"init"})," function and at the point of definition."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["Double initialization of fields can either be a programmer's mistake or simply\na waste of gas. It is always preferred to initialize values in the field declaration\nif they have a compile-time evaluatable default value, or in the ",(0,n.jsx)(t.code,{children:"init"})," function if\nthey must be initialized dynamically."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 0; // Bad\n init(x: Int) { self.a = x }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int; // Fixed\n init(x: Int) { self.a = x }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>r});var n=i(6540);const s={},o=n.createContext(s);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b80eaa74.91abd0f7.js b/assets/js/b80eaa74.91abd0f7.js new file mode 100644 index 000000000..002af74f0 --- /dev/null +++ b/assets/js/b80eaa74.91abd0f7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4111],{8050:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.3.0/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.3.0/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/hacking/souffle.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.3.0/hacking/design"},next:{title:"Tools",permalink:"/tools/misti/docs/0.3.0/hacking/tools"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is implemented in the ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/souffle.js",children:"Souffle.js library"}),". See the ",(0,t.jsx)(n.a,{href:"https://nowarp.io/lib/souffle-js/api/",children:"Souffle.js API reference"})," for more detailed information."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b91dc83b.a57e29d3.js b/assets/js/b91dc83b.a57e29d3.js new file mode 100644 index 000000000..ccf1311be --- /dev/null +++ b/assets/js/b91dc83b.a57e29d3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9601],{3137:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var t=n(4848),s=n(8453);const o={},r="Configuration",l={id:"tutorial/configuration",title:"Configuration",description:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.",source:"@site/versioned_docs/version-0.2.1/tutorial/configuration.md",sourceDirName:"tutorial",slug:"/tutorial/configuration",permalink:"/tools/misti/docs/0.2.1/tutorial/configuration",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/tutorial/configuration.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.2.1/tutorial/ci-cd"},next:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.2.1/detectors"}},a={},c=[{value:"Configuration Options",id:"configuration-options",level:3},{value:"Running Misti with Configuration",id:"running-misti-with-configuration",level:2},{value:"Default Configuration File",id:"default-configuration-file",level:2},{value:"Getting Help",id:"getting-help",level:2}];function d(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(i.h1,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsx)(i.p,{children:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set."}),"\n",(0,t.jsx)(i.h3,{id:"configuration-options",children:"Configuration Options"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"detectors"}),": List of detectors to run. Each detector can be specified with a ",(0,t.jsx)(i.code,{children:"className"})," and optionally a ",(0,t.jsx)(i.code,{children:"modulePath"})," if it\u2019s a custom detector."]}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"className"})," (string, required): The class name of the detector."]}),"\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"modulePath"})," (string, optional): The file path of the detector module."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"ignored_projects"})," (array of strings, optional): List of Tact projects to ignore during analysis."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"soufflePath"})," (string, optional): Directory to save generated Souffl\xe9 files which is helpful for debugging purposes. If not set, a temporary directory will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"tactStdlibPath"})," (string, optional): Path to Tact standard library. If not set, the default stdlib from the actual Tact setup will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"unusedPrefix"}),' (string, default: "_"): Identifiers starting with this prefix won\'t be reported as unused by built-in detectors.']}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"verbosity"})," (string, optional): Verbosity level of the logs. Possible values are ",(0,t.jsx)(i.code,{children:"quiet"}),", ",(0,t.jsx)(i.code,{children:"debug"}),", and ",(0,t.jsx)(i.code,{children:"default"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(i.h2,{id:"running-misti-with-configuration",children:"Running Misti with Configuration"}),"\n",(0,t.jsx)(i.p,{children:"To run Misti with the specified configuration file, use the following command:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --config path/to/mistiConfig.json test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsx)(i.p,{children:"This command tells Misti to use the provided configuration file to analyze the specified Tact project configuration."}),"\n",(0,t.jsx)(i.h2,{id:"default-configuration-file",children:"Default Configuration File"}),"\n",(0,t.jsx)(i.p,{children:"By default, Misti enables all built-in detectors. Below is an example of the default configuration file:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-json",children:'{\n "detectorsEnabled": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n { "className": "BranchDuplicate" },\n { "className": "FieldDoubleInit" },\n { "className": "PreferAugmentedAssign" }\n ],\n "ignoredProjects": [],\n "unusedPrefix": "_",\n "verbosity": "default"\n}\n'})}),"\n",(0,t.jsxs)(i.p,{children:["All the built-in detectors are enabled by default. You can find the complete configuration schema and default configuration file on GitHub: ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/blob/master/configSchema.json",children:"configSchema.json"}),"."]}),"\n",(0,t.jsxs)(i.p,{children:["You can always dump the Misti configuration file in use by passing the ",(0,t.jsx)(i.code,{children:"--dump-config"})," option in the CLI:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --dump-config test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsxs)(i.p,{children:["If there is no Misti config in the ",(0,t.jsx)(i.code,{children:"simple"})," directory, Misti dumps the default config. This can be used to adjust it, e.g., adding or suppressing some detectors."]}),"\n",(0,t.jsx)(i.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,t.jsxs)(i.p,{children:["If you need assistance or encounter any issues, please create an issue on GitHub at ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/issues",children:"nowarp/misti"})," or ask in the ",(0,t.jsx)(i.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function u(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>l});var t=n(6540);const s={},o=t.createContext(s);function r(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/b9de2907.1fc2ebe1.js b/assets/js/b9de2907.1fc2ebe1.js new file mode 100644 index 000000000..8feb97e21 --- /dev/null +++ b/assets/js/b9de2907.1fc2ebe1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4913],{5144:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var n=i(4848),s=i(8453);const r={},o="Using Misti with Blueprint",l={id:"tutorial/blueprint",title:"Using Misti with Blueprint",description:"Blueprint is a platform to compile, test, and deploy contracts on the TON blockchain. It is quite similar to Hardhat and Truffle for Ethereum.",source:"@site/versioned_docs/version-0.5/tutorial/blueprint.md",sourceDirName:"tutorial",slug:"/tutorial/blueprint",permalink:"/tools/misti/docs/tutorial/blueprint",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tutorial/blueprint.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Configuration",permalink:"/tools/misti/docs/tutorial/configuration"},next:{title:"Overview",permalink:"/tools/misti/docs/detectors"}},a={},c=[{value:"Getting Started",id:"getting-started",level:2},{value:"Usage",id:"usage",level:2}];function d(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"using-misti-with-blueprint",children:"Using Misti with Blueprint"}),"\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://github.com/ton-org/blueprint/",children:"Blueprint"})," is a platform to compile, test, and deploy contracts on the TON blockchain. It is quite similar to Hardhat and Truffle for Ethereum."]}),"\n",(0,n.jsxs)(t.p,{children:["There is a ",(0,n.jsx)(t.a,{href:"https://github.com/nowarp/blueprint-misti",children:"blueprint-misti"})," plugin that can be added to a Blueprint configuration. It adds the ",(0,n.jsx)(t.code,{children:"blueprint misti"})," command, which runs the static analyzer over the selected Blueprint project."]}),"\n",(0,n.jsx)(t.p,{children:"This page describes how to use it."}),"\n",(0,n.jsx)(t.h2,{id:"getting-started",children:"Getting Started"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsxs)(t.p,{children:[(0,n.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Install Souffl\xe9"})," to use all detectors provided by Misti."]}),"\n"]}),"\n",(0,n.jsxs)(t.li,{children:["\n",(0,n.jsx)(t.p,{children:"Add this plugin as a dependency of your Blueprint project:"}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"yarn add @nowarp/blueprint-misti\n"})}),"\n",(0,n.jsxs)(t.ol,{start:"3",children:["\n",(0,n.jsxs)(t.li,{children:["Add this configuration to ",(0,n.jsx)(t.code,{children:"blueprint.config.ts"}),":"]}),"\n"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-ts",children:"import { MistiPlugin } from '@nowarp/blueprint-misti';\nexport const config = {\n plugins: [\n new MistiPlugin(),\n ],\n};\n"})}),"\n",(0,n.jsx)(t.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(t.p,{children:"Run the following command:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"yarn blueprint misti\n"})}),"\n",(0,n.jsx)(t.p,{children:"It will run the analysis of the available project, if there is one, or show an interactive window to select a project:"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"img",src:i(1547).A+"",width:"493",height:"96"})}),"\n",(0,n.jsxs)(t.p,{children:["You could also pass the ",(0,n.jsx)(t.a,{href:"/tools/misti/docs/tutorial/cli",children:"supported CLI options"})," for Misti, for example:"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"yarn blueprint misti --all-detectors\n"})}),"\n",(0,n.jsx)(t.p,{children:"Or you can even pass the path to the contract directly:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:"yarn blueprint misti path/to/my/contract.tact\n"})}),"\n",(0,n.jsxs)(t.p,{children:["If you have any problems, feel free to reach out to us in the ",(0,n.jsx)(t.a,{href:"https://t.me/misti_dev",children:"Misti discussion group"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},1547:(e,t,i)=>{i.d(t,{A:()=>n});const n=i.p+"assets/images/blueprint-select-project-b8656fa4266c0c7923d6b67c7f5950e6.png"},8453:(e,t,i)=>{i.d(t,{R:()=>o,x:()=>l});var n=i(6540);const s={},r=n.createContext(s);function o(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bce595e9.46a0cb1c.js b/assets/js/bce595e9.46a0cb1c.js new file mode 100644 index 000000000..540387f5b --- /dev/null +++ b/assets/js/bce595e9.46a0cb1c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8692],{3117:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var t=i(4848),s=i(8453);const r={},o="Contributing Guide",a={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/versioned_docs/version-0.2.2/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/0.2.2/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/hacking/contributing.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Prefer Augmented Assignment",permalink:"/tools/misti/docs/0.2.2/detectors/PreferAugmentedAssign"},next:{title:"Design Overview",permalink:"/tools/misti/docs/0.2.2/hacking/design"}},c={},d=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["All guidelines and additional hacking tips are available in the repo. For low-level details not present in the docs, refer to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/HACKING.md",children:"HACKING.md"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>a});var t=i(6540);const s={},r=t.createContext(s);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/bd72ef9b.45e20252.js b/assets/js/bd72ef9b.45e20252.js new file mode 100644 index 000000000..1a77b20ad --- /dev/null +++ b/assets/js/bd72ef9b.45e20252.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1114],{9712:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>l});var n=i(4848),s=i(8453);const o={},a="Field Initialized Twice",d={id:"detectors/FieldDoubleInit",title:"Field Initialized Twice",description:"A detector that highlights cases where a field is initialized both in the init function and at the point of definition.",source:"@site/versioned_docs/version-0.2.0/detectors/FieldDoubleInit.md",sourceDirName:"detectors",slug:"/detectors/FieldDoubleInit",permalink:"/tools/misti/docs/0.2.0/detectors/FieldDoubleInit",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/FieldDoubleInit.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"`dump` Is Used",permalink:"/tools/misti/docs/0.2.0/detectors/DumpIsUsed"},next:{title:"Prefer Augmented Assignment",permalink:"/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign"}},r={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"field-initialized-twice",children:"Field Initialized Twice"}),"\n",(0,n.jsxs)(t.p,{children:["A detector that highlights cases where a field is initialized both in the ",(0,n.jsx)(t.code,{children:"init"})," function and at the point of definition."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["Double initialization of fields can either be a programmer's mistake or simply a waste of gas. It is always preferred to initialize values in the field declaration if they have a compile-time evaluatable default value, or in the ",(0,n.jsx)(t.code,{children:"init"})," function if they must be initialized dynamically."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 0; // Bad\n init(x: Int) { self.a = x }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int; // Fixed\n init(x: Int) { self.a = x }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>d});var n=i(6540);const s={},o=n.createContext(s);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/be04c9f2.c6a1b800.js b/assets/js/be04c9f2.c6a1b800.js new file mode 100644 index 000000000..389718122 --- /dev/null +++ b/assets/js/be04c9f2.c6a1b800.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[44],{2322:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>p,frontMatter:()=>s,metadata:()=>r,toc:()=>a});var o=t(4848),i=t(8453);const s={},d="SendInLoop",r={id:"detectors/SendInLoop",title:"SendInLoop",description:"An optional detector that identifies send functions being called inside loops.",source:"@site/docs/detectors/SendInLoop.md",sourceDirName:"detectors",slug:"/detectors/SendInLoop",permalink:"/tools/misti/docs/next/detectors/SendInLoop",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/SendInLoop.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/next/detectors/ReadOnlyVariables"},next:{title:"ShortCircuitCondition",permalink:"/tools/misti/docs/next/detectors/ShortCircuitCondition"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"sendinloop",children:"SendInLoop"}),"\n",(0,o.jsx)(n.p,{children:"An optional detector that identifies send functions being called inside loops."}),"\n",(0,o.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsx)(n.p,{children:"Calling send functions inside loops can lead to unintended consequences, such as\nexcessive message sending, increased gas consumption, and potential race conditions.\nLoops with send calls should be refactored to avoid these issues. This detector helps\nflag such code, prompting the developer to reconsider the design."}),"\n",(0,o.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"fun exampleWhileLoop(limit: Int, owner: Address) {\n let i = 0;\n while (i < limit) {\n send(SendParameters{ // Highlighted: An auditor should review the loop\n to: owner,\n value: 0,\n bounce: false,\n body: Msg{ a: i }.toCell()\n });\n i += 1;\n }\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>d,x:()=>r});var o=t(6540);const i={},s=o.createContext(i);function d(e){const n=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/be8ab43b.f4a8e3dd.js b/assets/js/be8ab43b.f4a8e3dd.js new file mode 100644 index 000000000..64cb49c57 --- /dev/null +++ b/assets/js/be8ab43b.f4a8e3dd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6584],{3308:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>I,default:()=>c,frontMatter:()=>l,metadata:()=>d,toc:()=>g});var n=t(4848),s=t(8453);const l={},I="Tools Guide",d={id:"hacking/tools",title:"Tools Guide",description:"This page describes the internal analyzer tools available in Misti to aid in development and debugging.",source:"@site/versioned_docs/version-0.3.1/hacking/tools.md",sourceDirName:"hacking",slug:"/hacking/tools",permalink:"/tools/misti/docs/0.3.1/hacking/tools",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/hacking/tools.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.3.1/hacking/souffle"},next:{title:"Custom Detectors",permalink:"/tools/misti/docs/0.3.1/hacking/custom-detector"}},o={},g=[{value:"CFG Dump",id:"cfg-dump",level:2},{value:"Usage",id:"usage",level:3},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function a(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"tools-guide",children:"Tools Guide"}),"\n",(0,n.jsx)(e.p,{children:"This page describes the internal analyzer tools available in Misti to aid in development and debugging."}),"\n",(0,n.jsx)(e.h2,{id:"cfg-dump",children:"CFG Dump"}),"\n",(0,n.jsx)(e.p,{children:"Misti provides a feature to dump the Control Flow Graph (CFG) in both JSON and DOT formats. This is essential for understanding the internal representation (IR) of the code and analyzing the control flow within contracts."}),"\n",(0,n.jsx)(e.h3,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="json" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" \n'})}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, you can save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allows you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for gaining a better understanding of the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function c(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(a,{...i})}):a(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>I,x:()=>d});var n=t(6540);const s={},l=n.createContext(s);function I(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function d(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:I(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/c00ee666.951c69ba.js b/assets/js/c00ee666.951c69ba.js new file mode 100644 index 000000000..47ad41f4f --- /dev/null +++ b/assets/js/c00ee666.951c69ba.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[906],{3425:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>d,metadata:()=>o,toc:()=>l});var r=n(4848),s=n(8453);const d={},i="PreferredStdlibApi",o={id:"detectors/PreferredStdlibApi",title:"PreferredStdlibApi",description:"An optional detector that flags the use of advanced functions from the standard library.",source:"@site/versioned_docs/version-0.3.0/detectors/PreferredStdlibApi.md",sourceDirName:"detectors",slug:"/detectors/PreferredStdlibApi",permalink:"/tools/misti/docs/0.3.0/detectors/PreferredStdlibApi",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/PreferredStdlibApi.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign"},next:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/0.3.0/detectors/ReadOnlyVariables"}},a={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"preferredstdlibapi",children:"PreferredStdlibApi"}),"\n",(0,r.jsx)(t.p,{children:"An optional detector that flags the use of advanced functions from the standard library."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"Auditors should pay extra attention to these functions, as incorrect usage can\nlead to subtle bugs. Safer stdlib alternatives should be preferred in the code."}),"\n",(0,r.jsx)(t.p,{children:"Supported functions:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:["Use ",(0,r.jsx)(t.code,{children:"send"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativesendmessage",children:(0,r.jsx)(t.code,{children:"nativeSendMessage"})})]}),"\n",(0,r.jsxs)(t.li,{children:["Prefer ",(0,r.jsx)(t.code,{children:"randomInt"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativerandom",children:(0,r.jsx)(t.code,{children:"nativeRandom"})})]}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"let pkg: Slice = msg.transfer;\nlet _seqno: Int = pkg.loadInt(32);\nlet mode: Int = pkg.loadInt(8);\nlet body: Cell = pkg.loadRef();\n// Bad: prefer `send` to avoid low-level manipulation of Slice\nnativeSendMessage(body, mode);\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// Safer: More explicit definition of the send operation\nsend(SendParameters{ value: amount,\n to: self.owner,\n mode: mode,\n body: beginCell().endCell() });\n"})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(6540);const s={},d=r.createContext(s);function i(e){const t=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(d.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c05c6791.1dfb4d97.js b/assets/js/c05c6791.1dfb4d97.js new file mode 100644 index 000000000..bc92eddad --- /dev/null +++ b/assets/js/c05c6791.1dfb4d97.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8677],{3820:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>d,metadata:()=>o,toc:()=>l});var r=n(4848),s=n(8453);const d={},i="PreferredStdlibApi",o={id:"detectors/PreferredStdlibApi",title:"PreferredStdlibApi",description:"An optional detector that flags the use of advanced functions from the standard library.",source:"@site/versioned_docs/version-0.3.1/detectors/PreferredStdlibApi.md",sourceDirName:"detectors",slug:"/detectors/PreferredStdlibApi",permalink:"/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/PreferredStdlibApi.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/0.3.1/detectors/PreferAugmentedAssign"},next:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables"}},a={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"preferredstdlibapi",children:"PreferredStdlibApi"}),"\n",(0,r.jsx)(t.p,{children:"An optional detector that flags the use of advanced functions from the standard library."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"Auditors should pay extra attention to these functions, as incorrect usage can\nlead to subtle bugs. Safer stdlib alternatives should be preferred in the code."}),"\n",(0,r.jsx)(t.p,{children:"Supported functions:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:["Use ",(0,r.jsx)(t.code,{children:"send"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativesendmessage",children:(0,r.jsx)(t.code,{children:"nativeSendMessage"})})]}),"\n",(0,r.jsxs)(t.li,{children:["Prefer ",(0,r.jsx)(t.code,{children:"randomInt"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativerandom",children:(0,r.jsx)(t.code,{children:"nativeRandom"})})]}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"let pkg: Slice = msg.transfer;\nlet _seqno: Int = pkg.loadInt(32);\nlet mode: Int = pkg.loadInt(8);\nlet body: Cell = pkg.loadRef();\n// Bad: prefer `send` to avoid low-level manipulation of Slice\nnativeSendMessage(body, mode);\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// Safer: More explicit definition of the send operation\nsend(SendParameters{ value: amount,\n to: self.owner,\n mode: mode,\n body: beginCell().endCell() });\n"})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(6540);const s={},d=r.createContext(s);function i(e){const t=r.useContext(d);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(d.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c252c345.a3cf3637.js b/assets/js/c252c345.a3cf3637.js new file mode 100644 index 000000000..6c56472e9 --- /dev/null +++ b/assets/js/c252c345.a3cf3637.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2798],{3618:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var n=s(4848),i=s(8453);const o={},r="AsmIsUsed",a={id:"detectors/AsmIsUsed",title:"AsmIsUsed",description:"An optional detector that highlights all the asm functions.",source:"@site/versioned_docs/version-0.3.0/detectors/AsmIsUsed.md",sourceDirName:"detectors",slug:"/detectors/AsmIsUsed",permalink:"/tools/misti/docs/0.3.0/detectors/AsmIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/AsmIsUsed.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"ArgCopyMutation",permalink:"/tools/misti/docs/0.3.0/detectors/ArgCopyMutation"},next:{title:"BranchDuplicate",permalink:"/tools/misti/docs/0.3.0/detectors/BranchDuplicate"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"asmisused",children:"AsmIsUsed"}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"asm"})," functions."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Using TVM Assembly is a potentially dangerous operation that requires additional\nattention from an auditor. This optional detector will highlight all its uses to\nassist in contract security audits."}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"// Highlighted: the asm function use should be audited\nasm fun getStorageFee(cells: Int, bits: Int, seconds: Int, is_masterchain: Bool): Int { GETSTORAGEFEE }\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>a});var n=s(6540);const i={},o=n.createContext(i);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c2845dc0.24f1aeb0.js b/assets/js/c2845dc0.24f1aeb0.js new file mode 100644 index 000000000..eda412e49 --- /dev/null +++ b/assets/js/c2845dc0.24f1aeb0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5378],{830:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var n=r(4848),s=r(8453);const i={},o="StringReceiversOverlap",c={id:"detectors/StringReceiversOverlap",title:"StringReceiversOverlap",description:"A detector that finds overlapping messages between general string receivers and string receivers.",source:"@site/versioned_docs/version-0.5/detectors/StringReceiversOverlap.md",sourceDirName:"detectors",slug:"/detectors/StringReceiversOverlap",permalink:"/tools/misti/docs/detectors/StringReceiversOverlap",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/StringReceiversOverlap.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"SendInLoop",permalink:"/tools/misti/docs/detectors/SendInLoop"},next:{title:"SuspiciousMessageMode",permalink:"/tools/misti/docs/detectors/SuspiciousMessageMode"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"stringreceiversoverlap",children:"StringReceiversOverlap"}),"\n",(0,n.jsx)(t.p,{children:"A detector that finds overlapping messages between general string receivers and string receivers."}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Constant string receivers and general string receivers can have overlapping messages\nin which case the constant string receiver always takes precedence."}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {\n if (msg == "foobar") { throw(1043) } // Bad: Dead code\n }\n}\n'})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {}\n}\n'})})]})}function p(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>o,x:()=>c});var n=r(6540);const s={},i=n.createContext(s);function o(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c377a04b.8c30a29b.js b/assets/js/c377a04b.8c30a29b.js new file mode 100644 index 000000000..afe0ac6a0 --- /dev/null +++ b/assets/js/c377a04b.8c30a29b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3361],{8321:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/docs/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/next/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/index.md",tags:[],version:"current",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/next/tutorial/getting-started"}},c={},l=[{value:"Use Cases",id:"use-cases",level:2},{value:"Name Origin",id:"name-origin",level:2},{value:"Funding",id:"funding",level:2}];function d(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.5 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"name-origin",children:"Name Origin"}),"\n",(0,i.jsx)(t.p,{children:'The name "Misti" comes from the Misti volcano in Peru. It was chosen because it\'s catchy and easy to remember.'}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been funded by the following ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"})," grants:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"TON Static Analyzer \xb7 #436"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/777",children:"Upgrade Misti with Advanced Tact Detectors \xb7 #777"})}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"This support has enabled us to develop and maintain the tool."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c49af6bd.85a90098.js b/assets/js/c49af6bd.85a90098.js new file mode 100644 index 000000000..70cc8e264 --- /dev/null +++ b/assets/js/c49af6bd.85a90098.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1006],{8765:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>a});var n=s(4848),i=s(8453);const o={},d="dump Is Used",r={id:"detectors/DumpIsUsed",title:"dump Is Used",description:"An optional detector that highlights all the dump function calls.",source:"@site/versioned_docs/version-0.2.1/detectors/DumpIsUsed.md",sourceDirName:"detectors",slug:"/detectors/DumpIsUsed",permalink:"/tools/misti/docs/0.2.1/detectors/DumpIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/DumpIsUsed.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Branch Duplicate",permalink:"/tools/misti/docs/0.2.1/detectors/BranchDuplicate"},next:{title:"Field Initialized Twice",permalink:"/tools/misti/docs/0.2.1/detectors/FieldDoubleInit"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.h1,{id:"dump-is-used",children:[(0,n.jsx)(t.code,{children:"dump"})," Is Used"]}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"dump"})," function calls."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"dump"})," function is a debug print that shouldn't be in the final code. Even though the compiler removes it in production, its presence suggests the developer was debugging something. This can flag areas where issues might exist, so auditors should take a closer look at these parts of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = (RANDOM_SEED >> half_shift) &\n (MAGIC_CONSTANT << DIVIDE_BY_TWO) ^ shift_mask;\n dump(combined); // Suspicious: Highlighted by the detector\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = this.seed ^ shift_mask\n // OK: The code was reviewed and simplified; `dump` was removed\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>d,x:()=>r});var n=s(6540);const i={},o=n.createContext(i);function d(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c55f1521.cb9c8e4f.js b/assets/js/c55f1521.cb9c8e4f.js new file mode 100644 index 000000000..b6b1e77bf --- /dev/null +++ b/assets/js/c55f1521.cb9c8e4f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7083],{384:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="ConstantAddress",a={id:"detectors/ConstantAddress",title:"ConstantAddress",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/versioned_docs/version-0.3.0/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/0.3.0/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/ConstantAddress.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"BranchDuplicate",permalink:"/tools/misti/docs/0.3.0/detectors/BranchDuplicate"},next:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/0.3.0/detectors/DivideBeforeMultiply"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constantaddress",children:"ConstantAddress"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c5c1850c.d97c4482.js b/assets/js/c5c1850c.d97c4482.js new file mode 100644 index 000000000..3fe12d664 --- /dev/null +++ b/assets/js/c5c1850c.d97c4482.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7837],{2134:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var t=n(4848),s=n(8453);const o={},r="Configuration",l={id:"tutorial/configuration",title:"Configuration",description:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.",source:"@site/versioned_docs/version-0.2.2/tutorial/configuration.md",sourceDirName:"tutorial",slug:"/tutorial/configuration",permalink:"/tools/misti/docs/0.2.2/tutorial/configuration",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/tutorial/configuration.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.2.2/tutorial/ci-cd"},next:{title:"Using with Blueprint",permalink:"/tools/misti/docs/0.2.2/tutorial/blueprint"}},a={},c=[{value:"Configuration Options",id:"configuration-options",level:3},{value:"Running Misti with Configuration",id:"running-misti-with-configuration",level:2},{value:"Default Configuration File",id:"default-configuration-file",level:2},{value:"Getting Help",id:"getting-help",level:2}];function d(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(i.h1,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsx)(i.p,{children:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set."}),"\n",(0,t.jsx)(i.h3,{id:"configuration-options",children:"Configuration Options"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"detectors"}),": List of detectors to run. Each detector can be specified with a ",(0,t.jsx)(i.code,{children:"className"})," and optionally a ",(0,t.jsx)(i.code,{children:"modulePath"})," if it\u2019s a custom detector."]}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"className"})," (string, required): The class name of the detector."]}),"\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"modulePath"})," (string, optional): The file path of the detector module."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"ignored_projects"})," (array of strings, optional): List of Tact projects to ignore during analysis."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"soufflePath"})," (string, optional): Directory to save generated Souffl\xe9 files which is helpful for debugging purposes. If not set, a temporary directory will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"tactStdlibPath"})," (string, optional): Path to Tact standard library. If not set, the default stdlib from the actual Tact setup will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"unusedPrefix"}),' (string, default: "_"): Identifiers starting with this prefix won\'t be reported as unused by built-in detectors.']}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"verbosity"})," (string, optional): Verbosity level of the logs. Possible values are ",(0,t.jsx)(i.code,{children:"quiet"}),", ",(0,t.jsx)(i.code,{children:"debug"}),", and ",(0,t.jsx)(i.code,{children:"default"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(i.h2,{id:"running-misti-with-configuration",children:"Running Misti with Configuration"}),"\n",(0,t.jsx)(i.p,{children:"To run Misti with the specified configuration file, use the following command:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --config path/to/mistiConfig.json test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsx)(i.p,{children:"This command tells Misti to use the provided configuration file to analyze the specified Tact project configuration."}),"\n",(0,t.jsx)(i.h2,{id:"default-configuration-file",children:"Default Configuration File"}),"\n",(0,t.jsx)(i.p,{children:"By default, Misti enables all built-in detectors. Below is an example of the default configuration file:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-json",children:'{\n "detectorsEnabled": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n { "className": "BranchDuplicate" },\n { "className": "FieldDoubleInit" },\n { "className": "PreferAugmentedAssign" }\n ],\n "ignoredProjects": [],\n "unusedPrefix": "_",\n "verbosity": "default"\n}\n'})}),"\n",(0,t.jsxs)(i.p,{children:["All the built-in detectors are enabled by default. You can find the complete configuration schema and default configuration file on GitHub: ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/blob/master/configSchema.json",children:"configSchema.json"}),"."]}),"\n",(0,t.jsxs)(i.p,{children:["You can always dump the Misti configuration file in use by passing the ",(0,t.jsx)(i.code,{children:"--dump-config"})," option in the CLI:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --dump-config test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsxs)(i.p,{children:["If there is no Misti config in the ",(0,t.jsx)(i.code,{children:"simple"})," directory, Misti dumps the default config. This can be used to adjust it, e.g., adding or suppressing some detectors."]}),"\n",(0,t.jsx)(i.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,t.jsxs)(i.p,{children:["If you need assistance or encounter any issues, please create an issue on GitHub at ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/issues",children:"nowarp/misti"})," or ask in the ",(0,t.jsx)(i.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function u(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>l});var t=n(6540);const s={},o=t.createContext(s);function r(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c5d65102.924539a3.js b/assets/js/c5d65102.924539a3.js new file mode 100644 index 000000000..1137f146f --- /dev/null +++ b/assets/js/c5d65102.924539a3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8221],{415:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>a,contentTitle:()=>d,default:()=>u,frontMatter:()=>r,metadata:()=>i,toc:()=>c});var n=t(4848),o=t(8453);const r={},d="Zero Address",i={id:"detectors/ZeroAddress",title:"Zero Address",description:"A detector that identifies uses of the zero address.",source:"@site/versioned_docs/version-0.2.2/detectors/ZeroAddress.md",sourceDirName:"detectors",slug:"/detectors/ZeroAddress",permalink:"/tools/misti/docs/0.2.2/detectors/ZeroAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/ZeroAddress.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Unbound Loops",permalink:"/tools/misti/docs/0.2.2/detectors/UnboundLoops"},next:{title:"Constant Address",permalink:"/tools/misti/docs/0.2.2/detectors/ConstantAddress"}},a={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const s={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"zero-address",children:"Zero Address"}),"\n",(0,n.jsx)(s.p,{children:"A detector that identifies uses of the zero address."}),"\n",(0,n.jsx)(s.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(s.p,{children:"Using the zero address in smart contracts is typically problematic because it can be\nexploited as a default or uninitialized address, leading to unintended transfers and\nsecurity vulnerabilities. Additionally, operations involving the zero address can\nresult in loss of funds or tokens, as there is no private key to access this address."}),"\n",(0,n.jsx)(s.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init() {\n // Warning: Insecure usage of zero address as default value\n self.to = newAddress(0, 0);\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})}),"\n",(0,n.jsx)(s.p,{children:"Use instead:"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-tact",children:"contract Proxy {\n to: Address;\n init(to: Address) {\n // Fixed: Using the input value on initializaiton.\n self.to = to;\n }\n fun setAddress(to: Address) {\n self.to = to\n }\n}\n"})})]})}function u(e={}){const{wrapper:s}={...(0,o.R)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>d,x:()=>i});var n=t(6540);const o={},r=n.createContext(o);function d(e){const s=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function i(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),n.createElement(r.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c734b99d.c559e4ef.js b/assets/js/c734b99d.c559e4ef.js new file mode 100644 index 000000000..2c099cd8c --- /dev/null +++ b/assets/js/c734b99d.c559e4ef.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[872],{8956:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var s=n(4848),i=n(8453);const o={},a="UnusedOptional",r={id:"detectors/UnusedOptional",title:"UnusedOptional",description:"A detector variables and fields with unused optional modifier.",source:"@site/versioned_docs/version-0.5/detectors/UnusedOptional.md",sourceDirName:"detectors",slug:"/detectors/UnusedOptional",permalink:"/tools/misti/docs/detectors/UnusedOptional",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/UnusedOptional.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"UnusedExpressionResult",permalink:"/tools/misti/docs/detectors/UnusedExpressionResult"},next:{title:"ZeroAddress",permalink:"/tools/misti/docs/detectors/ZeroAddress"}},d={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"unusedoptional",children:"UnusedOptional"}),"\n",(0,s.jsx)(t.p,{children:"A detector variables and fields with unused optional modifier."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"Optional"})," is a nullable value that has a special ",(0,s.jsx)(t.code,{children:"null"})," value indicating the absence\nof a value. If a developer creates an optional variable or field, he should leverage\nits functionality by accessing the ",(0,s.jsx)(t.code,{children:"null"})," value somewhere in his code. Otherwise,\nthe optional type should be removed to simplify and optimize the code."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int?; // Bad: null value is never accessed\n init() { self.a = 42; }\n get fun getA(): Int { return self.a!!; }\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 42; // OK: Removed optional\n get fun getA(): Int { return self.a; }\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var s=n(6540);const i={},o=s.createContext(i);function a(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c7ee6afe.d82db54e.js b/assets/js/c7ee6afe.d82db54e.js new file mode 100644 index 000000000..13c2384fe --- /dev/null +++ b/assets/js/c7ee6afe.d82db54e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5459],{4729:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.4.0/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/0.4.0/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/index.md",tags:[],version:"0.4.0",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/0.4.0/tutorial/getting-started"}},c={},l=[{value:"Use Cases",id:"use-cases",level:2},{value:"Name Origin",id:"name-origin",level:2},{value:"Funding",id:"funding",level:2}];function d(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.5 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"name-origin",children:"Name Origin"}),"\n",(0,i.jsx)(t.p,{children:'The name "Misti" comes from the Misti volcano in Peru. It was chosen because it\'s catchy and easy to remember.'}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been funded by the following ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"})," grants:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"TON Static Analyzer \xb7 #436"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/777",children:"Upgrade Misti with Advanced Tact Detectors \xb7 #777"})}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"This support has enabled us to develop and maintain the tool."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c82192ae.388e1126.js b/assets/js/c82192ae.388e1126.js new file mode 100644 index 000000000..82d252f93 --- /dev/null +++ b/assets/js/c82192ae.388e1126.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5321],{4482:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>o,contentTitle:()=>n,default:()=>x,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var d=s(4848),r=s(8453);const i={id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},n="Detectors Overview",c={id:"detectors",title:"Detectors Overview",description:"Misti currently supports 20 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:",source:"@site/versioned_docs/version-0.4.0/detectors.md",sourceDirName:".",slug:"/detectors",permalink:"/tools/misti/docs/0.4.0/detectors",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors.md",tags:[],version:"0.4.0",frontMatter:{id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},sidebar:"sidebar",previous:{title:"Using with Blueprint",permalink:"/tools/misti/docs/0.4.0/tutorial/blueprint"},next:{title:"ArgCopyMutation",permalink:"/tools/misti/docs/0.4.0/detectors/ArgCopyMutation"}},o={},l=[];function h(e){const t={a:"a",code:"code",h1:"h1",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(t.h1,{id:"detectors-overview",children:"Detectors Overview"}),"\n",(0,d.jsx)(t.p,{children:"Misti currently supports 20 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:"}),"\n",(0,d.jsxs)(t.table,{children:[(0,d.jsx)(t.thead,{children:(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.th,{children:"#"}),(0,d.jsx)(t.th,{children:"Detector"}),(0,d.jsx)(t.th,{children:"Severity"}),(0,d.jsx)(t.th,{children:"Requires Souffl\xe9"}),(0,d.jsx)(t.th,{children:"Enabled by default"})]})}),(0,d.jsxs)(t.tbody,{children:[(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"1"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/ArgCopyMutation",children:"ArgCopyMutation"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"2"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/AsmIsUsed",children:"AsmIsUsed"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"3"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/BranchDuplicate",children:"BranchDuplicate"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"4"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/ConstantAddress",children:"ConstantAddress"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"5"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply",children:"DivideBeforeMultiply"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{children:"\u2714"}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"6"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/DumpIsUsed",children:"DumpIsUsed"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"7"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/DuplicatedCondition",children:"DuplicatedCondition"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"8"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed",children:"EnsurePrgSeed"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"9"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/FalseCondition",children:"FalseCondition"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"10"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/FieldDoubleInit",children:"FieldDoubleInit"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"11"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/InheritedStateMutation",children:"InheritedStateMutation"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"12"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables",children:"NeverAccessedVariables"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"13"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/OptimalMathFunction",children:"OptimalMathFunction"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"14"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign",children:"PreferAugmentedAssign"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"15"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi",children:"PreferredStdlibApi"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"16"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables",children:"ReadOnlyVariables"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{children:"\u2714"}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"17"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap",children:"StringReceiversOverlap"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"18"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/UnboundLoops",children:"UnboundLoops"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{children:"\u2714"}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"19"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/UnusedOptional",children:"UnusedOptional"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"20"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/detectors/ZeroAddress",children:"ZeroAddress"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]})]})]}),"\n",(0,d.jsxs)(t.p,{children:["Some of the detectors require ",(0,d.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})," to be installed. If no Souffl\xe9 installation is found, these detectors won't be executed."]}),"\n",(0,d.jsxs)(t.p,{children:["A few detectors are optional and aimed at auditors to help uncover subtle issues in the source code. To enable all detectors, use the ",(0,d.jsx)(t.code,{children:"--all-detectors"})," option. You can find a full list of configuration options on the ",(0,d.jsx)(t.a,{href:"/tools/misti/docs/0.4.0/tutorial/configuration",children:"configuration page"}),"."]}),"\n",(0,d.jsx)(t.p,{children:"Each detector targets a specific type of problem in your code. Click on the detector name to learn more."})]})}function x(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,d.jsx)(t,{...e,children:(0,d.jsx)(h,{...e})}):h(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>n,x:()=>c});var d=s(6540);const r={},i=d.createContext(r);function n(e){const t=d.useContext(i);return d.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:n(e.components),d.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c926d0d4.30e3ae68.js b/assets/js/c926d0d4.30e3ae68.js new file mode 100644 index 000000000..ce8d109eb --- /dev/null +++ b/assets/js/c926d0d4.30e3ae68.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8771],{3608:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>a,frontMatter:()=>i,metadata:()=>n,toc:()=>l});var r=s(4848),d=s(8453);const i={id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},o="Detectors Overview",n={id:"detectors",title:"Detectors Overview",description:"Misti currently supports 15 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:",source:"@site/versioned_docs/version-0.3.1/detectors.md",sourceDirName:".",slug:"/detectors",permalink:"/tools/misti/docs/0.3.1/detectors",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors.md",tags:[],version:"0.3.1",frontMatter:{id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},sidebar:"sidebar",previous:{title:"Using with Blueprint",permalink:"/tools/misti/docs/0.3.1/tutorial/blueprint"},next:{title:"ArgCopyMutation",permalink:"/tools/misti/docs/0.3.1/detectors/ArgCopyMutation"}},c={},l=[];function h(e){const t={a:"a",code:"code",h1:"h1",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,d.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"detectors-overview",children:"Detectors Overview"}),"\n",(0,r.jsx)(t.p,{children:"Misti currently supports 15 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:"}),"\n",(0,r.jsxs)(t.table,{children:[(0,r.jsx)(t.thead,{children:(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.th,{children:"#"}),(0,r.jsx)(t.th,{children:"Detector"}),(0,r.jsx)(t.th,{children:"Requires Souffl\xe9"}),(0,r.jsx)(t.th,{children:"Enabled by default"})]})}),(0,r.jsxs)(t.tbody,{children:[(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"1"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/ArgCopyMutation",children:"ArgCopyMutation"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"2"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/AsmIsUsed",children:"AsmIsUsed"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"3"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/BranchDuplicate",children:"BranchDuplicate"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"4"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/ConstantAddress",children:"ConstantAddress"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"5"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply",children:"DivideBeforeMultiply"})}),(0,r.jsx)(t.td,{children:"\u2714"}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"6"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/DumpIsUsed",children:"DumpIsUsed"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"7"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit",children:"FieldDoubleInit"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"8"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/InheritedStateMutation",children:"InheritedStateMutation"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"9"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/NeverAccessedVariables",children:"NeverAccessedVariables"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"10"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/PreferAugmentedAssign",children:"PreferAugmentedAssign"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"11"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi",children:"PreferredStdlibApi"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"12"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables",children:"ReadOnlyVariables"})}),(0,r.jsx)(t.td,{children:"\u2714"}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"13"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap",children:"StringReceiversOverlap"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"14"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/UnboundLoops",children:"UnboundLoops"})}),(0,r.jsx)(t.td,{children:"\u2714"}),(0,r.jsx)(t.td,{children:"\u2714"})]}),(0,r.jsxs)(t.tr,{children:[(0,r.jsx)(t.td,{children:"15"}),(0,r.jsx)(t.td,{children:(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/detectors/ZeroAddress",children:"ZeroAddress"})}),(0,r.jsx)(t.td,{}),(0,r.jsx)(t.td,{children:"\u2714"})]})]})]}),"\n",(0,r.jsxs)(t.p,{children:["Some of the detectors require ",(0,r.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})," to be installed. If no Souffl\xe9 installation is found, these detectors won't be executed."]}),"\n",(0,r.jsxs)(t.p,{children:["A few detectors are optional and aimed at auditors to help uncover subtle issues in the source code. To enable all detectors, use the ",(0,r.jsx)(t.code,{children:"--all-detectors"})," option. You can find a full list of configuration options on the ",(0,r.jsx)(t.a,{href:"/tools/misti/docs/0.3.1/tutorial/configuration",children:"configuration page"}),"."]}),"\n",(0,r.jsx)(t.p,{children:"Each detector targets a specific type of problem in your code. Click on the detector name to learn more."})]})}function a(e={}){const{wrapper:t}={...(0,d.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>o,x:()=>n});var r=s(6540);const d={},i=r.createContext(d);function o(e){const t=r.useContext(i);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function n(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(d):e.components||d:o(e.components),r.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/c96954fa.f94afa3f.js b/assets/js/c96954fa.f94afa3f.js new file mode 100644 index 000000000..99ddb6852 --- /dev/null +++ b/assets/js/c96954fa.f94afa3f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2312],{263:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>a});var n=i(4848),r=i(8453);const o={},s="Divide before Multiply",l={id:"detectors/DivideBeforeMultiply",title:"Divide before Multiply",description:"A detector that identifies and corrects instances of division before multiplication to",source:"@site/versioned_docs/version-0.2.2/detectors/DivideBeforeMultiply.md",sourceDirName:"detectors",slug:"/detectors/DivideBeforeMultiply",permalink:"/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/DivideBeforeMultiply.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.2.2/detectors"},next:{title:"Never-accessed Variables",permalink:"/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,r.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"divide-before-multiply",children:"Divide before Multiply"}),"\n",(0,n.jsx)(t.p,{children:"A detector that identifies and corrects instances of division before multiplication to\nensure accurate mathematical operations."}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Performing division before multiplication can lead to unexpected results due to precision loss and rounding errors:"}),"\n",(0,n.jsxs)(t.ul,{children:["\n",(0,n.jsx)(t.li,{children:"Precision Loss: Dividing first can result in significant precision loss, especially when dealing with integers or fixed-point numbers."}),"\n",(0,n.jsx)(t.li,{children:"Rounding Errors: Early division might cause rounding errors that propagate through subsequent calculations."}),"\n",(0,n.jsx)(t.li,{children:"Unexpected Behavior: Incorrectly ordered operations can lead to incorrect outcomes, making debugging and maintenance more challenging."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Bad: Division before multiplication\nlet result: Int = a / b * c;\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"let a: Int = 10;\nlet b: Int = 3;\nlet c: Int = 2;\n// Correct: Multiplication before division\nlet result: Int = a * c / b;\n"})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>s,x:()=>l});var n=i(6540);const r={},o=n.createContext(r);function s(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ca178ca4.7d6ff74e.js b/assets/js/ca178ca4.7d6ff74e.js new file mode 100644 index 000000000..cae8f22d2 --- /dev/null +++ b/assets/js/ca178ca4.7d6ff74e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2195],{5778:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var a=t(4848),i=t(8453);const r={},s="Read-only Variables",o={id:"detectors/ReadOnlyVariables",title:"Read-only Variables",description:"A detector that identifies read-only variables and fields.",source:"@site/versioned_docs/version-0.2.2/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/ReadOnlyVariables.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Never-accessed Variables",permalink:"/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables"},next:{title:"Unbound Loops",permalink:"/tools/misti/docs/0.2.2/detectors/UnboundLoops"}},l={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"read-only-variables",children:"Read-only Variables"}),"\n",(0,a.jsx)(n.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,a.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,a.jsx)(n.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,a.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"Use instead:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the linter highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>o});var a=t(6540);const i={},r=a.createContext(i);function s(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cb77e040.4c34ff27.js b/assets/js/cb77e040.4c34ff27.js new file mode 100644 index 000000000..a011a8942 --- /dev/null +++ b/assets/js/cb77e040.4c34ff27.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6757],{4318:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>p,frontMatter:()=>s,metadata:()=>o,toc:()=>l});var r=n(4848),d=n(8453);const s={},i="PreferredStdlibApi",o={id:"detectors/PreferredStdlibApi",title:"PreferredStdlibApi",description:"An optional detector that flags the use of advanced functions from the standard library.",source:"@site/docs/detectors/PreferredStdlibApi.md",sourceDirName:"detectors",slug:"/detectors/PreferredStdlibApi",permalink:"/tools/misti/docs/next/detectors/PreferredStdlibApi",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/PreferredStdlibApi.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/next/detectors/PreferAugmentedAssign"},next:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/next/detectors/ReadOnlyVariables"}},a={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",ul:"ul",...(0,d.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"preferredstdlibapi",children:"PreferredStdlibApi"}),"\n",(0,r.jsx)(t.p,{children:"An optional detector that flags the use of advanced functions from the standard library."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"Auditors should pay extra attention to these functions, as incorrect usage can\nlead to subtle bugs. Safer stdlib alternatives should be preferred in the code."}),"\n",(0,r.jsx)(t.p,{children:"Supported functions:"}),"\n",(0,r.jsxs)(t.ul,{children:["\n",(0,r.jsxs)(t.li,{children:["Use ",(0,r.jsx)(t.code,{children:"send"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativesendmessage",children:(0,r.jsx)(t.code,{children:"nativeSendMessage"})})]}),"\n",(0,r.jsxs)(t.li,{children:["Prefer ",(0,r.jsx)(t.code,{children:"randomInt"})," instead of ",(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-advanced#nativerandom",children:(0,r.jsx)(t.code,{children:"nativeRandom"})})]}),"\n"]}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"let pkg: Slice = msg.transfer;\nlet _seqno: Int = pkg.loadInt(32);\nlet mode: Int = pkg.loadInt(8);\nlet body: Cell = pkg.loadRef();\n// Bad: prefer `send` to avoid low-level manipulation of Slice\nnativeSendMessage(body, mode);\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// Safer: More explicit definition of the send operation\nsend(SendParameters{ value: amount,\n to: self.owner,\n mode: mode,\n body: beginCell().endCell() });\n"})})]})}function p(e={}){const{wrapper:t}={...(0,d.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var r=n(6540);const d={},s=r.createContext(d);function i(e){const t=r.useContext(s);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(d):e.components||d:i(e.components),r.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cc6d1ce2.2f552c48.js b/assets/js/cc6d1ce2.2f552c48.js new file mode 100644 index 000000000..d8856b268 --- /dev/null +++ b/assets/js/cc6d1ce2.2f552c48.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3750],{433:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>u,frontMatter:()=>i,metadata:()=>r,toc:()=>l});var s=n(4848),o=n(8453);const i={},a="ArgCopyMutation",r={id:"detectors/ArgCopyMutation",title:"ArgCopyMutation",description:"A detector that highlights cases where function argument mutations are ineffective",source:"@site/versioned_docs/version-0.3.0/detectors/ArgCopyMutation.md",sourceDirName:"detectors",slug:"/detectors/ArgCopyMutation",permalink:"/tools/misti/docs/0.3.0/detectors/ArgCopyMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/ArgCopyMutation.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.3.0/detectors"},next:{title:"AsmIsUsed",permalink:"/tools/misti/docs/0.3.0/detectors/AsmIsUsed"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"argcopymutation",children:"ArgCopyMutation"}),"\n",(0,s.jsx)(t.p,{children:"A detector that highlights cases where function argument mutations are ineffective\ndue to call-by-value semantics in Tact."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"In Tact, function arguments are passed by value, meaning that any mutations applied\nto these arguments will only affect the local copy of the variable within the function.\nSuch mutations are unobservable outside the function, except for potentially\nincreasing gas consumption or causing exceptions."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun addEntry(m: map ) {\n m.set(1, 10); // Bad: Mutating the copy\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun addEntry() {\n self.m.set(1, 10); // OK: Changing contract's state\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Alternatively, you could redesign the method:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"fun generateNewValue(): Int {\n // ... produce new value for the map\n return self.nextValue + 1;\n}\n\nm.set(self.nextKey, self.generateNewValue()); // OK\n"})})]})}function u(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var s=n(6540);const o={},i=s.createContext(o);function a(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cd411a47.dbdd6a6b.js b/assets/js/cd411a47.dbdd6a6b.js new file mode 100644 index 000000000..b8583a558 --- /dev/null +++ b/assets/js/cd411a47.dbdd6a6b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4442],{4802:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.1.2/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.1.2/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/hacking/souffle.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.1.2/hacking/design"},next:{title:"Tools",permalink:"/tools/misti/docs/0.1.2/hacking/tools"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is detailed ",(0,t.jsx)(n.a,{href:"https://nowarp.github.io/docs/misti/api/modules/internals_souffle.html",children:"here"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ce7f72c2.19df7abf.js b/assets/js/ce7f72c2.19df7abf.js new file mode 100644 index 000000000..f2d1a26aa --- /dev/null +++ b/assets/js/ce7f72c2.19df7abf.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5200],{4795:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var t=i(4848),s=i(8453);const o={},r="Contributing Guide",a={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/versioned_docs/version-0.3.1/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/0.3.1/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/hacking/contributing.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"ZeroAddress",permalink:"/tools/misti/docs/0.3.1/detectors/ZeroAddress"},next:{title:"Design Overview",permalink:"/tools/misti/docs/0.3.1/hacking/design"}},c={},d=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["All guidelines and additional hacking tips are available in the repo. For low-level details not present in the docs, refer to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/HACKING.md",children:"HACKING.md"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>a});var t=i(6540);const s={},o=t.createContext(s);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cf2c24d9.7b0b1178.js b/assets/js/cf2c24d9.7b0b1178.js new file mode 100644 index 000000000..3948125ce --- /dev/null +++ b/assets/js/cf2c24d9.7b0b1178.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[338],{9:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>r,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>c});var o=t(4848),s=t(8453);const i={},r="UnboundLoops",a={id:"detectors/UnboundLoops",title:"UnboundLoops",description:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.",source:"@site/versioned_docs/version-0.4.0/detectors/UnboundLoops.md",sourceDirName:"detectors",slug:"/detectors/UnboundLoops",permalink:"/tools/misti/docs/0.4.0/detectors/UnboundLoops",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/UnboundLoops.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"StringReceiversOverlap",permalink:"/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap"},next:{title:"UnusedOptional",permalink:"/tools/misti/docs/0.4.0/detectors/UnusedOptional"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.h1,{id:"unboundloops",children:"UnboundLoops"}),"\n",(0,o.jsx)(n.p,{children:"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria."}),"\n",(0,o.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsx)(n.p,{children:"An unbounded loop can be problematic for several reasons:"}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Unexpected Behavior:"})," Without a defined termination, loops can lead to unpredictable contract behavior and make debugging difficult."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"Out-of-gas Attacks:"})," Continuous looping without termination can lead to out-of-gas attacks."]}),"\n",(0,o.jsxs)(n.li,{children:[(0,o.jsx)(n.strong,{children:"DoS Attacks:"})," Malicious actors can exploit unbounded loops to create denial-of-service attacks, impacting contract's availability."]}),"\n"]}),"\n",(0,o.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n // Bad: x is not changed due looping\n send(SendParameters{ to: sender(), ... });\n}\n"})}),"\n",(0,o.jsx)(n.p,{children:"Use instead:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-tact",children:"let x: Int = 10;\nwhile (x > 0) {\n send(SendParameters{ to: sender(), ... });\n x = x - 1;\n}\n"})})]})}function p(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>a});var o=t(6540);const s={},i=o.createContext(s);function r(e){const n=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/cf5f971a.651efe6f.js b/assets/js/cf5f971a.651efe6f.js new file mode 100644 index 000000000..c83dcc8e5 --- /dev/null +++ b/assets/js/cf5f971a.651efe6f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7003],{1963:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>I,default:()=>c,frontMatter:()=>l,metadata:()=>d,toc:()=>g});var n=t(4848),s=t(8453);const l={},I="Tools Guide",d={id:"hacking/tools",title:"Tools Guide",description:"This page describes the internal analyzer tools available in Misti to aid in development and debugging.",source:"@site/versioned_docs/version-0.1.2/hacking/tools.md",sourceDirName:"hacking",slug:"/hacking/tools",permalink:"/tools/misti/docs/0.1.2/hacking/tools",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/hacking/tools.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.1.2/hacking/souffle"},next:{title:"Custom Detectors",permalink:"/tools/misti/docs/0.1.2/hacking/custom-detector"}},o={},g=[{value:"CFG Dump",id:"cfg-dump",level:2},{value:"Usage",id:"usage",level:3},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function a(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"tools-guide",children:"Tools Guide"}),"\n",(0,n.jsx)(e.p,{children:"This page describes the internal analyzer tools available in Misti to aid in development and debugging."}),"\n",(0,n.jsx)(e.h2,{id:"cfg-dump",children:"CFG Dump"}),"\n",(0,n.jsx)(e.p,{children:"Misti provides a feature to dump the Control Flow Graph (CFG) in both JSON and DOT formats. This is essential for understanding the internal representation (IR) of the code and analyzing the control flow within contracts."}),"\n",(0,n.jsx)(e.h3,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="json" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" \n'})}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, you can save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'npx misti --dump-cfg="dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allows you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for gaining a better understanding of the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function c(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(a,{...i})}):a(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>I,x:()=>d});var n=t(6540);const s={},l=n.createContext(s);function I(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function d(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:I(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/d147047e.c3db349f.js b/assets/js/d147047e.c3db349f.js new file mode 100644 index 000000000..25d074cb9 --- /dev/null +++ b/assets/js/d147047e.c3db349f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7965],{2643:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=n(4848),a=n(8453);const r={},s="InheritedStateMutation",o={id:"detectors/InheritedStateMutation",title:"InheritedStateMutation",description:"An optional detector that highlights all instances where inherited trait variables",source:"@site/versioned_docs/version-0.3.1/detectors/InheritedStateMutation.md",sourceDirName:"detectors",slug:"/detectors/InheritedStateMutation",permalink:"/tools/misti/docs/0.3.1/detectors/InheritedStateMutation",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/detectors/InheritedStateMutation.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit"},next:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/0.3.1/detectors/NeverAccessedVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"inheritedstatemutation",children:"InheritedStateMutation"}),"\n",(0,i.jsx)(t.p,{children:"An optional detector that highlights all instances where inherited trait variables\nare directly modified."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Traits should provide setter methods to ensure that invariants related to their\nstate are preserved. Directly modifying trait variables (e.g., ",(0,i.jsx)(t.code,{children:"self.traitVar = 42"}),")\ncan violate these invariants, leading to potential bugs or security vulnerabilities.\nThis detector warns when such direct modifications occur, prompting further review\nby auditors."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"trait T {\n balance: Int;\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.balance = 100; // Suspicious: Highlighted by the detector\n }\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:'trait T {\n balance: Int;\n fun setBalance(newBalance: Int) {\n require(newBalance > 0, "balance cannot be negative"); // Invariant check\n self.balance = newBalance;\n }\n}\n\ncontract C with T {\n balance: Int = 42;\n fun updateBalance() {\n self.setBalance(100); // OK: Invariant preserved\n }\n}\n'})})]})}function h(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>o});var i=n(6540);const a={},r=i.createContext(a);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d15cc687.df08049f.js b/assets/js/d15cc687.df08049f.js new file mode 100644 index 000000000..3df3a99d9 --- /dev/null +++ b/assets/js/d15cc687.df08049f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6406],{7033:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="Branch Duplicate",o={id:"detectors/BranchDuplicate",title:"Branch Duplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.2.1/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/0.2.1/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/BranchDuplicate.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Constant Address",permalink:"/tools/misti/docs/0.2.1/detectors/ConstantAddress"},next:{title:"`dump` Is Used",permalink:"/tools/misti/docs/0.2.1/detectors/DumpIsUsed"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branch-duplicate",children:"Branch Duplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d1781038.35abe5aa.js b/assets/js/d1781038.35abe5aa.js new file mode 100644 index 000000000..2e049a1f4 --- /dev/null +++ b/assets/js/d1781038.35abe5aa.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6633],{5e3:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.2.1/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/0.2.1/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/index.md",tags:[],version:"0.2.1",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/0.2.1/tutorial/getting-started"}},c={},d=[{value:"Use Cases",id:"use-cases",level:2},{value:"Funding",id:"funding",level:2}];function l(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.4.4 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been ",(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"funded"})," by ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"}),". This support has enabled us to develop and maintain the tool."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d2aaf676.0ddaefea.js b/assets/js/d2aaf676.0ddaefea.js new file mode 100644 index 000000000..2a2bc2e98 --- /dev/null +++ b/assets/js/d2aaf676.0ddaefea.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4040],{9323:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="NeverAccessedVariables",o={id:"detectors/NeverAccessedVariables",title:"NeverAccessedVariables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/docs/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/next/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/NeverAccessedVariables.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/next/detectors/InheritedStateMutation"},next:{title:"OptimalMathFunction",permalink:"/tools/misti/docs/next/detectors/OptimalMathFunction"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"neveraccessedvariables",children:"NeverAccessedVariables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the analyzer highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d2d53d04.404d4960.js b/assets/js/d2d53d04.404d4960.js new file mode 100644 index 000000000..552cc4375 --- /dev/null +++ b/assets/js/d2d53d04.404d4960.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2537],{8023:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>s,metadata:()=>c,toc:()=>a});var i=n(4848),r=n(8453);const s={},o="Using Misti with Blueprint",c={id:"tutorial/blueprint",title:"Using Misti with Blueprint",description:"Blueprint is a development environment for writing, testing, and deploying TON smart contracts.",source:"@site/versioned_docs/version-0.2.2/tutorial/blueprint.md",sourceDirName:"tutorial",slug:"/tutorial/blueprint",permalink:"/tools/misti/docs/0.2.2/tutorial/blueprint",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/tutorial/blueprint.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Configuration",permalink:"/tools/misti/docs/0.2.2/tutorial/configuration"},next:{title:"Detectors Overview",permalink:"/tools/misti/docs/0.2.2/detectors"}},l={},a=[{value:"Getting started",id:"getting-started",level:2},{value:"Resources",id:"resources",level:2}];function u(t){const e={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"using-misti-with-blueprint",children:"Using Misti with Blueprint"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.a,{href:"https://github.com/ton-org/blueprint",children:"Blueprint"})," is a development environment for writing, testing, and deploying TON smart contracts."]}),"\n",(0,i.jsxs)(e.p,{children:["Misti can be used in Blueprint projects by leveraging the ",(0,i.jsx)(e.a,{href:"https://github.com/nowarp/blueprint-misti",children:(0,i.jsx)(e.code,{children:"blueprint-misti"})})," plugin."]}),"\n",(0,i.jsx)(e.h2,{id:"getting-started",children:"Getting started"}),"\n",(0,i.jsxs)(e.p,{children:["Add the plugin and the recent version of Tact to the ",(0,i.jsx)(e.code,{children:"package.json"})," of your Blueprint project by running:"]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-bash",children:"yarn add @tact-lang/compiler\nyarn add @nowarp/blueprint-misti\n"})}),"\n",(0,i.jsxs)(e.p,{children:["Then, add this configuration to ",(0,i.jsx)(e.code,{children:"blueprint.config.ts"}),":"]}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-ts",children:"import { MistiPlugin } from '@nowarp/blueprint-misti';\nexport const config = {\n plugins: [\n new MistiPlugin(),\n ],\n};\n"})}),"\n",(0,i.jsx)(e.p,{children:"Now, try to run Misti:"}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-bash",children:"yarn blueprint misti ./path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(e.h2,{id:"resources",children:"Resources"}),"\n",(0,i.jsxs)(e.p,{children:["For more information, please refer to the README of the ",(0,i.jsx)(e.a,{href:"https://github.com/nowarp/blueprint-misti",children:(0,i.jsx)(e.code,{children:"blueprint-misti"})})," project. If you have any problems, feel free to reach out to us in the ",(0,i.jsx)(e.a,{href:"https://t.me/misti_dev",children:"Misti discussion group"}),"."]})]})}function d(t={}){const{wrapper:e}={...(0,r.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(u,{...t})}):u(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>o,x:()=>c});var i=n(6540);const r={},s=i.createContext(r);function o(t){const e=i.useContext(s);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function c(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(r):t.components||r:o(t.components),i.createElement(s.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/d2f295f4.9f26dd12.js b/assets/js/d2f295f4.9f26dd12.js new file mode 100644 index 000000000..237f62e8c --- /dev/null +++ b/assets/js/d2f295f4.9f26dd12.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7242],{5077:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>d,default:()=>g,frontMatter:()=>l,metadata:()=>a,toc:()=>r});var n=t(4848),s=t(8453);const l={},d="DumpCfg",a={id:"tools/DumpCfg",title:"DumpCfg",description:"Misti provides a feature to dump the Control Flow Graph (CFG) in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts.",source:"@site/docs/tools/DumpCfg.md",sourceDirName:"tools",slug:"/tools/DumpCfg",permalink:"/tools/misti/docs/next/tools/DumpCfg",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/tools/DumpCfg.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpAst",permalink:"/tools/misti/docs/next/tools/DumpAst"},next:{title:"DumpConfig",permalink:"/tools/misti/docs/next/tools/DumpConfig"}},o={},r=[{value:"Usage",id:"usage",level:2},{value:"Working with Mermaid",id:"working-with-mermaid",level:2},{value:"Working with Graphviz",id:"working-with-graphviz",level:2},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function I(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"dumpcfg",children:"DumpCfg"}),"\n",(0,n.jsxs)(e.p,{children:["Misti provides a feature to dump the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Control-flow_graph",children:"Control Flow Graph (CFG)"})," in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts."]}),"\n",(0,n.jsx)(e.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Mermaid format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=mmd" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Graphviz DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=dot" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=json" \n'})}),"\n",(0,n.jsxs)(e.p,{children:["You could also include Tact standard library functions to the dump adding ",(0,n.jsx)(e.code,{children:"dumpStdlib=true"})," to the ",(0,n.jsx)(e.code,{children:"DumpCfg"})," options."]}),"\n",(0,n.jsx)(e.h2,{id:"working-with-mermaid",children:"Working with Mermaid"}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.a,{href:"https://mermaid.js.org",children:"Mermaid"})," is a JavaScript-based diagramming and charting tool that allows you to create dynamic visualizations, such as flowcharts and sequence diagrams, using a simple syntax. It is integrated into various platforms, including Visual Studio Code."]}),"\n",(0,n.jsxs)(e.p,{children:["To view Mermaid diagrams in Visual Studio Code, you can use the ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid",children:"Markdown Preview Mermaid Support"})," extension. You can also use the ",(0,n.jsx)(e.a,{href:"https://mermaid.live",children:"Mermaid Live Editor"})," to preview your diagrams online."]}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Mermaid format using Misti, run the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=mermaid" \n'})}),"\n",(0,n.jsx)(e.p,{children:"The output can be viewed directly in the VS Code plugin or the online editor."}),"\n",(0,n.jsx)(e.h2,{id:"working-with-graphviz",children:"Working with Graphviz"}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-tact",children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allow you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for understanding the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"Mermaid Dumps"}),": The Mermaid format allows you to generate flowcharts that are easy to read and share. They offer a convenient way to visualize the CFG without requiring additional tools, as they can be directly embedded in markdown files or viewed in the Mermaid Live Editor."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function g(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(I,{...i})}):I(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>d,x:()=>a});var n=t(6540);const s={},l=n.createContext(s);function d(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function a(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:d(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/d3996cd7.2fcfc32a.js b/assets/js/d3996cd7.2fcfc32a.js new file mode 100644 index 000000000..e2d52cd68 --- /dev/null +++ b/assets/js/d3996cd7.2fcfc32a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5664],{9735:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>l,frontMatter:()=>r,metadata:()=>d,toc:()=>c});var n=s(4848),o=s(8453);const r={},i="DumpAst",d={id:"tools/DumpAst",title:"DumpAst",description:"The DumpAst tool in Misti enables users to output the Abstract Syntax Tree (AST) of project modules in JSON format. This is particularly useful when writing custom detectors, as it helps understand the structure and components of the code.",source:"@site/docs/tools/DumpAst.md",sourceDirName:"tools",slug:"/tools/DumpAst",permalink:"/tools/misti/docs/next/tools/DumpAst",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/tools/DumpAst.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Overview",permalink:"/tools/misti/docs/next/tools"},next:{title:"DumpCfg",permalink:"/tools/misti/docs/next/tools/DumpCfg"}},a={},c=[{value:"Usage",id:"usage",level:2},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function u(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dumpast",children:"DumpAst"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"DumpAst"})," tool in Misti enables users to output the ",(0,n.jsx)(t.a,{href:"https://en.wikipedia.org/wiki/Abstract_syntax_tree",children:"Abstract Syntax Tree (AST)"})," of project modules in JSON format. This is particularly useful when writing custom detectors, as it helps understand the structure and components of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(t.p,{children:"To dump the AST in JSON format, use the following command:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'misti -t "DumpAst" \n'})}),"\n",(0,n.jsxs)(t.p,{children:["If you wish to include the standard library in the dump, set ",(0,n.jsx)(t.code,{children:"dumpStdlib"})," to ",(0,n.jsx)(t.code,{children:"true"}),":"]}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-bash",children:'misti -t "DumpAst:dumpStdlib=true" \n'})}),"\n",(0,n.jsx)(t.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(t.p,{children:["The AST provides a detailed breakdown of code components, offering insights into its structure. This is essential when creating or debugging ",(0,n.jsx)(t.a,{href:"/tools/misti/docs/next/hacking/custom-detector",children:"custom detectors"}),", as it allows a deeper understanding of how code is represented internally by the analyzer."]}),"\n",(0,n.jsxs)(t.p,{children:["By leveraging the ",(0,n.jsx)(t.code,{children:"DumpAst"})," tool, developers can more effectively navigate and interpret the project's syntax, supporting the development of accurate and efficient detectors."]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(u,{...e})}):u(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>i,x:()=>d});var n=s(6540);const o={},r=n.createContext(o);function i(e){const t=n.useContext(r);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),n.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d46ee8ed.7ed1c3f4.js b/assets/js/d46ee8ed.7ed1c3f4.js new file mode 100644 index 000000000..b115152fb --- /dev/null +++ b/assets/js/d46ee8ed.7ed1c3f4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8072],{7884:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"0.3.1","label":"0.3.1","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-0.3.1","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/0.3.1/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/0.3.1/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"CI/CD Integration","href":"/tools/misti/docs/0.3.1/tutorial/ci-cd","docId":"tutorial/ci-cd","unlisted":false},{"type":"link","label":"Command-Line Interface","href":"/tools/misti/docs/0.3.1/tutorial/cli","docId":"tutorial/cli","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/0.3.1/tutorial/configuration","docId":"tutorial/configuration","unlisted":false},{"type":"link","label":"Using with Blueprint","href":"/tools/misti/docs/0.3.1/tutorial/blueprint","docId":"tutorial/blueprint","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Detectors Overview","href":"/tools/misti/docs/0.3.1/detectors","docId":"detectors","unlisted":false},{"type":"category","label":"Detectors","items":[{"type":"link","label":"ArgCopyMutation","href":"/tools/misti/docs/0.3.1/detectors/ArgCopyMutation","docId":"detectors/ArgCopyMutation","unlisted":false},{"type":"link","label":"AsmIsUsed","href":"/tools/misti/docs/0.3.1/detectors/AsmIsUsed","docId":"detectors/AsmIsUsed","unlisted":false},{"type":"link","label":"BranchDuplicate","href":"/tools/misti/docs/0.3.1/detectors/BranchDuplicate","docId":"detectors/BranchDuplicate","unlisted":false},{"type":"link","label":"ConstantAddress","href":"/tools/misti/docs/0.3.1/detectors/ConstantAddress","docId":"detectors/ConstantAddress","unlisted":false},{"type":"link","label":"DivideBeforeMultiply","href":"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"DumpIsUsed","href":"/tools/misti/docs/0.3.1/detectors/DumpIsUsed","docId":"detectors/DumpIsUsed","unlisted":false},{"type":"link","label":"FieldDoubleInit","href":"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit","docId":"detectors/FieldDoubleInit","unlisted":false},{"type":"link","label":"InheritedStateMutation","href":"/tools/misti/docs/0.3.1/detectors/InheritedStateMutation","docId":"detectors/InheritedStateMutation","unlisted":false},{"type":"link","label":"NeverAccessedVariables","href":"/tools/misti/docs/0.3.1/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"PreferAugmentedAssign","href":"/tools/misti/docs/0.3.1/detectors/PreferAugmentedAssign","docId":"detectors/PreferAugmentedAssign","unlisted":false},{"type":"link","label":"PreferredStdlibApi","href":"/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi","docId":"detectors/PreferredStdlibApi","unlisted":false},{"type":"link","label":"ReadOnlyVariables","href":"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"StringReceiversOverlap","href":"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap","docId":"detectors/StringReceiversOverlap","unlisted":false},{"type":"link","label":"UnboundLoops","href":"/tools/misti/docs/0.3.1/detectors/UnboundLoops","docId":"detectors/UnboundLoops","unlisted":false},{"type":"link","label":"ZeroAddress","href":"/tools/misti/docs/0.3.1/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/0.3.1/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Design Overview","href":"/tools/misti/docs/0.3.1/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/0.3.1/hacking/souffle","docId":"hacking/souffle","unlisted":false},{"type":"link","label":"Tools","href":"/tools/misti/docs/0.3.1/hacking/tools","docId":"hacking/tools","unlisted":false},{"type":"link","label":"Custom Detectors","href":"/tools/misti/docs/0.3.1/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"detectors":{"id":"detectors","title":"Detectors Overview","description":"Misti currently supports 15 detectors designed to identify specific code issues, detect vulnerabilities, and enforce best practices:","sidebar":"sidebar"},"detectors/ArgCopyMutation":{"id":"detectors/ArgCopyMutation","title":"ArgCopyMutation","description":"A detector that highlights cases where function argument mutations are ineffective","sidebar":"sidebar"},"detectors/AsmIsUsed":{"id":"detectors/AsmIsUsed","title":"AsmIsUsed","description":"An optional detector that highlights all the asm functions.","sidebar":"sidebar"},"detectors/BranchDuplicate":{"id":"detectors/BranchDuplicate","title":"BranchDuplicate","description":"Detector that reports duplicated code in conditional branches.","sidebar":"sidebar"},"detectors/ConstantAddress":{"id":"detectors/ConstantAddress","title":"ConstantAddress","description":"An optional detector that highlights all the constant addresses appearing in the source code.","sidebar":"sidebar"},"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"DivideBeforeMultiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/DumpIsUsed":{"id":"detectors/DumpIsUsed","title":"DumpIsUsed","description":"An optional detector that highlights all the dump function calls.","sidebar":"sidebar"},"detectors/FieldDoubleInit":{"id":"detectors/FieldDoubleInit","title":"FieldDoubleInit","description":"A detector that highlights cases where a field is initialized both in the","sidebar":"sidebar"},"detectors/InheritedStateMutation":{"id":"detectors/InheritedStateMutation","title":"InheritedStateMutation","description":"An optional detector that highlights all instances where inherited trait variables","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"NeverAccessedVariables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/PreferAugmentedAssign":{"id":"detectors/PreferAugmentedAssign","title":"PreferAugmentedAssign","description":"Detects non-idiomatic statements that can be written using augmented assignment","sidebar":"sidebar"},"detectors/PreferredStdlibApi":{"id":"detectors/PreferredStdlibApi","title":"PreferredStdlibApi","description":"An optional detector that flags the use of advanced functions from the standard library.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"ReadOnlyVariables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/StringReceiversOverlap":{"id":"detectors/StringReceiversOverlap","title":"StringReceiversOverlap","description":"A detector that finds overlapping messages between general string receivers and string receivers.","sidebar":"sidebar"},"detectors/UnboundLoops":{"id":"detectors/UnboundLoops","title":"UnboundLoops","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"ZeroAddress","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"hacking/tools":{"id":"hacking/tools","title":"Tools Guide","description":"This page describes the internal analyzer tools available in Misti to aid in development and debugging.","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tutorial/blueprint":{"id":"tutorial/blueprint","title":"Using Misti with Blueprint","description":"Blueprint is a development environment for writing, testing, and deploying TON smart contracts.","sidebar":"sidebar"},"tutorial/ci-cd":{"id":"tutorial/ci-cd","title":"Integrating Misti into CI/CD","description":"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.","sidebar":"sidebar"},"tutorial/cli":{"id":"tutorial/cli","title":"Command-Line Interface","description":"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each.","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/d6f3e79e.d1be0df5.js b/assets/js/d6f3e79e.d1be0df5.js new file mode 100644 index 000000000..e70d9d318 --- /dev/null +++ b/assets/js/d6f3e79e.d1be0df5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1678],{1747:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var a=t(4848),i=t(8453);const r={},s="Read-only Variables",o={id:"detectors/ReadOnlyVariables",title:"Read-only Variables",description:"A detector that identifies read-only variables and fields.",source:"@site/versioned_docs/version-0.1.2/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/detectors/ReadOnlyVariables.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Never-accessed Variables",permalink:"/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables"},next:{title:"Unbound Loops",permalink:"/tools/misti/docs/0.1.2/detectors/UnboundLoops"}},l={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h1,{id:"read-only-variables",children:"Read-only Variables"}),"\n",(0,a.jsx)(n.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,a.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,a.jsx)(n.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,a.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,a.jsx)(n.p,{children:"Use instead:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the linter highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>s,x:()=>o});var a=t(6540);const i={},r=a.createContext(i);function s(e){const n=a.useContext(r);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:s(e.components),a.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d7c99f30.2f60268c.js b/assets/js/d7c99f30.2f60268c.js new file mode 100644 index 000000000..2f721f3bb --- /dev/null +++ b/assets/js/d7c99f30.2f60268c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8904],{7389:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={},r="OptimalMathFunction",a={id:"detectors/OptimalMathFunction",title:"OptimalMathFunction",description:"A detector that highlights standard library math function calls that have more gas-efficient alternatives.",source:"@site/versioned_docs/version-0.4.0/detectors/OptimalMathFunction.md",sourceDirName:"detectors",slug:"/detectors/OptimalMathFunction",permalink:"/tools/misti/docs/0.4.0/detectors/OptimalMathFunction",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/OptimalMathFunction.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"NeverAccessedVariables",permalink:"/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables"},next:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"optimalmathfunction",children:"OptimalMathFunction"}),"\n",(0,i.jsx)(t.p,{children:"A detector that highlights standard library math function calls that have more gas-efficient alternatives."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(t.p,{children:["Tact supports ",(0,i.jsx)(t.code,{children:"log2"}),"/",(0,i.jsx)(t.code,{children:"pow2"})," functions, which are more gas-efficient than ",(0,i.jsx)(t.code,{children:"log(x, 2)"}),"/",(0,i.jsx)(t.code,{children:"pow(x, 2)"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"log(x, 2);\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"log2(x)\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d7d99e1d.67e2d007.js b/assets/js/d7d99e1d.67e2d007.js new file mode 100644 index 000000000..0f74a1ddd --- /dev/null +++ b/assets/js/d7d99e1d.67e2d007.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9076],{668:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="Never-accessed Variables",o={id:"detectors/NeverAccessedVariables",title:"Never-accessed Variables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.2.2/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/NeverAccessedVariables.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Divide before Multiply",permalink:"/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply"},next:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"never-accessed-variables",children:"Never-accessed Variables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the linter highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d7ebd85b.81f998f6.js b/assets/js/d7ebd85b.81f998f6.js new file mode 100644 index 000000000..bf5d92ed2 --- /dev/null +++ b/assets/js/d7ebd85b.81f998f6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5308],{6659:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>n,metadata:()=>r,toc:()=>a});var o=t(4848),i=t(8453);const n={id:"tools",title:"Tools Overview"},l="Tools Overview",r={id:"tools",title:"Tools Overview",description:"Misti Tools are additional modules designed to work alongside detectors, enabling various tasks beyond code analysis.",source:"@site/versioned_docs/version-0.5/tools.md",sourceDirName:".",slug:"/tools",permalink:"/tools/misti/docs/tools",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tools.md",tags:[],version:"0.5",frontMatter:{id:"tools",title:"Tools Overview"},sidebar:"sidebar",previous:{title:"ZeroAddress",permalink:"/tools/misti/docs/detectors/ZeroAddress"},next:{title:"DumpAst",permalink:"/tools/misti/docs/tools/DumpAst"}},d={},a=[{value:"Usage",id:"usage",level:2},{value:"Usage Examples",id:"usage-examples",level:2},{value:"Available Tools",id:"available-tools",level:2}];function c(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(s.h1,{id:"tools-overview",children:"Tools Overview"}),"\n",(0,o.jsx)(s.p,{children:"Misti Tools are additional modules designed to work alongside detectors, enabling various tasks beyond code analysis."}),"\n",(0,o.jsx)(s.p,{children:"These tools are particularly useful for auditors, providing additional functionalities to assist in manual code reviews."}),"\n",(0,o.jsx)(s.h2,{id:"usage",children:"Usage"}),"\n",(0,o.jsx)(s.p,{children:"List available tools and their options:"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-bash",children:"misti --list-tools\n"})}),"\n",(0,o.jsx)(s.p,{children:"To invoke a specific tool, use the following command format:"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{className:"language-bash",children:'misti -t "ToolName:option=value,option=value" /path/to/tact.config.json\n'})}),"\n",(0,o.jsx)(s.h2,{id:"usage-examples",children:"Usage Examples"}),"\n",(0,o.jsx)(s.p,{children:"Dump the AST of the project:"}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{children:'misti -t "DumpAst" my-example.tact\n'})}),"\n",(0,o.jsxs)(s.p,{children:["Dump the CFGs of the project in ",(0,o.jsx)(s.a,{href:"https://mermaid.live",children:"Mermaid"})," format to the file ",(0,o.jsx)(s.code,{children:"/tmp/my-example.DumpCfg.out"}),":"]}),"\n",(0,o.jsx)(s.pre,{children:(0,o.jsx)(s.code,{children:'misti --output-path "/tmp" -t "DumpCfg:format=mermaid" my-example.tact\n'})}),"\n",(0,o.jsx)(s.h2,{id:"available-tools",children:"Available Tools"}),"\n",(0,o.jsx)(s.p,{children:"Below is the complete list of built-in tools. Click on any of them to learn more."}),"\n",(0,o.jsxs)(s.table,{children:[(0,o.jsx)(s.thead,{children:(0,o.jsxs)(s.tr,{children:[(0,o.jsx)(s.th,{children:"#"}),(0,o.jsx)(s.th,{children:"Tool"}),(0,o.jsx)(s.th,{children:"Description"})]})}),(0,o.jsxs)(s.tbody,{children:[(0,o.jsxs)(s.tr,{children:[(0,o.jsx)(s.td,{children:"1"}),(0,o.jsx)(s.td,{children:(0,o.jsx)(s.a,{href:"/tools/misti/docs/tools/DumpAst",children:"DumpAst"})}),(0,o.jsx)(s.td,{children:"Dumps the AST of project modules"})]}),(0,o.jsxs)(s.tr,{children:[(0,o.jsx)(s.td,{children:"2"}),(0,o.jsx)(s.td,{children:(0,o.jsx)(s.a,{href:"/tools/misti/docs/tools/DumpCfg",children:"DumpCfg"})}),(0,o.jsx)(s.td,{children:"Dumps the CFG of project modules"})]}),(0,o.jsxs)(s.tr,{children:[(0,o.jsx)(s.td,{children:"3"}),(0,o.jsx)(s.td,{children:(0,o.jsx)(s.a,{href:"/tools/misti/docs/tools/DumpConfig",children:"DumpConfig"})}),(0,o.jsx)(s.td,{children:"Dumps the Misti configuration file in use"})]}),(0,o.jsxs)(s.tr,{children:[(0,o.jsx)(s.td,{children:"4"}),(0,o.jsx)(s.td,{children:(0,o.jsx)(s.a,{href:"/tools/misti/docs/tools/DumpImports",children:"DumpImports"})}),(0,o.jsx)(s.td,{children:"Dumps the graph of imports"})]})]})]})]})}function h(e={}){const{wrapper:s}={...(0,i.R)(),...e.components};return s?(0,o.jsx)(s,{...e,children:(0,o.jsx)(c,{...e})}):c(e)}},8453:(e,s,t)=>{t.d(s,{R:()=>l,x:()=>r});var o=t(6540);const i={},n=o.createContext(i);function l(e){const s=o.useContext(n);return o.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function r(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:l(e.components),o.createElement(n.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d9542fcf.bbcb88d0.js b/assets/js/d9542fcf.bbcb88d0.js new file mode 100644 index 000000000..033f9c03f --- /dev/null +++ b/assets/js/d9542fcf.bbcb88d0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3590],{2866:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="Branch Duplicate",o={id:"detectors/BranchDuplicate",title:"Branch Duplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.2.0/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/0.2.0/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors/BranchDuplicate.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Constant Address",permalink:"/tools/misti/docs/0.2.0/detectors/ConstantAddress"},next:{title:"`dump` Is Used",permalink:"/tools/misti/docs/0.2.0/detectors/DumpIsUsed"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branch-duplicate",children:"Branch Duplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/d9941f94.b1fb5e38.js b/assets/js/d9941f94.b1fb5e38.js new file mode 100644 index 000000000..84dcca808 --- /dev/null +++ b/assets/js/d9941f94.b1fb5e38.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8183],{7084:(i,e,t)=>{t.r(e),t.d(e,{assets:()=>o,contentTitle:()=>d,default:()=>g,frontMatter:()=>l,metadata:()=>a,toc:()=>r});var n=t(4848),s=t(8453);const l={},d="DumpCfg",a={id:"tools/DumpCfg",title:"DumpCfg",description:"Misti provides a feature to dump the Control Flow Graph (CFG) in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts.",source:"@site/versioned_docs/version-0.5/tools/DumpCfg.md",sourceDirName:"tools",slug:"/tools/DumpCfg",permalink:"/tools/misti/docs/tools/DumpCfg",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tools/DumpCfg.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpAst",permalink:"/tools/misti/docs/tools/DumpAst"},next:{title:"DumpConfig",permalink:"/tools/misti/docs/tools/DumpConfig"}},o={},r=[{value:"Usage",id:"usage",level:2},{value:"Working with Mermaid",id:"working-with-mermaid",level:2},{value:"Working with Graphviz",id:"working-with-graphviz",level:2},{value:"Converting DOT to SVG",id:"converting-dot-to-svg",level:3},{value:"Viewing the SVG",id:"viewing-the-svg",level:3},{value:"VS Code Plugin",id:"vs-code-plugin",level:3},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2}];function I(i){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...i.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(e.h1,{id:"dumpcfg",children:"DumpCfg"}),"\n",(0,n.jsxs)(e.p,{children:["Misti provides a feature to dump the ",(0,n.jsx)(e.a,{href:"https://en.wikipedia.org/wiki/Control-flow_graph",children:"Control Flow Graph (CFG)"})," in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts."]}),"\n",(0,n.jsx)(e.h2,{id:"usage",children:"Usage"}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Mermaid format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=mmd" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Graphviz DOT format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=dot" \n'})}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in JSON format, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=json" \n'})}),"\n",(0,n.jsxs)(e.p,{children:["You could also include Tact standard library functions to the dump adding ",(0,n.jsx)(e.code,{children:"dumpStdlib=true"})," to the ",(0,n.jsx)(e.code,{children:"DumpCfg"})," options."]}),"\n",(0,n.jsx)(e.h2,{id:"working-with-mermaid",children:"Working with Mermaid"}),"\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.a,{href:"https://mermaid.js.org",children:"Mermaid"})," is a JavaScript-based diagramming and charting tool that allows you to create dynamic visualizations, such as flowcharts and sequence diagrams, using a simple syntax. It is integrated into various platforms, including Visual Studio Code."]}),"\n",(0,n.jsxs)(e.p,{children:["To view Mermaid diagrams in Visual Studio Code, you can use the ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid",children:"Markdown Preview Mermaid Support"})," extension. You can also use the ",(0,n.jsx)(e.a,{href:"https://mermaid.live",children:"Mermaid Live Editor"})," to preview your diagrams online."]}),"\n",(0,n.jsx)(e.p,{children:"To dump the CFG in Mermaid format using Misti, run the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=mermaid" \n'})}),"\n",(0,n.jsx)(e.p,{children:"The output can be viewed directly in the VS Code plugin or the online editor."}),"\n",(0,n.jsx)(e.h2,{id:"working-with-graphviz",children:"Working with Graphviz"}),"\n",(0,n.jsx)(e.h3,{id:"converting-dot-to-svg",children:"Converting DOT to SVG"}),"\n",(0,n.jsxs)(e.p,{children:["To convert the resulting DOT file to an SVG for visualization, save the generated DOT dump to a file and use ",(0,n.jsx)(e.a,{href:"https://graphviz.org",children:"Graphviz"})," with the following command:"]}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:'misti -t "DumpCfg:format=dot" > output.dot\ndot -Tsvg output.dot -o output.svg\n'})}),"\n",(0,n.jsx)(e.h3,{id:"viewing-the-svg",children:"Viewing the SVG"}),"\n",(0,n.jsx)(e.p,{children:"To view the SVG file in Firefox, use the following command:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-bash",children:"firefox output.svg\n"})}),"\n",(0,n.jsx)(e.p,{children:"For example, for the following contract:"}),"\n",(0,n.jsx)(e.pre,{children:(0,n.jsx)(e.code,{className:"language-tact",children:"fun test(): Int {\n let sum: Int = 0;\n let i: Int = 0;\n repeat (10) {\n i = i + 1;\n sum = sum + i;\n }\n return sum;\n}\n"})}),"\n",(0,n.jsx)(e.p,{children:"The following CFG will be generated:"}),"\n",(0,n.jsx)(e.p,{children:(0,n.jsx)(e.img,{alt:"CFG Example",src:t(685).A+"",width:"337",height:"516"})}),"\n",(0,n.jsx)(e.h3,{id:"vs-code-plugin",children:"VS Code Plugin"}),"\n",(0,n.jsxs)(e.p,{children:["For real-time visualization of DOT files, you can use ",(0,n.jsx)(e.a,{href:"https://marketplace.visualstudio.com/search?term=tag%3Agraphviz&target=VSCode&category=All%20categories&sortBy=Relevance",children:"one of the available"})," Graphviz plugins for Visual Studio Code. These plugins allow you to view DOT diagrams directly within the editor, facilitating easier debugging and development."]}),"\n",(0,n.jsx)(e.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,n.jsxs)(e.ul,{children:["\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"JSON Dumps"}),": These are mostly helpful for understanding low-level details on how the IR is generated. They provide a comprehensive representation of the internal structures used by the analyzer."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"DOT Dumps"}),": These provide a visual representation of the contract's control flow. They are particularly useful for understanding the control flow within contracts, making it easier to identify issues and optimize the code."]}),"\n"]}),"\n",(0,n.jsxs)(e.li,{children:["\n",(0,n.jsxs)(e.p,{children:[(0,n.jsx)(e.strong,{children:"Mermaid Dumps"}),": The Mermaid format allows you to generate flowcharts that are easy to read and share. They offer a convenient way to visualize the CFG without requiring additional tools, as they can be directly embedded in markdown files or viewed in the Mermaid Live Editor."]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(e.p,{children:"By utilizing these tools, developers can gain deeper insights into the workings of the static analyzer and effectively debug and enhance their custom detectors."})]})}function g(i={}){const{wrapper:e}={...(0,s.R)(),...i.components};return e?(0,n.jsx)(e,{...i,children:(0,n.jsx)(I,{...i})}):I(i)}},685:(i,e,t)=>{t.d(e,{A:()=>n});const n="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIKICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8IS0tIEdlbmVyYXRlZCBieSBncmFwaHZpeiB2ZXJzaW9uIDIuNDIuNCAoMCkKIC0tPgo8IS0tIFRpdGxlOiBsb29wcyYjNDU7MyBQYWdlczogMSAtLT4KPHN2ZyB3aWR0aD0iMjUzcHQiIGhlaWdodD0iMzg3cHQiCiB2aWV3Qm94PSIwLjAwIDAuMDAgMjUzLjAwIDM4Ny4wMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayI+CjxnIGlkPSJncmFwaDAiIGNsYXNzPSJncmFwaCIgdHJhbnNmb3JtPSJzY2FsZSgxIDEpIHJvdGF0ZSgwKSB0cmFuc2xhdGUoNCAzODMpIj4KPHRpdGxlPmxvb3BzJiM0NTszPC90aXRsZT4KPHBvbHlnb24gZmlsbD0id2hpdGUiIHN0cm9rZT0idHJhbnNwYXJlbnQiIHBvaW50cz0iLTQsNCAtNCwtMzgzIDI0OSwtMzgzIDI0OSw0IC00LDQiLz4KPGcgaWQ9ImNsdXN0MSIgY2xhc3M9ImNsdXN0ZXIiPgo8dGl0bGU+Y2x1c3Rlcl90ZXN0PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSI4LC04IDgsLTM3MSAyMzcsLTM3MSAyMzcsLTggOCwtOCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIuNSIgeT0iLTM1NS44IiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnRlc3Q8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0MSAtLT4KPGcgaWQ9Im5vZGUxIiBjbGFzcz0ibm9kZSI+Cjx0aXRsZT50ZXN0XzE0MTwvdGl0bGU+Cjxwb2x5Z29uIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMjI0LjUsLTM0MCA5NS41LC0zNDAgOTUuNSwtMzA0IDIyNC41LC0zMDQgMjI0LjUsLTM0MCIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxNjAiIHk9Ii0zMTguMyIgZm9udC1mYW1pbHk9IlRpbWVzLHNlcmlmIiBmb250LXNpemU9IjE0LjAwIj5sZXQgc3VtOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDIgLS0+CjxnIGlkPSJub2RlMiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDI8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIxMiwtMjY4IDEwOCwtMjY4IDEwOCwtMjMyIDIxMiwtMjMyIDIxMiwtMjY4Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTI0Ni4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPmxldCBpOiBJbnQgPSAwPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDEmIzQ1OyZndDt0ZXN0XzE0MiAtLT4KPGcgaWQ9ImVkZ2UxIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MSYjNDU7Jmd0O3Rlc3RfMTQyPC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMzAzLjdDMTYwLC0yOTUuOTggMTYwLC0yODYuNzEgMTYwLC0yNzguMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTI3OC4xIDE2MCwtMjY4LjEgMTU2LjUsLTI3OC4xIDE2My41LC0yNzguMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDQgLS0+CjxnIGlkPSJub2RlMyIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDQ8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOCwtMTk2IDExMiwtMTk2IDExMiwtMTYwIDIwOCwtMTYwIDIwOCwtMTk2Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjE2MCIgeT0iLTE3NC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnJlcGVhdCAoMTApPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDImIzQ1OyZndDt0ZXN0XzE0NCAtLT4KPGcgaWQ9ImVkZ2UyIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0MiYjNDU7Jmd0O3Rlc3RfMTQ0PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE2MCwtMjMxLjdDMTYwLC0yMjMuOTggMTYwLC0yMTQuNzEgMTYwLC0yMDYuMTEiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTYzLjUsLTIwNi4xIDE2MCwtMTk2LjEgMTU2LjUsLTIwNi4xIDE2My41LC0yMDYuMSIvPgo8L2c+CjwhLS0gdGVzdF8xNDYgLS0+CjxnIGlkPSJub2RlNCIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNDY8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjkzLjUsLTEyNCAxNi41LC0xMjQgMTYuNSwtODggOTMuNSwtODggOTMuNSwtMTI0Ii8+Cjx0ZXh0IHRleHQtYW5jaG9yPSJtaWRkbGUiIHg9IjU1IiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+aSA9IGkgKyAxPC90ZXh0Pgo8L2c+CjwhLS0gdGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE0NiAtLT4KPGcgaWQ9ImVkZ2UzIiBjbGFzcz0iZWRnZSI+Cjx0aXRsZT50ZXN0XzE0NCYjNDU7Jmd0O3Rlc3RfMTQ2PC90aXRsZT4KPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTEzNC4zMSwtMTU5Ljg4QzEyMC43MSwtMTUwLjgxIDEwMy44MywtMTM5LjU1IDg5LjE0LC0xMjkuNzYiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iOTEuMDUsLTEyNi44MiA4MC43OCwtMTI0LjE5IDg3LjE2LC0xMzIuNjUgOTEuMDUsLTEyNi44MiIvPgo8L2c+CjwhLS0gdGVzdF8xNTEgLS0+CjxnIGlkPSJub2RlNiIgY2xhc3M9Im5vZGUiPgo8dGl0bGU+dGVzdF8xNTE8L3RpdGxlPgo8cG9seWdvbiBmaWxsPSIjNjZhN2RiIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjIwOC41LC0xMjQgMTExLjUsLTEyNCAxMTEuNSwtODggMjA4LjUsLTg4IDIwOC41LC0xMjQiLz4KPHRleHQgdGV4dC1hbmNob3I9Im1pZGRsZSIgeD0iMTYwIiB5PSItMTAyLjMiIGZvbnQtZmFtaWx5PSJUaW1lcyxzZXJpZiIgZm9udC1zaXplPSIxNC4wMCI+cmV0dXJuIHN1bTwvdGV4dD4KPC9nPgo8IS0tIHRlc3RfMTQ0JiM0NTsmZ3Q7dGVzdF8xNTEgLS0+CjxnIGlkPSJlZGdlNiIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDQmIzQ1OyZndDt0ZXN0XzE1MTwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNjAsLTE1OS43QzE2MCwtMTUxLjk4IDE2MCwtMTQyLjcxIDE2MCwtMTM0LjExIi8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiBwb2ludHM9IjE2My41LC0xMzQuMSAxNjAsLTEyNC4xIDE1Ni41LC0xMzQuMSAxNjMuNSwtMTM0LjEiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4IC0tPgo8ZyBpZD0ibm9kZTUiIGNsYXNzPSJub2RlIj4KPHRpdGxlPnRlc3RfMTQ4PC90aXRsZT4KPHBvbHlnb24gZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgcG9pbnRzPSIxODMuNSwtNTIgNjAuNSwtNTIgNjAuNSwtMTYgMTgzLjUsLTE2IDE4My41LC01MiIvPgo8dGV4dCB0ZXh0LWFuY2hvcj0ibWlkZGxlIiB4PSIxMjIiIHk9Ii0zMC4zIiBmb250LWZhbWlseT0iVGltZXMsc2VyaWYiIGZvbnQtc2l6ZT0iMTQuMDAiPnN1bSA9IHN1bSArIGk8L3RleHQ+CjwvZz4KPCEtLSB0ZXN0XzE0NiYjNDU7Jmd0O3Rlc3RfMTQ4IC0tPgo8ZyBpZD0iZWRnZTQiIGNsYXNzPSJlZGdlIj4KPHRpdGxlPnRlc3RfMTQ2JiM0NTsmZ3Q7dGVzdF8xNDg8L3RpdGxlPgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNzEuNTYsLTg3LjdDNzkuNjgsLTc5LjIyIDg5LjU5LC02OC44NiA5OC40NywtNTkuNTgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTAxLjI0LC02MS43NSAxMDUuNjMsLTUyLjEgOTYuMTksLTU2LjkxIDEwMS4yNCwtNjEuNzUiLz4KPC9nPgo8IS0tIHRlc3RfMTQ4JiM0NTsmZ3Q7dGVzdF8xNDQgLS0+CjxnIGlkPSJlZGdlNSIgY2xhc3M9ImVkZ2UiPgo8dGl0bGU+dGVzdF8xNDgmIzQ1OyZndDt0ZXN0XzE0NDwvdGl0bGU+CjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjIsLTUyLjA0QzE5MS44OSwtNjAuMTYgMjA4LjQyLC03MS43NyAyMTgsLTg4IDIyNi4xMywtMTAxLjc4IDIyNC40NSwtMTA5LjM2IDIxOCwtMTI0IDIxMy4wMSwtMTM1LjMxIDIwNC4yOSwtMTQ1LjI2IDE5NS4xLC0xNTMuMzgiLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIHBvaW50cz0iMTkyLjgzLC0xNTAuNzIgMTg3LjM0LC0xNTkuNzcgMTk3LjI4LC0xNTYuMTIgMTkyLjgzLC0xNTAuNzIiLz4KPC9nPgo8L2c+Cjwvc3ZnPgo="},8453:(i,e,t)=>{t.d(e,{R:()=>d,x:()=>a});var n=t(6540);const s={},l=n.createContext(s);function d(i){const e=n.useContext(l);return n.useMemo((function(){return"function"==typeof i?i(e):{...e,...i}}),[e,i])}function a(i){let e;return e=i.disableParentContext?"function"==typeof i.components?i.components(s):i.components||s:d(i.components),n.createElement(l.Provider,{value:e},i.children)}}}]); \ No newline at end of file diff --git a/assets/js/dc55925b.1af0a38f.js b/assets/js/dc55925b.1af0a38f.js new file mode 100644 index 000000000..e0a56cdff --- /dev/null +++ b/assets/js/dc55925b.1af0a38f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8546],{5729:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>s,toc:()=>c});var i=t(4848),r=t(8453);const o={},a="EnsurePrgSeed",s={id:"detectors/EnsurePrgSeed",title:"EnsurePrgSeed",description:"A detector that identifies all calls to nativeRandom and nativeRandomInterval",source:"@site/docs/detectors/EnsurePrgSeed.md",sourceDirName:"detectors",slug:"/detectors/EnsurePrgSeed",permalink:"/tools/misti/docs/next/detectors/EnsurePrgSeed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/EnsurePrgSeed.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"DuplicatedCondition",permalink:"/tools/misti/docs/next/detectors/DuplicatedCondition"},next:{title:"FalseCondition",permalink:"/tools/misti/docs/next/detectors/FalseCondition"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const n={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"ensureprgseed",children:"EnsurePrgSeed"}),"\n",(0,i.jsxs)(n.p,{children:["A detector that identifies all calls to ",(0,i.jsx)(n.code,{children:"nativeRandom"})," and ",(0,i.jsx)(n.code,{children:"nativeRandomInterval"}),"\nwithout a preceding PRG seed initialization."]}),"\n",(0,i.jsx)(n.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsxs)(n.p,{children:["Using ",(0,i.jsx)(n.code,{children:"nativeRandom"})," or ",(0,i.jsx)(n.code,{children:"nativeRandomInterval"})," without first initializing the PRG seed via\n",(0,i.jsx)(n.code,{children:"nativePrepareRandom"}),", ",(0,i.jsx)(n.code,{children:"nativeRandomize"}),", or ",(0,i.jsx)(n.code,{children:"nativeRandomizeLt"})," may lead to unintended behavior\nor weak random number generation. This detector ensures that PRG seed initialization\nis always performed before any use of random functions, enhancing contract security."]}),"\n",(0,i.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"// Bad: `nativeRandom` is used without prior PRG seed initialization\nfun generateRandomValue(): Int {\n return nativeRandom()\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"Use instead:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"fun test(): Int {\n nativePrepareRandom();\n}\n\n// OK: PRG has been initialized somewhere in the contract\nfun generateRandomValue(): Int {\n return nativeRandom()\n}\n"})})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>s});var i=t(6540);const r={},o=i.createContext(r);function a(e){const n=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),i.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/dd8730c9.ffc63748.js b/assets/js/dd8730c9.ffc63748.js new file mode 100644 index 000000000..44b0ea848 --- /dev/null +++ b/assets/js/dd8730c9.ffc63748.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8137],{2205:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"current","label":"Next","banner":"unreleased","badge":true,"noIndex":false,"className":"docs-version-current","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/next/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/next/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"CI/CD Integration","href":"/tools/misti/docs/next/tutorial/ci-cd","docId":"tutorial/ci-cd","unlisted":false},{"type":"link","label":"Command-Line Interface","href":"/tools/misti/docs/next/tutorial/cli","docId":"tutorial/cli","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/next/tutorial/configuration","docId":"tutorial/configuration","unlisted":false},{"type":"link","label":"Using with Blueprint","href":"/tools/misti/docs/next/tutorial/blueprint","docId":"tutorial/blueprint","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"html","value":"
"},{"type":"html","value":" "},{"type":"link","label":"Overview","href":"/tools/misti/docs/next/detectors","docId":"detectors","unlisted":false},{"type":"category","label":"Built-in Detectors","items":[{"type":"link","label":"ArgCopyMutation","href":"/tools/misti/docs/next/detectors/ArgCopyMutation","docId":"detectors/ArgCopyMutation","unlisted":false},{"type":"link","label":"AsmIsUsed","href":"/tools/misti/docs/next/detectors/AsmIsUsed","docId":"detectors/AsmIsUsed","unlisted":false},{"type":"link","label":"BranchDuplicate","href":"/tools/misti/docs/next/detectors/BranchDuplicate","docId":"detectors/BranchDuplicate","unlisted":false},{"type":"link","label":"CellOverflow","href":"/tools/misti/docs/next/detectors/CellOverflow","docId":"detectors/CellOverflow","unlisted":false},{"type":"link","label":"ConstantAddress","href":"/tools/misti/docs/next/detectors/ConstantAddress","docId":"detectors/ConstantAddress","unlisted":false},{"type":"link","label":"DivideBeforeMultiply","href":"/tools/misti/docs/next/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"DumpIsUsed","href":"/tools/misti/docs/next/detectors/DumpIsUsed","docId":"detectors/DumpIsUsed","unlisted":false},{"type":"link","label":"DuplicatedCondition","href":"/tools/misti/docs/next/detectors/DuplicatedCondition","docId":"detectors/DuplicatedCondition","unlisted":false},{"type":"link","label":"EnsurePrgSeed","href":"/tools/misti/docs/next/detectors/EnsurePrgSeed","docId":"detectors/EnsurePrgSeed","unlisted":false},{"type":"link","label":"FalseCondition","href":"/tools/misti/docs/next/detectors/FalseCondition","docId":"detectors/FalseCondition","unlisted":false},{"type":"link","label":"FieldDoubleInit","href":"/tools/misti/docs/next/detectors/FieldDoubleInit","docId":"detectors/FieldDoubleInit","unlisted":false},{"type":"link","label":"InheritedStateMutation","href":"/tools/misti/docs/next/detectors/InheritedStateMutation","docId":"detectors/InheritedStateMutation","unlisted":false},{"type":"link","label":"NeverAccessedVariables","href":"/tools/misti/docs/next/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"OptimalMathFunction","href":"/tools/misti/docs/next/detectors/OptimalMathFunction","docId":"detectors/OptimalMathFunction","unlisted":false},{"type":"link","label":"PreferAugmentedAssign","href":"/tools/misti/docs/next/detectors/PreferAugmentedAssign","docId":"detectors/PreferAugmentedAssign","unlisted":false},{"type":"link","label":"PreferredStdlibApi","href":"/tools/misti/docs/next/detectors/PreferredStdlibApi","docId":"detectors/PreferredStdlibApi","unlisted":false},{"type":"link","label":"ReadOnlyVariables","href":"/tools/misti/docs/next/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"SendInLoop","href":"/tools/misti/docs/next/detectors/SendInLoop","docId":"detectors/SendInLoop","unlisted":false},{"type":"link","label":"ShortCircuitCondition","href":"/tools/misti/docs/next/detectors/ShortCircuitCondition","docId":"detectors/ShortCircuitCondition","unlisted":false},{"type":"link","label":"StringReceiversOverlap","href":"/tools/misti/docs/next/detectors/StringReceiversOverlap","docId":"detectors/StringReceiversOverlap","unlisted":false},{"type":"link","label":"SuspiciousMessageMode","href":"/tools/misti/docs/next/detectors/SuspiciousMessageMode","docId":"detectors/SuspiciousMessageMode","unlisted":false},{"type":"link","label":"UnboundLoop","href":"/tools/misti/docs/next/detectors/UnboundLoop","docId":"detectors/UnboundLoop","unlisted":false},{"type":"link","label":"UnboundMap","href":"/tools/misti/docs/next/detectors/UnboundMap","docId":"detectors/UnboundMap","unlisted":false},{"type":"link","label":"UnusedExpressionResult","href":"/tools/misti/docs/next/detectors/UnusedExpressionResult","docId":"detectors/UnusedExpressionResult","unlisted":false},{"type":"link","label":"UnusedOptional","href":"/tools/misti/docs/next/detectors/UnusedOptional","docId":"detectors/UnusedOptional","unlisted":false},{"type":"link","label":"ZeroAddress","href":"/tools/misti/docs/next/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"html","value":"
"},{"type":"html","value":" "},{"type":"link","label":"Overview","href":"/tools/misti/docs/next/tools","docId":"tools","unlisted":false},{"type":"category","label":"Built-in Tools","items":[{"type":"link","label":"DumpAst","href":"/tools/misti/docs/next/tools/DumpAst","docId":"tools/DumpAst","unlisted":false},{"type":"link","label":"DumpCfg","href":"/tools/misti/docs/next/tools/DumpCfg","docId":"tools/DumpCfg","unlisted":false},{"type":"link","label":"DumpConfig","href":"/tools/misti/docs/next/tools/DumpConfig","docId":"tools/DumpConfig","unlisted":false},{"type":"link","label":"DumpImports","href":"/tools/misti/docs/next/tools/DumpImports","docId":"tools/DumpImports","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"html","value":"
"},{"type":"html","value":" "},{"type":"category","label":"Misti Design","items":[{"type":"link","label":"Design Overview","href":"/tools/misti/docs/next/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/next/hacking/souffle","docId":"hacking/souffle","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/next/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Developing Misti","href":"/tools/misti/docs/next/hacking/developing-misti","docId":"hacking/developing-misti","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Writing Custom Detectors","href":"/tools/misti/docs/next/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false}]},"docs":{"detectors":{"id":"detectors","title":"Detectors Overview","description":"Built-in Detectors","sidebar":"sidebar"},"detectors/ArgCopyMutation":{"id":"detectors/ArgCopyMutation","title":"ArgCopyMutation","description":"A detector that highlights cases where function argument mutations are ineffective","sidebar":"sidebar"},"detectors/AsmIsUsed":{"id":"detectors/AsmIsUsed","title":"AsmIsUsed","description":"An optional detector that highlights all the asm functions.","sidebar":"sidebar"},"detectors/BranchDuplicate":{"id":"detectors/BranchDuplicate","title":"BranchDuplicate","description":"Detector that reports duplicated code in conditional branches.","sidebar":"sidebar"},"detectors/CellOverflow":{"id":"detectors/CellOverflow","title":"CellOverflow","description":"A detector that identifies cell overflow problems.","sidebar":"sidebar"},"detectors/ConstantAddress":{"id":"detectors/ConstantAddress","title":"ConstantAddress","description":"An optional detector that highlights all the constant addresses appearing in the source code.","sidebar":"sidebar"},"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"DivideBeforeMultiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/DumpIsUsed":{"id":"detectors/DumpIsUsed","title":"DumpIsUsed","description":"An optional detector that highlights all the dump debug prints.","sidebar":"sidebar"},"detectors/DuplicatedCondition":{"id":"detectors/DuplicatedCondition","title":"DuplicatedCondition","description":"A detector that finds duplicated conditions appearing in conditional expressions.","sidebar":"sidebar"},"detectors/EnsurePrgSeed":{"id":"detectors/EnsurePrgSeed","title":"EnsurePrgSeed","description":"A detector that identifies all calls to nativeRandom and nativeRandomInterval","sidebar":"sidebar"},"detectors/FalseCondition":{"id":"detectors/FalseCondition","title":"FalseCondition","description":"A detector that highlights conditions that evaluate to a constant true or false","sidebar":"sidebar"},"detectors/FieldDoubleInit":{"id":"detectors/FieldDoubleInit","title":"FieldDoubleInit","description":"A detector that highlights cases where a field is initialized both in the","sidebar":"sidebar"},"detectors/InheritedStateMutation":{"id":"detectors/InheritedStateMutation","title":"InheritedStateMutation","description":"An optional detector that highlights all instances where inherited trait variables","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"NeverAccessedVariables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/OptimalMathFunction":{"id":"detectors/OptimalMathFunction","title":"OptimalMathFunction","description":"A detector that highlights standard library math function calls that have more gas-efficient alternatives.","sidebar":"sidebar"},"detectors/PreferAugmentedAssign":{"id":"detectors/PreferAugmentedAssign","title":"PreferAugmentedAssign","description":"Detects non-idiomatic statements that can be written using augmented assignment","sidebar":"sidebar"},"detectors/PreferredStdlibApi":{"id":"detectors/PreferredStdlibApi","title":"PreferredStdlibApi","description":"An optional detector that flags the use of advanced functions from the standard library.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"ReadOnlyVariables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/SendInLoop":{"id":"detectors/SendInLoop","title":"SendInLoop","description":"An optional detector that identifies send functions being called inside loops.","sidebar":"sidebar"},"detectors/ShortCircuitCondition":{"id":"detectors/ShortCircuitCondition","title":"ShortCircuitCondition","description":"A detector that suggests optimizing boolean expressions to leverage short-circuit evaluation.","sidebar":"sidebar"},"detectors/StringReceiversOverlap":{"id":"detectors/StringReceiversOverlap","title":"StringReceiversOverlap","description":"A detector that finds overlapping messages between general string receivers and string receivers.","sidebar":"sidebar"},"detectors/SuspiciousMessageMode":{"id":"detectors/SuspiciousMessageMode","title":"SuspiciousMessageMode","description":"Detects suspicious usage of the mode field in SendParameters struct instances.","sidebar":"sidebar"},"detectors/UnboundLoop":{"id":"detectors/UnboundLoop","title":"UnboundLoop","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/UnboundMap":{"id":"detectors/UnboundMap","title":"UnboundMap","description":"An optional detector that highlights cases where a map field allows inserting","sidebar":"sidebar"},"detectors/UnusedExpressionResult":{"id":"detectors/UnusedExpressionResult","title":"UnusedExpressionResult","description":"A detector that identifies expression statements whose result is unused.","sidebar":"sidebar"},"detectors/UnusedOptional":{"id":"detectors/UnusedOptional","title":"UnusedOptional","description":"A detector variables and fields with unused optional modifier.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"ZeroAddress","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/developing-misti":{"id":"hacking/developing-misti","title":"Developing Misti","description":"Prerequisites","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tools":{"id":"tools","title":"Tools Overview","description":"Misti Tools are additional modules designed to work alongside detectors, enabling various tasks beyond code analysis.","sidebar":"sidebar"},"tools/DumpAst":{"id":"tools/DumpAst","title":"DumpAst","description":"The DumpAst tool in Misti enables users to output the Abstract Syntax Tree (AST) of project modules in JSON format. This is particularly useful when writing custom detectors, as it helps understand the structure and components of the code.","sidebar":"sidebar"},"tools/DumpCfg":{"id":"tools/DumpCfg","title":"DumpCfg","description":"Misti provides a feature to dump the Control Flow Graph (CFG) in JSON, DOT, and Mermaid formats. This is essential for understanding the Internal Representation (IR) of the code and analyzing the control flow within contracts.","sidebar":"sidebar"},"tools/DumpConfig":{"id":"tools/DumpConfig","title":"DumpConfig","description":"The DumpConfig tool in Misti allows you to print the current configuration file used by the analyzer. This is useful for obtaining the default configuration to use as a starting point for your custom setup or to inspect and understand the existing configuration in use.","sidebar":"sidebar"},"tools/DumpImports":{"id":"tools/DumpImports","title":"DumpImports","description":"Misti provides a feature to dump the Import Graph of your Tact code in JSON, DOT, and Mermaid formats. This tool helps you understand the dependencies between different files and modules in your project, including how contracts import each other and use the standard library.","sidebar":"sidebar"},"tutorial/blueprint":{"id":"tutorial/blueprint","title":"Using Misti with Blueprint","description":"Blueprint is a platform to compile, test, and deploy contracts on the TON blockchain. It is quite similar to Hardhat and Truffle for Ethereum.","sidebar":"sidebar"},"tutorial/ci-cd":{"id":"tutorial/ci-cd","title":"Integrating Misti into CI/CD","description":"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.","sidebar":"sidebar"},"tutorial/cli":{"id":"tutorial/cli","title":"Command-Line Interface","description":"CLI Options","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/dda96275.6e542222.js b/assets/js/dda96275.6e542222.js new file mode 100644 index 000000000..d054349cf --- /dev/null +++ b/assets/js/dda96275.6e542222.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7193],{6924:(e,i,s)=>{s.r(i),s.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var n=s(4848),t=s(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.5/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/hacking/design.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpImports",permalink:"/tools/misti/docs/tools/DumpImports"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,n.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,n.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,n.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,n.jsxs)(i.p,{children:["Misti leverages the ",(0,n.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,n.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,n.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,n.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,n.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,n.jsxs)(i.ul,{children:["\n",(0,n.jsx)(i.li,{children:(0,n.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,n.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,n.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,n.jsx)(i,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8453:(e,i,s)=>{s.d(i,{R:()=>o,x:()=>l});var n=s(6540);const t={},a=n.createContext(t);function o(e){const i=n.useContext(a);return n.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),n.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/de7c269b.f7040048.js b/assets/js/de7c269b.f7040048.js new file mode 100644 index 000000000..5f7585c42 --- /dev/null +++ b/assets/js/de7c269b.f7040048.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6309],{5275:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>d});var r=s(4848),n=s(8453);const o={},l="CellOverflow",i={id:"detectors/CellOverflow",title:"CellOverflow",description:"A detector that identifies cell overflow problems.",source:"@site/docs/detectors/CellOverflow.md",sourceDirName:"detectors",slug:"/detectors/CellOverflow",permalink:"/tools/misti/docs/next/detectors/CellOverflow",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/CellOverflow.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"BranchDuplicate",permalink:"/tools/misti/docs/next/detectors/BranchDuplicate"},next:{title:"ConstantAddress",permalink:"/tools/misti/docs/next/detectors/ConstantAddress"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2},{value:"Resources",id:"resources",level:2}];function a(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",...(0,n.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"celloverflow",children:"CellOverflow"}),"\n",(0,r.jsx)(t.p,{children:"A detector that identifies cell overflow problems."}),"\n",(0,r.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,r.jsx)(t.p,{children:"Cell overflow is an issue specific to the TON blockchain. TON stores data in\ncells, which are low-level data structures used for serialization and deserialization."}),"\n",(0,r.jsxs)(t.p,{children:["The overflow issue occurs when the user attempts to store more data in a cell\nthan it supports. The current limitation is 1023 bits and 4 references to other\ncells. When these limits are exceeded, the contract throws an error with the\nexit code ",(0,r.jsx)(t.code,{children:"8"})," during the compute phase."]}),"\n",(0,r.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// Bad: storeRef is used more than 4 times\nbeginCell()\n .storeRef(...)\n .storeAddress(myAddress())\n .storeRef(...)\n .storeRef(...)\n .storeRef(...)\n .storeRef(...)\n .endCell()\n"})}),"\n",(0,r.jsx)(t.p,{children:"Use instead:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-tact",children:"// OK: Fixed after the analyzer highlighted it\nbeginCell()\n .storeRef(...)\n .storeAddress(myAddress())\n .storeRef(...)\n .storeRef(...)\n .storeRef(...)\n .endCell()\n"})}),"\n",(0,r.jsx)(t.h2,{id:"resources",children:"Resources"}),"\n",(0,r.jsxs)(t.ol,{children:["\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.ton.org/develop/data-formats/cell-boc",children:"Cell & Bag of Cells (BoC) | TON Docs"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.ton.org/learn/tvm-instructions/tvm-exit-codes",children:"TVM Exit codes | TON Docs"})}),"\n",(0,r.jsx)(t.li,{children:(0,r.jsx)(t.a,{href:"https://docs.tact-lang.org/ref/core-cells/",children:"Cells, Builders and Slices | Tact Docs"})}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,n.R)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>l,x:()=>i});var r=s(6540);const n={},o=r.createContext(n);function l(e){const t=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:l(e.components),r.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/df3f8a78.19c23fa7.js b/assets/js/df3f8a78.19c23fa7.js new file mode 100644 index 000000000..a0e45ed08 --- /dev/null +++ b/assets/js/df3f8a78.19c23fa7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6474],{9633:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var s=i(4848),t=i(8453);const o={},r="Configuration",l={id:"tutorial/configuration",title:"Configuration",description:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.",source:"@site/versioned_docs/version-0.5/tutorial/configuration.md",sourceDirName:"tutorial",slug:"/tutorial/configuration",permalink:"/tools/misti/docs/tutorial/configuration",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tutorial/configuration.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Command-Line Interface",permalink:"/tools/misti/docs/tutorial/cli"},next:{title:"Using with Blueprint",permalink:"/tools/misti/docs/tutorial/blueprint"}},a={},c=[{value:"Configuration Options",id:"configuration-options",level:3},{value:"Running Misti with Configuration",id:"running-misti-with-configuration",level:2},{value:"Default Configuration File",id:"default-configuration-file",level:2},{value:"Environment Variables",id:"environment-variables",level:2},{value:"Getting Help",id:"getting-help",level:2}];function d(e){const n={a:"a",br:"br",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"configuration",children:"Configuration"}),"\n",(0,s.jsx)(n.p,{children:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set."}),"\n",(0,s.jsx)(n.h3,{id:"configuration-options",children:"Configuration Options"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"detectors"})," (array of objects, optional): List of detectors to run. Each detector can be specified with a ",(0,s.jsx)(n.code,{children:"className"})," and optionally a ",(0,s.jsx)(n.code,{children:"modulePath"})," if it\u2019s a custom detector."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"className"})," (string, required): The class name of the detector."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"modulePath"})," (string, optional): The file path of the detector module if it's a custom implementation."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"tools"})," (array of objects, optional): List of tools to enable, each with its own configuration."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"className"})," (string, required): The class name of the tool."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"options"})," (object, optional): Key-value configuration options for the tool."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"suppressions"})," (array of objects, optional): A list of suppressions for warnings."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"detector"})," (string, required): The detector to suppress warnings for."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"position"})," (string, required): The position in the code where the warning should be suppressed."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"ignoredProjects"})," (array of strings, optional): List of Tact projects to ignore during analysis."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"soufflePath"})," (string, optional): Directory to save generated Souffl\xe9 files, useful for debugging purposes. If not set, a temporary directory will be used."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"souffleVerbose"})," (boolean, optional): If set, generates more readable Souffl\xe9 files instead of optimizing the output for size."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"tactStdlibPath"})," (string, optional): Path to the Tact standard library. If not set, the default standard library from the active Tact setup will be used."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"unusedPrefix"}),' (string, default: "_"): Identifiers starting with this prefix won\'t be reported as unused by the built-in detectors.']}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"verbosity"}),' (string, optional, default: "default"): Verbosity level of the logs. Possible values are ',(0,s.jsx)(n.code,{children:"quiet"}),", ",(0,s.jsx)(n.code,{children:"debug"}),", and ",(0,s.jsx)(n.code,{children:"default"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"running-misti-with-configuration",children:"Running Misti with Configuration"}),"\n",(0,s.jsx)(n.p,{children:"To run Misti with the specified configuration file, use the following command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"misti --config path/to/mistiConfig.json test/projects/simple/tactConfig.json\n"})}),"\n",(0,s.jsx)(n.p,{children:"This command tells Misti to use the provided configuration file to analyze the specified Tact project configuration."}),"\n",(0,s.jsx)(n.h2,{id:"default-configuration-file",children:"Default Configuration File"}),"\n",(0,s.jsx)(n.p,{children:"By default, Misti enables all built-in detectors. Below is an example of the default configuration file:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "detectors": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n { "className": "BranchDuplicate" },\n { "className": "FieldDoubleInit" },\n { "className": "PreferAugmentedAssign" },\n { "className": "StringReceiversOverlap" },\n { "className": "ArgCopyMutation" }\n ],\n "ignoredProjects": [],\n "soufflePath": "/tmp/misti/souffle",\n "souffleVerbose": false,\n "unusedPrefix": "_",\n "verbosity": "default"\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["All the built-in detectors are enabled by default. You can find the complete configuration schema and default configuration file on GitHub: ",(0,s.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/configSchema.json",children:"configSchema.json"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["You can always dump the Misti configuration file in use by passing the ",(0,s.jsx)(n.code,{children:"--dump-config"})," option in the CLI:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"misti --dump-config path/to/your/tact.config.json\n"})}),"\n",(0,s.jsx)(n.p,{children:"If there is no Misti config in the directory, Misti dumps the default config. This can be used to adjust it, such as adding or suppressing some detectors."}),"\n",(0,s.jsx)(n.h2,{id:"environment-variables",children:"Environment Variables"}),"\n",(0,s.jsx)(n.p,{children:"Misti offers advanced configuration through environment variables to control specific options."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"MISTI_TIMEOUT"})}),(0,s.jsx)(n.br,{}),"\n","Sets the timeout for detector execution in milliseconds.",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"15000"}),(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Example"}),":","\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"export MISTI_TIMEOUT=20000\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"MISTI_TRACE"})}),(0,s.jsx)(n.br,{}),"\n","Enables tracing of the execution. Set to ",(0,s.jsx)(n.code,{children:"1"})," to enable tracing, otherwise it is disabled.",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"}),(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Example"}),":","\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"export MISTI_TRACE=1\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,s.jsxs)(n.p,{children:["If you need assistance or encounter any issues, please create an issue on GitHub at ",(0,s.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"nowarp/misti"})," or ask in the ",(0,s.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>l});var s=i(6540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e0636556.3ece1612.js b/assets/js/e0636556.3ece1612.js new file mode 100644 index 000000000..053558dd2 --- /dev/null +++ b/assets/js/e0636556.3ece1612.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8047],{3944:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.5/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/index.md",tags:[],version:"0.5",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/tutorial/getting-started"}},c={},l=[{value:"Use Cases",id:"use-cases",level:2},{value:"Name Origin",id:"name-origin",level:2},{value:"Funding",id:"funding",level:2}];function d(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.5 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"name-origin",children:"Name Origin"}),"\n",(0,i.jsx)(t.p,{children:'The name "Misti" comes from the Misti volcano in Peru. It was chosen because it\'s catchy and easy to remember.'}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been funded by the following ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"})," grants:"]}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"TON Static Analyzer \xb7 #436"})}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/777",children:"Upgrade Misti with Advanced Tact Detectors \xb7 #777"})}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"This support has enabled us to develop and maintain the tool."})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e1c88a01.26b5c812.js b/assets/js/e1c88a01.26b5c812.js new file mode 100644 index 000000000..4dacb8281 --- /dev/null +++ b/assets/js/e1c88a01.26b5c812.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[488],{9423:e=>{e.exports=JSON.parse('{"version":{"pluginId":"default","version":"0.2.2","label":"0.2.2","banner":"unmaintained","badge":true,"noIndex":false,"className":"docs-version-0.2.2","isLast":false,"docsSidebars":{"sidebar":[{"type":"link","label":"Introduction","href":"/tools/misti/docs/0.2.2/","docId":"intro","unlisted":false},{"type":"category","label":"Tutorial","items":[{"type":"link","label":"Getting Started","href":"/tools/misti/docs/0.2.2/tutorial/getting-started","docId":"tutorial/getting-started","unlisted":false},{"type":"link","label":"CI/CD Integration","href":"/tools/misti/docs/0.2.2/tutorial/ci-cd","docId":"tutorial/ci-cd","unlisted":false},{"type":"link","label":"Configuration","href":"/tools/misti/docs/0.2.2/tutorial/configuration","docId":"tutorial/configuration","unlisted":false},{"type":"link","label":"Using with Blueprint","href":"/tools/misti/docs/0.2.2/tutorial/blueprint","docId":"tutorial/blueprint","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"link","label":"Detectors Overview","href":"/tools/misti/docs/0.2.2/detectors","docId":"detectors","unlisted":false},{"type":"category","label":"Detectors","items":[{"type":"link","label":"Divide before Multiply","href":"/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply","docId":"detectors/DivideBeforeMultiply","unlisted":false},{"type":"link","label":"Never-accessed Variables","href":"/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables","docId":"detectors/NeverAccessedVariables","unlisted":false},{"type":"link","label":"Read-only Variables","href":"/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables","docId":"detectors/ReadOnlyVariables","unlisted":false},{"type":"link","label":"Unbound Loops","href":"/tools/misti/docs/0.2.2/detectors/UnboundLoops","docId":"detectors/UnboundLoops","unlisted":false},{"type":"link","label":"Zero Address","href":"/tools/misti/docs/0.2.2/detectors/ZeroAddress","docId":"detectors/ZeroAddress","unlisted":false},{"type":"link","label":"Constant Address","href":"/tools/misti/docs/0.2.2/detectors/ConstantAddress","docId":"detectors/ConstantAddress","unlisted":false},{"type":"link","label":"Branch Duplicate","href":"/tools/misti/docs/0.2.2/detectors/BranchDuplicate","docId":"detectors/BranchDuplicate","unlisted":false},{"type":"link","label":"`dump` Is Used","href":"/tools/misti/docs/0.2.2/detectors/DumpIsUsed","docId":"detectors/DumpIsUsed","unlisted":false},{"type":"link","label":"Field Initialized Twice","href":"/tools/misti/docs/0.2.2/detectors/FieldDoubleInit","docId":"detectors/FieldDoubleInit","unlisted":false},{"type":"link","label":"Prefer Augmented Assignment","href":"/tools/misti/docs/0.2.2/detectors/PreferAugmentedAssign","docId":"detectors/PreferAugmentedAssign","unlisted":false}],"collapsed":true,"collapsible":true},{"type":"category","label":"Hacking","items":[{"type":"link","label":"Contributing","href":"/tools/misti/docs/0.2.2/hacking/contributing","docId":"hacking/contributing","unlisted":false},{"type":"link","label":"Design Overview","href":"/tools/misti/docs/0.2.2/hacking/design","docId":"hacking/design","unlisted":false},{"type":"link","label":"Souffl\xe9","href":"/tools/misti/docs/0.2.2/hacking/souffle","docId":"hacking/souffle","unlisted":false},{"type":"link","label":"Tools","href":"/tools/misti/docs/0.2.2/hacking/tools","docId":"hacking/tools","unlisted":false},{"type":"link","label":"Custom Detectors","href":"/tools/misti/docs/0.2.2/hacking/custom-detector","docId":"hacking/custom-detector","unlisted":false}],"collapsed":true,"collapsible":true}]},"docs":{"detectors":{"id":"detectors","title":"Detectors Overview","description":"Here\'s a list of all the detectors:","sidebar":"sidebar"},"detectors/BranchDuplicate":{"id":"detectors/BranchDuplicate","title":"Branch Duplicate","description":"Detector that reports duplicated code in conditional branches.","sidebar":"sidebar"},"detectors/ConstantAddress":{"id":"detectors/ConstantAddress","title":"Constant Address","description":"An optional detector that highlights all the constant addresses appearing in the source code.","sidebar":"sidebar"},"detectors/DivideBeforeMultiply":{"id":"detectors/DivideBeforeMultiply","title":"Divide before Multiply","description":"A detector that identifies and corrects instances of division before multiplication to","sidebar":"sidebar"},"detectors/DumpIsUsed":{"id":"detectors/DumpIsUsed","title":"dump Is Used","description":"An optional detector that highlights all the dump function calls.","sidebar":"sidebar"},"detectors/FieldDoubleInit":{"id":"detectors/FieldDoubleInit","title":"Field Initialized Twice","description":"A detector that highlights cases where a field is initialized both in the init function and at the point of definition.","sidebar":"sidebar"},"detectors/NeverAccessedVariables":{"id":"detectors/NeverAccessedVariables","title":"Never-accessed Variables","description":"A detector that identifies write-only or unused variables, fields and constants.","sidebar":"sidebar"},"detectors/PreferAugmentedAssign":{"id":"detectors/PreferAugmentedAssign","title":"Prefer Augmented Assignment","description":"Detects non-idiomatic statements that can be written using augmented assignment operators like +=, -=, etc.","sidebar":"sidebar"},"detectors/ReadOnlyVariables":{"id":"detectors/ReadOnlyVariables","title":"Read-only Variables","description":"A detector that identifies read-only variables and fields.","sidebar":"sidebar"},"detectors/UnboundLoops":{"id":"detectors/UnboundLoops","title":"Unbound Loops","description":"A detector that analyzes loop conditions and control flow to ensure loops have proper termination criteria.","sidebar":"sidebar"},"detectors/ZeroAddress":{"id":"detectors/ZeroAddress","title":"Zero Address","description":"A detector that identifies uses of the zero address.","sidebar":"sidebar"},"hacking/contributing":{"id":"hacking/contributing","title":"Contributing Guide","description":"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.","sidebar":"sidebar"},"hacking/custom-detector":{"id":"hacking/custom-detector","title":"Custom Detector Guide","description":"Introduction","sidebar":"sidebar"},"hacking/design":{"id":"hacking/design","title":"Design Overview","description":"Static Analysis","sidebar":"sidebar"},"hacking/souffle":{"id":"hacking/souffle","title":"Souffl\xe9 Integration Guide","description":"What is Souffl\xe9?","sidebar":"sidebar"},"hacking/tools":{"id":"hacking/tools","title":"Tools Guide","description":"This page describes the internal analyzer tools available in Misti to aid in development and debugging.","sidebar":"sidebar"},"intro":{"id":"intro","title":"Introduction","description":"Misti is a static analysis tool designed for smart contracts on the TON blockchain.","sidebar":"sidebar"},"tutorial/blueprint":{"id":"tutorial/blueprint","title":"Using Misti with Blueprint","description":"Blueprint is a development environment for writing, testing, and deploying TON smart contracts.","sidebar":"sidebar"},"tutorial/ci-cd":{"id":"tutorial/ci-cd","title":"Integrating Misti into CI/CD","description":"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.","sidebar":"sidebar"},"tutorial/configuration":{"id":"tutorial/configuration","title":"Configuration","description":"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.","sidebar":"sidebar"},"tutorial/getting-started":{"id":"tutorial/getting-started","title":"Getting started","description":"This guide will walk you through the steps to install and set up the Misti static analyzer.","sidebar":"sidebar"}}}}')}}]); \ No newline at end of file diff --git a/assets/js/e2ad9c7a.573d9426.js b/assets/js/e2ad9c7a.573d9426.js new file mode 100644 index 000000000..561e6fc1e --- /dev/null +++ b/assets/js/e2ad9c7a.573d9426.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5945],{4193:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var s=n(4848),t=n(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.3.1/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.3.1/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/hacking/design.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.3.1/hacking/contributing"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.3.1/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const t={},a=s.createContext(t);function o(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e3b47995.f50ac3b9.js b/assets/js/e3b47995.f50ac3b9.js new file mode 100644 index 000000000..ce57749e4 --- /dev/null +++ b/assets/js/e3b47995.f50ac3b9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1171],{7112:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>l});var s=n(4848),i=n(8453);const r={},c="BranchDuplicate",a={id:"detectors/BranchDuplicate",title:"BranchDuplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/docs/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/next/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/BranchDuplicate.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"AsmIsUsed",permalink:"/tools/misti/docs/next/detectors/AsmIsUsed"},next:{title:"CellOverflow",permalink:"/tools/misti/docs/next/detectors/CellOverflow"}},o={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function d(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branchduplicate",children:"BranchDuplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>a});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e3c4fe0a.bf2b73e2.js b/assets/js/e3c4fe0a.bf2b73e2.js new file mode 100644 index 000000000..0914e4dd4 --- /dev/null +++ b/assets/js/e3c4fe0a.bf2b73e2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9428],{503:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var n=i(4848),s=i(8453);const o={},a="FieldDoubleInit",r={id:"detectors/FieldDoubleInit",title:"FieldDoubleInit",description:"A detector that highlights cases where a field is initialized both in the",source:"@site/versioned_docs/version-0.3.0/detectors/FieldDoubleInit.md",sourceDirName:"detectors",slug:"/detectors/FieldDoubleInit",permalink:"/tools/misti/docs/0.3.0/detectors/FieldDoubleInit",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/FieldDoubleInit.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpIsUsed",permalink:"/tools/misti/docs/0.3.0/detectors/DumpIsUsed"},next:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/0.3.0/detectors/InheritedStateMutation"}},d={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"fielddoubleinit",children:"FieldDoubleInit"}),"\n",(0,n.jsxs)(t.p,{children:["A detector that highlights cases where a field is initialized both in the\n",(0,n.jsx)(t.code,{children:"init"})," function and at the point of definition."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["Double initialization of fields can either be a programmer's mistake or simply\na waste of gas. It is always preferred to initialize values in the field declaration\nif they have a compile-time evaluatable default value, or in the ",(0,n.jsx)(t.code,{children:"init"})," function if\nthey must be initialized dynamically."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 0; // Bad\n init(x: Int) { self.a = x }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int; // Fixed\n init(x: Int) { self.a = x }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>r});var n=i(6540);const s={},o=n.createContext(s);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e4a43c7d.190cf370.js b/assets/js/e4a43c7d.190cf370.js new file mode 100644 index 000000000..357b23580 --- /dev/null +++ b/assets/js/e4a43c7d.190cf370.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7348],{3888:(e,s,t)=>{t.r(s),t.d(s,{default:()=>o});t(6540);var i=t(781);const r={heroBanner:"heroBanner_hAhw",heroTitle:"heroTitle_zNcP",heroSubtitle:"heroSubtitle_NX3L",heroSubtitleSmall:"heroSubtitleSmall_wW8f",textContainer:"textContainer_y9OC",buttons:"buttons_YgGx",sectionPadding:"sectionPadding_JTui",featureBox:"featureBox_C4l2",rowWithMargin:"rowWithMargin_rNqB",centerButton:"centerButton_N5e1",featuresTitle:"featuresTitle_elEa"};var c=t(5604),a=t(4848);function o(){return(0,a.jsxs)(i.A,{title:"Welcome to Misti",description:"The TON Static Analyzer",children:[(0,a.jsx)("header",{className:r.heroBanner,children:(0,a.jsxs)("div",{className:r.textContainer,children:[(0,a.jsx)("h1",{className:r.heroTitle,children:"Misti"}),(0,a.jsx)("p",{className:r.heroSubtitle,children:"TON Security Tool"}),(0,a.jsx)("p",{className:r.heroSubtitleSmall,children:"Detect security issues in TON smart contracts before they reach production"}),(0,a.jsx)("div",{className:r.buttons,children:(0,a.jsx)("a",{className:"button button--primary button--lg",href:"/tools/misti/docs/",children:"Get Started"})})]})}),(0,a.jsxs)("main",{children:[(0,a.jsx)("section",{className:`${r.features} ${r.sectionPadding}`,children:(0,a.jsxs)("div",{className:"container",children:[(0,a.jsx)("h2",{className:r.featuresTitle,children:"Misti Overview"}),(0,a.jsx)("p",{className:r.featuresSummary,children:"Misti is a comprehensive security tool designed to identify and prevent vulnerabilities in TON smart contracts. By streamlining the development process and integrating security checks early, Misti ensures your code remains robust and secure."}),(0,a.jsxs)("div",{className:`${r.rowWithMargin} row`,children:[(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\ud83d\udd12 Code Analysis"}),(0,a.jsxs)("p",{children:["Identify and fix potential"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors",children:"security flaws and code problems"})," ","early in the development cycle."]})]})}),(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\u2699\ufe0f CI/CD Integration"}),(0,a.jsxs)("p",{children:[(0,a.jsx)("a",{href:"/tools/misti/docs/tutorial/ci-cd",children:"Integrate"})," Misti into your CI/CD pipeline to ensure continuous code quality checks."]})]})}),(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\ud83d\udee0\ufe0f Custom Detectors"}),(0,a.jsxs)("p",{children:["Create"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/hacking/custom-detector",children:"custom detectors"})," ","to solve specific problems in your code or to provide a thorough security review if you are an auditor."]})]})})]}),(0,a.jsx)("div",{className:`${r.buttons} ${r.centerButton}`,children:(0,a.jsx)("a",{className:"button button--primary button--lg",href:"/tools/misti/docs/",children:"Read Documentation"})})]})}),(0,a.jsx)("section",{className:`${r.features} ${r.sectionPadding} ${r.alternateBackground}`,children:(0,a.jsxs)("div",{className:"container",children:[(0,a.jsx)("h2",{className:r.featuresTitle,children:"Discover Detectors"}),(0,a.jsx)("p",{className:r.featuresSummary,children:"Misti supports 26 specialized detectors designed to identify code issues, detect vulnerabilities, and enforce best practices."}),(0,a.jsxs)("div",{className:`${r.rowWithMargin} row`,children:[(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\ud83c\udf10 TON & Tact Specific"}),(0,a.jsxs)("p",{children:["Detect patterns unique to TON and Tact that could lead to unintended behavior, such as"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/CellOverflow",children:"CellOverflow"})," or"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/StringReceiversOverlap",children:"StringReceiversOverlap"}),"."]})]})}),(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\ud83d\udeab DoS Prevention"}),(0,a.jsxs)("p",{children:["Identify vulnerabilities that could lead to Denial of Service attacks, like"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/SendInLoop",children:"SendInLoop"})," or"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/UnboundMap",children:"UnboundMap"}),"."]})]})}),(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\u2797 Arithmetic Accuracy"}),(0,a.jsxs)("p",{children:["Avoid critical calculation errors with detectors like"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/DivideBeforeMultiply",children:"DivideBeforeMultiply"}),"."]})]})})]}),(0,a.jsxs)("div",{className:`${r.rowWithMargin} row`,children:[(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\ud83d\udd10 Access Control"}),(0,a.jsxs)("p",{children:["Ensure only authorized entities perform actions, preventing unauthorized access with detectors like"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/SuspiciousMessageMode",children:"SuspiciousMessageMode"}),"."]})]})}),(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\u26a1 Code Optimization"}),(0,a.jsxs)("p",{children:["Enhance code efficiency and readability with detectors like"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/OptimalMathFunction",children:"OptimalMathFunction"})," and"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/PreferAugmentedAssign",children:"PreferAugmentedAssign"}),"."]})]})}),(0,a.jsx)("div",{className:"col col--4",children:(0,a.jsxs)("div",{className:r.featureBox,children:[(0,a.jsx)("h3",{children:"\ud83d\udd75\ufe0f Suspicious Patterns"}),(0,a.jsxs)("p",{children:["Uncover subtle issues in your code with detectors such as"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/ZeroAddress",children:"ZeroAddress"})," and"," ",(0,a.jsx)("a",{href:"/tools/misti/docs/detectors/InheritedStateMutation",children:"InheritedStateMutation"}),"."]})]})})]}),(0,a.jsx)("div",{className:`${r.buttons} ${r.centerButton}`,children:(0,a.jsx)("a",{className:"button button--primary button--lg",href:"/tools/misti/docs/detectors",children:"View All Detectors"})})]})}),(0,a.jsx)("section",{className:`${r.features} ${r.sectionPadding}`,children:(0,a.jsxs)("div",{className:"container",children:[(0,a.jsx)("h2",{className:r.featuresTitle,children:"Request an Audit"}),(0,a.jsxs)("p",{className:r.featuresSummary,children:["Certain types of bugs cannot be caught by automated tools as they demand a deep understanding of the underlying system.",(0,a.jsx)("br",{}),"We offer audit services for TON smart contracts, backed by deep security expertise, as our availability allows. If you are interested, reach out to us."]}),(0,a.jsx)("div",{className:`${r.buttons} ${r.centerButton}`,children:(0,a.jsxs)("a",{className:"button button--primary button--lg",href:"https://t.me/jubnzv",children:[(0,a.jsx)(c.zyo,{style:{marginRight:"8px",verticalAlign:"middle"}}),"Contact Us"]})})]})})]})]})}}}]); \ No newline at end of file diff --git a/assets/js/e530f65e.a3814a9a.js b/assets/js/e530f65e.a3814a9a.js new file mode 100644 index 000000000..a75b96a3e --- /dev/null +++ b/assets/js/e530f65e.a3814a9a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[738],{425:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="BranchDuplicate",o={id:"detectors/BranchDuplicate",title:"BranchDuplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.5/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/detectors/BranchDuplicate.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"AsmIsUsed",permalink:"/tools/misti/docs/detectors/AsmIsUsed"},next:{title:"CellOverflow",permalink:"/tools/misti/docs/detectors/CellOverflow"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branchduplicate",children:"BranchDuplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e5aa38d8.17e7d0ef.js b/assets/js/e5aa38d8.17e7d0ef.js new file mode 100644 index 000000000..d420580b0 --- /dev/null +++ b/assets/js/e5aa38d8.17e7d0ef.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4082],{7817:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var n=s(4848),i=s(8453);const o={},d="DumpIsUsed",r={id:"detectors/DumpIsUsed",title:"DumpIsUsed",description:"An optional detector that highlights all the dump function calls.",source:"@site/versioned_docs/version-0.3.0/detectors/DumpIsUsed.md",sourceDirName:"detectors",slug:"/detectors/DumpIsUsed",permalink:"/tools/misti/docs/0.3.0/detectors/DumpIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/DumpIsUsed.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/0.3.0/detectors/DivideBeforeMultiply"},next:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/0.3.0/detectors/FieldDoubleInit"}},c={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function a(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"dumpisused",children:"DumpIsUsed"}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"dump"})," function calls."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"dump"})," function is a debug print that shouldn't be in the final code.\nEven though the compiler removes it in production, its presence suggests the\ndeveloper was debugging something. This can flag areas where issues might exist,\nso auditors should take a closer look at these parts of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = (RANDOM_SEED >> half_shift) &\n (MAGIC_CONSTANT << DIVIDE_BY_TWO) ^ shift_mask;\n dump(combined); // Suspicious: Highlighted by the detector\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = this.seed ^ shift_mask\n // OK: The code was reviewed and simplified; `dump` was removed\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>d,x:()=>r});var n=s(6540);const i={},o=n.createContext(i);function d(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e63578c3.6cc338fe.js b/assets/js/e63578c3.6cc338fe.js new file mode 100644 index 000000000..af9666219 --- /dev/null +++ b/assets/js/e63578c3.6cc338fe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9641],{7717:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>a,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var t=n(4848),s=n(8453);const o={},r="Configuration",l={id:"tutorial/configuration",title:"Configuration",description:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.",source:"@site/versioned_docs/version-0.3.0/tutorial/configuration.md",sourceDirName:"tutorial",slug:"/tutorial/configuration",permalink:"/tools/misti/docs/0.3.0/tutorial/configuration",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/tutorial/configuration.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Command-Line Interface",permalink:"/tools/misti/docs/0.3.0/tutorial/cli"},next:{title:"Using with Blueprint",permalink:"/tools/misti/docs/0.3.0/tutorial/blueprint"}},a={},c=[{value:"Configuration Options",id:"configuration-options",level:3},{value:"Running Misti with Configuration",id:"running-misti-with-configuration",level:2},{value:"Default Configuration File",id:"default-configuration-file",level:2},{value:"Getting Help",id:"getting-help",level:2}];function d(e){const i={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(i.h1,{id:"configuration",children:"Configuration"}),"\n",(0,t.jsx)(i.p,{children:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set."}),"\n",(0,t.jsx)(i.h3,{id:"configuration-options",children:"Configuration Options"}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"detectors"}),": List of detectors to run. Each detector can be specified with a ",(0,t.jsx)(i.code,{children:"className"})," and optionally a ",(0,t.jsx)(i.code,{children:"modulePath"})," if it\u2019s a custom detector."]}),"\n",(0,t.jsxs)(i.ul,{children:["\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"className"})," (string, required): The class name of the detector."]}),"\n",(0,t.jsxs)(i.li,{children:[(0,t.jsx)(i.strong,{children:"modulePath"})," (string, optional): The file path of the detector module."]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"ignoredProjects"})," (array of strings, optional): List of Tact projects to ignore during analysis."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"soufflePath"})," (string, optional): Directory to save generated Souffl\xe9 files which is helpful for debugging purposes. If not set, a temporary directory will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"souffleVerbose"})," (boolean, optional): If set, generates more readable Souffl\xe9 files instead of making the result source code smaller."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"tactStdlibPath"})," (string, optional): Path to Tact standard library. If not set, the default stdlib from the actual Tact setup will be used."]}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"unusedPrefix"}),' (string, default: "_"): Identifiers starting with this prefix won\'t be reported as unused by built-in detectors.']}),"\n"]}),"\n",(0,t.jsxs)(i.li,{children:["\n",(0,t.jsxs)(i.p,{children:[(0,t.jsx)(i.strong,{children:"verbosity"})," (string, optional): Verbosity level of the logs. Possible values are ",(0,t.jsx)(i.code,{children:"quiet"}),", ",(0,t.jsx)(i.code,{children:"debug"}),", and ",(0,t.jsx)(i.code,{children:"default"}),"."]}),"\n"]}),"\n"]}),"\n",(0,t.jsx)(i.h2,{id:"running-misti-with-configuration",children:"Running Misti with Configuration"}),"\n",(0,t.jsx)(i.p,{children:"To run Misti with the specified configuration file, use the following command:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --config path/to/mistiConfig.json test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsx)(i.p,{children:"This command tells Misti to use the provided configuration file to analyze the specified Tact project configuration."}),"\n",(0,t.jsx)(i.h2,{id:"default-configuration-file",children:"Default Configuration File"}),"\n",(0,t.jsx)(i.p,{children:"By default, Misti enables all built-in detectors. Below is an example of the default configuration file:"}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-json",children:'{\n "detectors": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n { "className": "BranchDuplicate" },\n { "className": "FieldDoubleInit" },\n { "className": "PreferAugmentedAssign" },\n { "className": "StringReceiversOverlap" },\n { "className": "ArgCopyMutation" }\n ],\n "ignoredProjects": [],\n "soufflePath": "/tmp/misti/souffle",\n "souffleVerbose": false,\n "unusedPrefix": "_",\n "verbosity": "default"\n}\n'})}),"\n",(0,t.jsxs)(i.p,{children:["All the built-in detectors are enabled by default. You can find the complete configuration schema and default configuration file on GitHub: ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/blob/master/configSchema.json",children:"configSchema.json"}),"."]}),"\n",(0,t.jsxs)(i.p,{children:["You can always dump the Misti configuration file in use by passing the ",(0,t.jsx)(i.code,{children:"--dump-config"})," option in the CLI:"]}),"\n",(0,t.jsx)(i.pre,{children:(0,t.jsx)(i.code,{className:"language-bash",children:"npx misti --dump-config test/projects/simple/tactConfig.json\n"})}),"\n",(0,t.jsxs)(i.p,{children:["If there is no Misti config in the ",(0,t.jsx)(i.code,{children:"simple"})," directory, Misti dumps the default config. This can be used to adjust it, e.g., adding or suppressing some detectors."]}),"\n",(0,t.jsx)(i.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,t.jsxs)(i.p,{children:["If you need assistance or encounter any issues, please create an issue on GitHub at ",(0,t.jsx)(i.a,{href:"https://github.com/nowarp/misti/issues",children:"nowarp/misti"})," or ask in the ",(0,t.jsx)(i.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function u(e={}){const{wrapper:i}={...(0,s.R)(),...e.components};return i?(0,t.jsx)(i,{...e,children:(0,t.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>r,x:()=>l});var t=n(6540);const s={},o=t.createContext(s);function r(e){const i=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e6ef21e7.18abdbcd.js b/assets/js/e6ef21e7.18abdbcd.js new file mode 100644 index 000000000..6e062f5b7 --- /dev/null +++ b/assets/js/e6ef21e7.18abdbcd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4984],{1053:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>p,frontMatter:()=>s,metadata:()=>d,toc:()=>a});var i=n(4848),o=n(8453);const s={},r="DuplicatedCondition",d={id:"detectors/DuplicatedCondition",title:"DuplicatedCondition",description:"A detector that finds duplicated conditions appearing in conditional expressions.",source:"@site/versioned_docs/version-0.4.0/detectors/DuplicatedCondition.md",sourceDirName:"detectors",slug:"/detectors/DuplicatedCondition",permalink:"/tools/misti/docs/0.4.0/detectors/DuplicatedCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/DuplicatedCondition.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpIsUsed",permalink:"/tools/misti/docs/0.4.0/detectors/DumpIsUsed"},next:{title:"EnsurePrgSeed",permalink:"/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"duplicatedcondition",children:"DuplicatedCondition"}),"\n",(0,i.jsx)(t.p,{children:"A detector that finds duplicated conditions appearing in conditional expressions."}),"\n",(0,i.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,i.jsx)(t.p,{children:"Typically, these cases are developer errors caused by copy-pasting code, leading\nto unreachable code."}),"\n",(0,i.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"fun test(a: Int): Int {\n if (a < 1) { return 1; }\n else if (a > 4) { return 2; }\n // Bad: A developer copy-pasted the condition\n else if (a > 4) { return 3; }\n return 4;\n}\n"})}),"\n",(0,i.jsx)(t.p,{children:"Use instead:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-tact",children:"fun test(a: Int): Int {\n if (a < 1) { return 1; }\n else if (a > 4) { return 2; }\n // OK: Fixed\n else if (a < x) { return 3; }\n return 4;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>d});var i=n(6540);const o={},s=i.createContext(o);function r(e){const t=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),i.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/e9524270.4f13728a.js b/assets/js/e9524270.4f13728a.js new file mode 100644 index 000000000..3ab8f0c17 --- /dev/null +++ b/assets/js/e9524270.4f13728a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2167],{7019:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={},r="Integrating Misti into CI/CD",a={id:"tutorial/ci-cd",title:"Integrating Misti into CI/CD",description:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.",source:"@site/docs/tutorial/ci-cd.md",sourceDirName:"tutorial",slug:"/tutorial/ci-cd",permalink:"/tools/misti/docs/next/tutorial/ci-cd",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/tutorial/ci-cd.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Getting Started",permalink:"/tools/misti/docs/next/tutorial/getting-started"},next:{title:"Command-Line Interface",permalink:"/tools/misti/docs/next/tutorial/cli"}},c={},l=[{value:"Using Tact Template",id:"using-tact-template",level:2},{value:"GitHub Actions",id:"github-actions",level:2},{value:"Integration with Blueprint Projects",id:"integration-with-blueprint-projects",level:2}];function u(t){const e={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"integrating-misti-into-cicd",children:"Integrating Misti into CI/CD"}),"\n",(0,i.jsx)(e.p,{children:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle."}),"\n",(0,i.jsx)(e.h2,{id:"using-tact-template",children:"Using Tact Template"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.a,{href:"https://github.com/tact-lang/tact-template",children:(0,i.jsx)(e.code,{children:"tact-template"})})," is a template project for Tact. If you started your project from this template, Misti is already installed in ",(0,i.jsx)(e.a,{href:"https://github.com/tact-lang/tact-template/tree/main/.github/workflows",children:"the CI"}),". You also have the ",(0,i.jsx)(e.code,{children:"yarn lint"})," command available in your ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsx)(e.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(e.p,{children:"To integrate Misti into your GitHub Actions workflow, you need to add a command that runs Misti as part of your CI process. Here's how you can do it:"}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"1. Open your GitHub repository"})}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"2. Create or edit the GitHub Actions workflow YAML file"})}),"\n",(0,i.jsxs)(e.p,{children:["It could be located at e.g., ",(0,i.jsx)(e.code,{children:".github/workflows/ci.yml"}),"."]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"3. Add the step to run Misti to your YAML file"})}),"\n",(0,i.jsx)(e.p,{children:"For example:"}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-yaml",children:'name: CI\n\non:\n push:\n branches: [ "main" ]\n pull_request:\n branches: [ "main" ]\n workflow_dispatch:\n\njobs:\n test:\n strategy:\n fail-fast: false\n matrix:\n node-version: [22]\n os: [ubuntu-latest]\n runs-on: ${{ matrix.os }}\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n\n - name: Install Souffl\xe9 on Ubuntu\n if: matrix.os == \'ubuntu-latest\'\n run: |\n sudo wget https://souffle-lang.github.io/ppa/souffle-key.public -O /usr/share/keyrings/souffle-archive-keyring.gpg\n echo "deb [signed-by=/usr/share/keyrings/souffle-archive-keyring.gpg] https://souffle-lang.github.io/ppa/ubuntu/ stable main" | sudo tee /etc/apt/sources.list.d/souffle.list\n sudo apt update\n sudo apt install souffle\n\n - name: Setup Node.js\n uses: actions/setup-node@v3\n with:\n node-version: ${{ matrix.node-version }}\n\n - name: Install dependencies\n run: yarn install\n\n - name: Run Misti\n run: yarn misti --min-severity medium /path/to/your/tact.config.json\n'})}),"\n",(0,i.jsxs)(e.p,{children:["The ",(0,i.jsx)(e.code,{children:"yarn misti --min-severity medium /path/to/your/tact.config.json"})," command will run Misti against your project. If Misti detects any issues that are not suppressed by your configuration, it will return a non-zero exit code, causing the CI pipeline to fail."]}),"\n",(0,i.jsxs)(e.p,{children:["The ",(0,i.jsx)(e.code,{children:"--min-severity medium"})," will filter out low-priority warnings. You can always run Misti with all the detectors enabled locally in order to get the most comprehensive warnings output: ",(0,i.jsx)(e.code,{children:"yarn misti --all-detectors /path/to/your/tact.config.json"})]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"4. Adjusting the Misti Configuration"})}),"\n",(0,i.jsxs)(e.p,{children:["If you find that Misti is too noisy (e.g., detecting issues that are not relevant to your project), you can adjust your Misti configuration file to suppress those warnings. Refer to the ",(0,i.jsx)(e.a,{href:"./configuration",children:"Configuration"})," section for more details on how to customize your settings."]}),"\n",(0,i.jsx)(e.h2,{id:"integration-with-blueprint-projects",children:"Integration with Blueprint Projects"}),"\n",(0,i.jsx)(e.p,{children:"To add Misti to the CI for your Blueprint project, follow these steps:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.a,{href:"/tools/misti/docs/next/tutorial/blueprint",children:["Install ",(0,i.jsx)(e.code,{children:"blueprint-misti"})]}),"."]}),"\n",(0,i.jsxs)(e.li,{children:["Follow the steps to set up the GitHub action above, but replace the ",(0,i.jsx)(e.code,{children:"yarn misti"})," command with ",(0,i.jsx)(e.code,{children:"npx blueprint misti --blueprint-project"}),", where ",(0,i.jsx)(e.code,{children:" "})," is the name of the project displayed when you run ",(0,i.jsx)(e.code,{children:"npx blueprint build"}),"."]}),"\n"]})]})}function d(t={}){const{wrapper:e}={...(0,s.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(u,{...t})}):u(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(t){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(s):t.components||s:r(t.components),i.createElement(o.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/ea064c97.a5aaaeb2.js b/assets/js/ea064c97.a5aaaeb2.js new file mode 100644 index 000000000..a05e7fa0e --- /dev/null +++ b/assets/js/ea064c97.a5aaaeb2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5508],{3195:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>d,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});var n=s(4848),i=s(8453);const o={},r="AsmIsUsed",a={id:"detectors/AsmIsUsed",title:"AsmIsUsed",description:"An optional detector that highlights all the asm functions.",source:"@site/versioned_docs/version-0.4.0/detectors/AsmIsUsed.md",sourceDirName:"detectors",slug:"/detectors/AsmIsUsed",permalink:"/tools/misti/docs/0.4.0/detectors/AsmIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/AsmIsUsed.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"ArgCopyMutation",permalink:"/tools/misti/docs/0.4.0/detectors/ArgCopyMutation"},next:{title:"BranchDuplicate",permalink:"/tools/misti/docs/0.4.0/detectors/BranchDuplicate"}},d={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"asmisused",children:"AsmIsUsed"}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"asm"})," functions."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(t.p,{children:"Using TVM Assembly is a potentially dangerous operation that requires additional\nattention from an auditor. This optional detector will highlight all its uses to\nassist in contract security audits."}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"// Highlighted: the asm function use should be audited\nasm fun getStorageFee(cells: Int, bits: Int, seconds: Int, is_masterchain: Bool): Int { GETSTORAGEFEE }\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>r,x:()=>a});var n=s(6540);const i={},o=n.createContext(i);function r(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ea8d0df0.3be72894.js b/assets/js/ea8d0df0.3be72894.js new file mode 100644 index 000000000..a5aaf2468 --- /dev/null +++ b/assets/js/ea8d0df0.3be72894.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[335],{4905:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>a,contentTitle:()=>c,default:()=>l,frontMatter:()=>r,metadata:()=>s,toc:()=>d});var i=n(4848),o=n(8453);const r={},c="Custom Detector Guide",s={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/docs/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/next/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/hacking/custom-detector.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Developing Misti",permalink:"/tools/misti/docs/next/hacking/developing-misti"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Creating a Detector",id:"creating-a-detector",level:2},{value:"Testing the detector",id:"testing-the-detector",level:3},{value:"Saving the configuration",id:"saving-the-configuration",level:3},{value:"Example Detectors",id:"example-detectors",level:2}];function h(t){const e={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,i.jsx)(e.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(e.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,i.jsx)(e.a,{href:"https://nowarp.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,i.jsx)(e.a,{href:"https://nowarp.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,i.jsx)(e.code,{children:"Detector"})})," interface."]}),"\n",(0,i.jsx)(e.h2,{id:"creating-a-detector",children:"Creating a Detector"}),"\n",(0,i.jsxs)(e.p,{children:["You can create a new custom detector by executing Misti with the ",(0,i.jsx)(e.code,{children:"--new-detector"})," option: ",(0,i.jsx)(e.code,{children:"misti --new-detector implicitInit"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["This will create the ",(0,i.jsx)(e.code,{children:"implicitInit.ts"})," file, which contains the template code for writing your own custom detector logic leveraging the Misti API."]}),"\n",(0,i.jsx)(e.p,{children:"Here's an example of how to implement a custom detector using Misti API:"}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-typescript",children:'import { ASTDetector } from "@nowarp/misti/dist/detectors/detector";\nimport { CompilationUnit } from "@nowarp/misti/dist/internals/ir";\nimport {\n MistiTactWarning,\n Severity,\n} from "@nowarp/misti/dist/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that doesn\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends ASTDetector {\n severity = Severity.INFO;\n\n async check(cu: CompilationUnit): Promise {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = this.makeWarning(\n `Contract ${contract.name} doesn\'t define an init function`,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactWarning[]);\n }\n}\n\n'})}),"\n",(0,i.jsx)(e.h3,{id:"testing-the-detector",children:"Testing the detector"}),"\n",(0,i.jsxs)(e.p,{children:["To run Misti with only your new detector, use the ",(0,i.jsx)(e.code,{children:"--detectors"})," option, specifying the path to the detector and the Detector class name: ",(0,i.jsx)(e.code,{children:"misti path/to/your/tact.config.json --detectors path/to/implicitInit.ts:ImplicitInit"}),"."]}),"\n",(0,i.jsxs)(e.p,{children:["That's a good way to test the detector on the first run. You could also use the ",(0,i.jsx)(e.code,{children:"--verbose"})," CLI option and set the environment variable ",(0,i.jsx)(e.code,{children:"MISTI_TRACE=1"})," to facilitate debugging."]}),"\n",(0,i.jsx)(e.h3,{id:"saving-the-configuration",children:"Saving the configuration"}),"\n",(0,i.jsx)(e.p,{children:"After testing the detector, you can specify it in your configuration to enable it in future runs. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{children:'{\n "detectors": [\n // Other detectors...\n { "className": "ImplicitInit", "modulePath": "ImplicitInit.ts" }\n ],\n}\n'})}),"\n",(0,i.jsxs)(e.p,{children:["After this, you could run Misti specifying a path to a custom configuration ",(0,i.jsx)(e.code,{children:"misti --config path/to/misti.config.json path/to/your/tact.config.json"}),"."]}),"\n",(0,i.jsx)(e.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,i.jsxs)(e.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,i.jsx)(e.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function l(t={}){const{wrapper:e}={...(0,o.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(h,{...t})}):h(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>c,x:()=>s});var i=n(6540);const o={},r=i.createContext(o);function c(t){const e=i.useContext(r);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function s(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(o):t.components||o:c(t.components),i.createElement(r.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/eb1a8185.161f6a09.js b/assets/js/eb1a8185.161f6a09.js new file mode 100644 index 000000000..4bd89ae50 --- /dev/null +++ b/assets/js/eb1a8185.161f6a09.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5656],{3872:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var s=n(4848),i=n(8453);const r={},o="Developing Misti",a={id:"hacking/developing-misti",title:"Developing Misti",description:"Prerequisites",source:"@site/versioned_docs/version-0.5/hacking/developing-misti.md",sourceDirName:"hacking",slug:"/hacking/developing-misti",permalink:"/tools/misti/docs/hacking/developing-misti",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/hacking/developing-misti.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/hacking/contributing"},next:{title:"Writing Custom Detectors",permalink:"/tools/misti/docs/hacking/custom-detector"}},c={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Cloning the Repository",id:"cloning-the-repository",level:2},{value:"Building the Project",id:"building-the-project",level:2},{value:"Running the Analyzer",id:"running-the-analyzer",level:2},{value:"Adding Backtraces to the Logger",id:"adding-backtraces-to-the-logger",level:2},{value:"Updating Expected Outputs of Tests",id:"updating-expected-outputs-of-tests",level:2}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"developing-misti",children:"Developing Misti"}),"\n",(0,s.jsx)(t.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsxs)(t.p,{children:["Before you begin, please refer to the ",(0,s.jsx)(t.a,{href:"https://nowarp.io/tools/misti/docs/next/tutorial/getting-started",children:"Getting Started documentation"})," for the required system dependencies."]}),"\n",(0,s.jsx)(t.h2,{id:"cloning-the-repository",children:"Cloning the Repository"}),"\n",(0,s.jsx)(t.p,{children:"Clone the Misti repository:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"git clone 'https://github.com/nowarp/misti'\n"})}),"\n",(0,s.jsx)(t.h2,{id:"building-the-project",children:"Building the Project"}),"\n",(0,s.jsx)(t.p,{children:"Navigate to the project directory, install dependencies, generate necessary files, and build the project:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"cd misti && yarn install && yarn gen && yarn build\n"})}),"\n",(0,s.jsx)(t.h2,{id:"running-the-analyzer",children:"Running the Analyzer"}),"\n",(0,s.jsx)(t.p,{children:"During development, you can run the analyzer using:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"yarn misti\n"})}),"\n",(0,s.jsx)(t.p,{children:"For example, to run it for tests:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"yarn misti test/detectors/NeverAccessedVariables.tact\n"})}),"\n",(0,s.jsx)(t.h2,{id:"adding-backtraces-to-the-logger",children:"Adding Backtraces to the Logger"}),"\n",(0,s.jsxs)(t.p,{children:["To add debug traces to all log messages, set the ",(0,s.jsx)(t.code,{children:"MISTI_TRACE"})," environment variable to ",(0,s.jsx)(t.code,{children:"1"}),":"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"MISTI_TRACE=1 yarn misti test/detectors/NeverAccessedVariables.tact\n"})}),"\n",(0,s.jsx)(t.h2,{id:"updating-expected-outputs-of-tests",children:"Updating Expected Outputs of Tests"}),"\n",(0,s.jsxs)(t.p,{children:["To update the expected outputs of tests, set the ",(0,s.jsx)(t.code,{children:"BLESS"})," environment variable and run the tests:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test\n"})}),"\n",(0,s.jsx)(t.p,{children:"You can also run a single test or update its expected output when working with a specific test file:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test test/tactIR.spec.ts tests/detectors/NeverAccessedVariables.tact\n"})}),"\n",(0,s.jsx)(t.p,{children:"And for another specific test:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-bash",children:"BLESS=1 yarn test test/builtinDetectors.spec.ts test/detectors/BranchDuplicate.tact\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const i={},r=s.createContext(i);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ebcc9167.b433e15d.js b/assets/js/ebcc9167.b433e15d.js new file mode 100644 index 000000000..d96ecde6a --- /dev/null +++ b/assets/js/ebcc9167.b433e15d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6387],{4416:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>a,metadata:()=>o,toc:()=>d});var s=n(4848),r=n(8453);const a={},i="NeverAccessedVariables",o={id:"detectors/NeverAccessedVariables",title:"NeverAccessedVariables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.3.0/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/NeverAccessedVariables.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"InheritedStateMutation",permalink:"/tools/misti/docs/0.3.0/detectors/InheritedStateMutation"},next:{title:"PreferAugmentedAssign",permalink:"/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"neveraccessedvariables",children:"NeverAccessedVariables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the analyzer highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const r={},a=s.createContext(r);function i(e){const t=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),s.createElement(a.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ed017323.30666872.js b/assets/js/ed017323.30666872.js new file mode 100644 index 000000000..87d17af7f --- /dev/null +++ b/assets/js/ed017323.30666872.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4138],{8065:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>c,toc:()=>l});var t=i(4848),s=i(8453);const o={},r="Contributing Guide",c={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/docs/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/next/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/hacking/contributing.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/next/hacking/souffle"},next:{title:"Developing Misti",permalink:"/tools/misti/docs/next/hacking/developing-misti"}},a={},l=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function u(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["See ",(0,t.jsx)(n.a,{href:"/tools/misti/docs/next/hacking/developing-misti",children:"Developing Misti"})," for information about initializing the environment and additional hacking tips."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function d(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(u,{...e})}):u(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>c});var t=i(6540);const s={},o=t.createContext(s);function r(e){const n=t.useContext(o);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),t.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ed2e6971.2d114ae2.js b/assets/js/ed2e6971.2d114ae2.js new file mode 100644 index 000000000..3a104acac --- /dev/null +++ b/assets/js/ed2e6971.2d114ae2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8300],{8315:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>a,default:()=>u,frontMatter:()=>o,metadata:()=>r,toc:()=>l});var s=n(4848),i=n(8453);const o={},a="UnusedOptional",r={id:"detectors/UnusedOptional",title:"UnusedOptional",description:"A detector variables and fields with unused optional modifier.",source:"@site/docs/detectors/UnusedOptional.md",sourceDirName:"detectors",slug:"/detectors/UnusedOptional",permalink:"/tools/misti/docs/next/detectors/UnusedOptional",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/UnusedOptional.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"UnusedExpressionResult",permalink:"/tools/misti/docs/next/detectors/UnusedExpressionResult"},next:{title:"ZeroAddress",permalink:"/tools/misti/docs/next/detectors/ZeroAddress"}},d={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"unusedoptional",children:"UnusedOptional"}),"\n",(0,s.jsx)(t.p,{children:"A detector variables and fields with unused optional modifier."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.code,{children:"Optional"})," is a nullable value that has a special ",(0,s.jsx)(t.code,{children:"null"})," value indicating the absence\nof a value. If a developer creates an optional variable or field, he should leverage\nits functionality by accessing the ",(0,s.jsx)(t.code,{children:"null"})," value somewhere in his code. Otherwise,\nthe optional type should be removed to simplify and optimize the code."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int?; // Bad: null value is never accessed\n init() { self.a = 42; }\n get fun getA(): Int { return self.a!!; }\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 42; // OK: Removed optional\n get fun getA(): Int { return self.a; }\n}\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>a,x:()=>r});var s=n(6540);const i={},o=s.createContext(i);function a(e){const t=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/edf1e52e.7e8e467f.js b/assets/js/edf1e52e.7e8e467f.js new file mode 100644 index 000000000..76349e9da --- /dev/null +++ b/assets/js/edf1e52e.7e8e467f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3434],{3744:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),a=n(8453);const r={},i="Never-accessed Variables",o={id:"detectors/NeverAccessedVariables",title:"Never-accessed Variables",description:"A detector that identifies write-only or unused variables, fields and constants.",source:"@site/versioned_docs/version-0.1.2/detectors/NeverAccessedVariables.md",sourceDirName:"detectors",slug:"/detectors/NeverAccessedVariables",permalink:"/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/detectors/NeverAccessedVariables.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Divide before Multiply",permalink:"/tools/misti/docs/0.1.2/detectors/DivideBeforeMultiply"},next:{title:"Read-only Variables",permalink:"/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,a.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"never-accessed-variables",children:"Never-accessed Variables"}),"\n",(0,s.jsx)(t.p,{children:"A detector that identifies write-only or unused variables, fields and constants."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"These variables are either assigned but never used in any meaningful computation,\nor they are declared and never used at all, which may indicate redundant code\nor an incomplete implementation of the intended logic."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"// Error: the developer forgot to use the constant\nconst MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'const MAX_SUPPLY: Int = 1000;\n\nfun mint(to: Address, amount: Int) {\n // OK: Fixed after the linter highlighted this warning\n require(totalSupply + amount <= MAX_SUPPLY, "Exceeds max supply");\n balances.set(to, balances.get(to)!! + amount);\n totalSupply += amount;\n}\n'})})]})}function u(e={}){const{wrapper:t}={...(0,a.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var s=n(6540);const a={},r=s.createContext(a);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ef43b7e4.3a22e7e4.js b/assets/js/ef43b7e4.3a22e7e4.js new file mode 100644 index 000000000..d5bc6b7b6 --- /dev/null +++ b/assets/js/ef43b7e4.3a22e7e4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9623],{3467:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var i=s(4848),t=s(8453);const l={},r="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/versioned_docs/version-0.5/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.5/tutorial/getting-started.md",tags:[],version:"0.5",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/tutorial/ci-cd"}},a={},c=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"More usage examples",id:"more-usage-examples",level:2},{value:"Suppressing Warnings",id:"suppressing-warnings",level:3},{value:"Enabling All Detectors",id:"enabling-all-detectors",level:3},{value:"Running in Quiet Mode",id:"running-in-quiet-mode",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,t.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,i.jsx)(n.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,i.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsx)(n.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Git"}),"\n",(0,i.jsx)(n.li,{children:"Yarn"}),"\n",(0,i.jsx)(n.li,{children:"Node.js version 22 or higher"}),"\n",(0,i.jsx)(n.li,{children:(0,i.jsx)(n.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"npm install -g @nowarp/misti\n"})}),"\n",(0,i.jsx)(n.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,i.jsx)(n.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,i.jsx)(n.p,{children:"To install the latest development version you should:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Clone Misti: ",(0,i.jsx)(n.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,i.jsxs)(n.li,{children:["Build it: ",(0,i.jsx)(n.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,i.jsxs)(n.li,{children:["Use it in your Tact project: ",(0,i.jsx)(n.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,i.jsx)(n.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"misti path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,i.jsxs)(n.p,{children:["You can also add a script to your ",(0,i.jsx)(n.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "misti path/to/tact.config.json"\n }\n}\n'})}),"\n",(0,i.jsx)(n.h2,{id:"more-usage-examples",children:"More usage examples"}),"\n",(0,i.jsxs)(n.p,{children:["Below are a few usage examples for common scenarios when using ",(0,i.jsxs)(n.a,{href:"/tools/misti/docs/tutorial/cli",children:["the ",(0,i.jsx)(n.code,{children:"misti"})," CLI"]}),"."]}),"\n",(0,i.jsx)(n.h3,{id:"suppressing-warnings",children:"Suppressing Warnings"}),"\n",(0,i.jsxs)(n.p,{children:["If you want to suppress some warnings in specific places of source code, you should use the ",(0,i.jsx)(n.code,{children:"@misti:suppress"})," annotations in the comment on the previous line, for example:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"fun test(): Int {\n // @misti:suppress NeverAccessedVariables\n let sum: Int = 0; // OK: The warning will be suppressed\n return 52;\n}\n"})}),"\n",(0,i.jsx)(n.p,{children:"This syntax also enables you to list a few detectors to be suppressed, including the custom ones, for example:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"// @misti:suppress NeverAccessedVariables,MyCustomDetector,ReadOnlyVariables\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Alternatively, you could run ",(0,i.jsx)(n.code,{children:"misti"})," while entirely suppressing specific detectors:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"misti --suppress ReadOnlyVariables path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.h3,{id:"enabling-all-detectors",children:"Enabling All Detectors"}),"\n",(0,i.jsxs)(n.p,{children:["Running ",(0,i.jsx)(n.code,{children:"misti"})," with all available built-in detectors enabled:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"misti --all-detectors path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"It is recommended to do that when auditing the project."}),"\n",(0,i.jsx)(n.h3,{id:"running-in-quiet-mode",children:"Running in Quiet Mode"}),"\n",(0,i.jsxs)(n.p,{children:["To suppress all output while running ",(0,i.jsx)(n.code,{children:"misti"})," getting just a return code:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"misti --quiet path/to/tact.config.json\n"})}),"\n",(0,i.jsx)(n.p,{children:"This might be useful in scripts and CI/CD."}),"\n",(0,i.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsxs)(n.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,i.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,i.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>r,x:()=>o});var i=s(6540);const t={},l=i.createContext(t);function r(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/effcc73a.c554b68a.js b/assets/js/effcc73a.c554b68a.js new file mode 100644 index 000000000..4ecc0093f --- /dev/null +++ b/assets/js/effcc73a.c554b68a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[485],{968:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.4.0/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.4.0/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/hacking/souffle.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.4.0/hacking/design"},next:{title:"Custom Detectors",permalink:"/tools/misti/docs/0.4.0/hacking/custom-detector"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is implemented in the ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/souffle.js",children:"Souffle.js library"}),". See the ",(0,t.jsx)(n.a,{href:"https://nowarp.io/lib/souffle-js/api/",children:"Souffle.js API reference"})," for more detailed information."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f18c7db7.502a736a.js b/assets/js/f18c7db7.502a736a.js new file mode 100644 index 000000000..31515d8ef --- /dev/null +++ b/assets/js/f18c7db7.502a736a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9959],{4172:(e,t,r)=>{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>n,metadata:()=>c,toc:()=>l});var s=r(4848),i=r(8453);const n={id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},o="Detectors Overview",c={id:"detectors",title:"Detectors Overview",description:"Here's a list of all the detectors:",source:"@site/versioned_docs/version-0.2.0/detectors.md",sourceDirName:".",slug:"/detectors",permalink:"/tools/misti/docs/0.2.0/detectors",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/detectors.md",tags:[],version:"0.2.0",frontMatter:{id:"detectors",title:"Detectors Overview",sidebar_label:"Detectors Overview"},sidebar:"sidebar",previous:{title:"Configuration",permalink:"/tools/misti/docs/0.2.0/tutorial/configuration"},next:{title:"Divide before Multiply",permalink:"/tools/misti/docs/0.2.0/detectors/DivideBeforeMultiply"}},d={},l=[];function a(e){const t={a:"a",code:"code",h1:"h1",li:"li",p:"p",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"detectors-overview",children:"Detectors Overview"}),"\n",(0,s.jsx)(t.p,{children:"Here's a list of all the detectors:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/DivideBeforeMultiply",children:"Divide before Multiply"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/NeverAccessedVariables",children:"Never-accessed Variables"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/ReadOnlyVariables",children:"Read-only Variables"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/UnboundLoops",children:"Unbound Loops"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/ZeroAddress",children:"Zero Address"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/ConstantAddress",children:"Constant Address"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/BranchDuplicate",children:"Branch Duplicate"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsxs)(t.a,{href:"./detectors/DumpIsUsed",children:[(0,s.jsx)(t.code,{children:"dump"})," Is Used"]})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/FieldDoubleInit",children:"Field Initialized Twice"})}),"\n",(0,s.jsx)(t.li,{children:(0,s.jsx)(t.a,{href:"./detectors/PreferAugmentedAssign",children:"Prefer Augmented Assignment"})}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"Each detector is designed to catch specific issues in your code. Click on any of them to learn more."})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,t,r)=>{r.d(t,{R:()=>o,x:()=>c});var s=r(6540);const i={},n=s.createContext(i);function o(e){const t=s.useContext(n);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f2bdb0f5.256a666a.js b/assets/js/f2bdb0f5.256a666a.js new file mode 100644 index 000000000..43a72c0ff --- /dev/null +++ b/assets/js/f2bdb0f5.256a666a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8836],{1582:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>s,metadata:()=>o,toc:()=>f});var t=i(4848),r=i(8453);const s={},a="Souffl\xe9 Integration Guide",o={id:"hacking/souffle",title:"Souffl\xe9 Integration Guide",description:"What is Souffl\xe9?",source:"@site/versioned_docs/version-0.2.1/hacking/souffle.md",sourceDirName:"hacking",slug:"/hacking/souffle",permalink:"/tools/misti/docs/0.2.1/hacking/souffle",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/hacking/souffle.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Design Overview",permalink:"/tools/misti/docs/0.2.1/hacking/design"},next:{title:"Tools",permalink:"/tools/misti/docs/0.2.1/hacking/tools"}},l={},f=[{value:"What is Souffl\xe9?",id:"what-is-souffl\xe9",level:2},{value:"Benefits of Using Souffl\xe9 for Static Analysis",id:"benefits-of-using-souffl\xe9-for-static-analysis",level:2},{value:"Souffl\xe9 Integration in Misti",id:"souffl\xe9-integration-in-misti",level:2},{value:"Creating Souffl\xe9 Programs",id:"creating-souffl\xe9-programs",level:3},{value:"Generating Facts and Executing Souffl\xe9",id:"generating-facts-and-executing-souffl\xe9",level:3},{value:"Learning from Existing Code",id:"learning-from-existing-code",level:3},{value:"Further Reading",id:"further-reading",level:2}];function c(e){const n={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"souffl\xe9-integration-guide",children:"Souffl\xe9 Integration Guide"}),"\n",(0,t.jsx)(n.h2,{id:"what-is-souffl\xe9",children:"What is Souffl\xe9?"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.a,{href:"https://souffle-lang.github.io",children:"Souffl\xe9"})," is a highly efficient Datalog solver designed specifically for program analysis. It offers native parallel execution, making it incredibly fast and suitable for handling complex static analysis tasks. By leveraging Souffl\xe9, Misti can perform deep and scalable analyses of smart contracts."]}),"\n",(0,t.jsx)(n.h2,{id:"benefits-of-using-souffl\xe9-for-static-analysis",children:"Benefits of Using Souffl\xe9 for Static Analysis"}),"\n",(0,t.jsx)(n.p,{children:"Souffl\xe9 allows to express static analysis problems declaratively, making it easier to define and solve complex queries over the code's intermediate representation (IR). In some cases writing a Souffl\xe9 program might be more straightforward then implementing a complex transfer function in for a classic monotone framework."}),"\n",(0,t.jsx)(n.h2,{id:"souffl\xe9-integration-in-misti",children:"Souffl\xe9 Integration in Misti"}),"\n",(0,t.jsxs)(n.p,{children:["The API for interacting with Souffl\xe9 in Misti is detailed ",(0,t.jsx)(n.a,{href:"https://nowarp.github.io/docs/misti/api/modules/internals_souffle.html",children:"here"}),"."]}),"\n",(0,t.jsx)(n.h3,{id:"creating-souffl\xe9-programs",children:"Creating Souffl\xe9 Programs"}),"\n",(0,t.jsx)(n.p,{children:'To create a Souffl\xe9 program within Misti, you need to declare relations, rules and generate facts based on the IR. Here is an example from the built-in "readonly variables" detector:'}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addDecls(ctx: Context ) {\n ctx.add(\n Relation.from(\n "varDecl",\n [\n ["var", FactType.Symbol],\n ["func", FactType.Symbol],\n ],\n undefined,\n ),\n );\n // other declarations\n}\n'})}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'addRules(ctx: Context ) {\n // readOnly(var, func) :-\n // varDecl(var, func),\n // !varAssign(var, func),\n // !varUse(var, func).\n ctx.add(\n Rule.from(\n [makeAtom("readOnly", ["var", "func"])],\n makeRuleBody(makeAtom("varDecl", ["var", "func"])),\n makeRuleBody(makeAtom("varAssign", ["var", "func"]), {\n negated: true,\n }),\n makeRuleBody(makeAtom("varUse", ["var", "func"]), { negated: true }),\n ),\n );\n }\n'})}),"\n",(0,t.jsx)(n.h3,{id:"generating-facts-and-executing-souffl\xe9",children:"Generating Facts and Executing Souffl\xe9"}),"\n",(0,t.jsx)(n.p,{children:"After declaring the necessary relations, you need to iterate over the IR to generate facts for these declarations. Then, use the built-in Souffl\xe9 executor to run the analysis:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:"const executor = ctx.config.soufflePath\n ? new Executor ({\n inputDir: ctx.config.soufflePath,\n outputDir: ctx.config.soufflePath,\n })\n : new Executor ();\n\nconst result = executor.executeSync(program);\n\nif (!result.success) {\n throw new Error(\n `Error executing Souffl\xe9 for ${this.id}:\\n${result.stderr}`,\n );\n}\n\nconst warnings = Array.from(result.results.entries.values()).map((fact) => {\n // raise warnings\n});\n"})}),"\n",(0,t.jsx)(n.h3,{id:"learning-from-existing-code",children:"Learning from Existing Code"}),"\n",(0,t.jsx)(n.p,{children:"We recommend studying the existing codebase, as it is well-documented and provides a comprehensive overview of integrating Souffl\xe9 with Misti. This will help you understand the intricacies of generating IR and executing Souffl\xe9 programs effectively."}),"\n",(0,t.jsx)(n.h2,{id:"further-reading",children:"Further Reading"}),"\n",(0,t.jsxs)(n.p,{children:["For a deeper understanding of static analysis using Souffl\xe9, refer to the textbook ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.a,{href:"https://arxiv.org/pdf/2012.10086",children:"Program Analysis: An Appetizer"})})," by Flemming Nielson and Hanne Riis Nielson. It discusses Souffl\xe9-based analysis in greater detail and is an excellent resource for both beginners and experienced developers in the field."]})]})}function u(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>a,x:()=>o});var t=i(6540);const r={},s=t.createContext(r);function a(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:a(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f3297ff5.c88faef0.js b/assets/js/f3297ff5.c88faef0.js new file mode 100644 index 000000000..64c8ec45a --- /dev/null +++ b/assets/js/f3297ff5.c88faef0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1537],{7942:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>o,contentTitle:()=>s,default:()=>p,frontMatter:()=>i,metadata:()=>l,toc:()=>d});var a=n(4848),r=n(8453);const i={},s="ReadOnlyVariables",l={id:"detectors/ReadOnlyVariables",title:"ReadOnlyVariables",description:"A detector that identifies read-only variables and fields.",source:"@site/docs/detectors/ReadOnlyVariables.md",sourceDirName:"detectors",slug:"/detectors/ReadOnlyVariables",permalink:"/tools/misti/docs/next/detectors/ReadOnlyVariables",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/ReadOnlyVariables.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"PreferredStdlibApi",permalink:"/tools/misti/docs/next/detectors/PreferredStdlibApi"},next:{title:"SendInLoop",permalink:"/tools/misti/docs/next/detectors/SendInLoop"}},o={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(t.h1,{id:"readonlyvariables",children:"ReadOnlyVariables"}),"\n",(0,a.jsx)(t.p,{children:"A detector that identifies read-only variables and fields."}),"\n",(0,a.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,a.jsx)(t.p,{children:"These variables could typically be replaced with constants to optimize performance.\nAlternatively, identifying read-only variables may reveal issues where unused values are being replaced unintentionally."}),"\n",(0,a.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-tact",children:"fun calculateFinalPrice(price: Int): Int {\n // Warning: the developer uses a read-only variable that could be a constant\n let DISCOUNT_AMOUNT: Int = 10;\n return price - DISCOUNT_AMOUNT;\n}\n"})}),"\n",(0,a.jsx)(t.p,{children:"Use instead:"}),"\n",(0,a.jsx)(t.pre,{children:(0,a.jsx)(t.code,{className:"language-tact",children:"const DISCOUNT_AMOUNT: Int = 10;\n\nfun calculateFinalPrice(price: Int): Int {\n // OK: Fixed after the analyzer highlighted this warning\n return price - DISCOUNT_AMOUNT;\n}\n"})})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,a.jsx)(t,{...e,children:(0,a.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>l});var a=n(6540);const r={},i=a.createContext(r);function s(e){const t=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f3466e67.b2bd9e44.js b/assets/js/f3466e67.b2bd9e44.js new file mode 100644 index 000000000..ae83b47cd --- /dev/null +++ b/assets/js/f3466e67.b2bd9e44.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[278],{252:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>a,toc:()=>d});var i=n(4848),s=n(8453);const o={id:"intro",title:"Introduction",slug:"/",sidebar_position:1},r=void 0,a={id:"intro",title:"Introduction",description:"Misti is a static analysis tool designed for smart contracts on the TON blockchain.",source:"@site/versioned_docs/version-0.1.2/index.md",sourceDirName:".",slug:"/",permalink:"/tools/misti/docs/0.1.2/",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/index.md",tags:[],version:"0.1.2",sidebarPosition:1,frontMatter:{id:"intro",title:"Introduction",slug:"/",sidebar_position:1},sidebar:"sidebar",next:{title:"Getting Started",permalink:"/tools/misti/docs/0.1.2/tutorial/getting-started"}},c={},d=[{value:"Use Cases",id:"use-cases",level:2},{value:"Funding",id:"funding",level:2}];function l(e){const t={a:"a",h2:"h2",li:"li",p:"p",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsxs)(t.p,{children:["Misti is a static analysis tool designed for smart contracts on the ",(0,i.jsx)(t.a,{href:"https://ton.org/",children:"TON blockchain"}),"."]}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.strong,{children:"Language Support:"})}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.a,{href:"https://tact-lang.org/",children:"Tact"})," 1.4.1 is supported."]}),"\n",(0,i.jsxs)(t.li,{children:["Support for ",(0,i.jsx)(t.a,{href:"https://docs.ton.org/develop/func/overview",children:"FunC"})," ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/56",children:"is planned"}),"."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"use-cases",children:"Use Cases"}),"\n",(0,i.jsx)(t.p,{children:"Misti is designed to detect issues in smart contracts efficiently, making it ideal for integration into development tools and CI/CD pipelines. By incorporating Misti, you can:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Detect Vulnerabilities:"})," Identify and fix potential security flaws early in the development cycle."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Improve Code Quality:"})," Maintain high standards by catching bugs and enforcing best practices automatically."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Streamline Development:"})," Integrate Misti into your CI/CD pipeline to ensure continuous code quality checks."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Custom Detectors:"})," Create custom detectors to solve specific problems in your code or to provide a thorough security review if you are an auditor."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"Go ahead and read more about the tool, including its design, to fully leverage its capabilities and integrate it effectively into your workflow."}),"\n",(0,i.jsx)(t.h2,{id:"funding",children:"Funding"}),"\n",(0,i.jsxs)(t.p,{children:["Misti has been ",(0,i.jsx)(t.a,{href:"https://github.com/ton-society/grants-and-bounties/issues/436",children:"funded"})," by ",(0,i.jsx)(t.a,{href:"https://ton.foundation",children:"TON Foundation"}),". This support has enabled us to develop and maintain the tool."]})]})}function u(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(e){const t=i.useContext(o);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f34cb5e0.b26c4fc7.js b/assets/js/f34cb5e0.b26c4fc7.js new file mode 100644 index 000000000..886ad2b7c --- /dev/null +++ b/assets/js/f34cb5e0.b26c4fc7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[9337],{9385:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>d});var o=n(4848),i=n(8453);const s={},r="FalseCondition",a={id:"detectors/FalseCondition",title:"FalseCondition",description:"A detector that highlights conditions that evaluate to a constant true or false",source:"@site/docs/detectors/FalseCondition.md",sourceDirName:"detectors",slug:"/detectors/FalseCondition",permalink:"/tools/misti/docs/next/detectors/FalseCondition",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/FalseCondition.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"EnsurePrgSeed",permalink:"/tools/misti/docs/next/detectors/EnsurePrgSeed"},next:{title:"FieldDoubleInit",permalink:"/tools/misti/docs/next/detectors/FieldDoubleInit"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"falsecondition",children:"FalseCondition"}),"\n",(0,o.jsxs)(t.p,{children:["A detector that highlights conditions that evaluate to a constant ",(0,o.jsx)(t.code,{children:"true"})," or ",(0,o.jsx)(t.code,{children:"false"}),"\nin ",(0,o.jsx)(t.code,{children:"if"}),", ",(0,o.jsx)(t.code,{children:"while"}),", or ",(0,o.jsx)(t.code,{children:"until"})," statements, and zero iterations in ",(0,o.jsx)(t.code,{children:"repeat"})," statements."]}),"\n",(0,o.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,o.jsxs)(t.p,{children:["Conditions that always evaluate to a constant ",(0,o.jsx)(t.code,{children:"true"})," or ",(0,o.jsx)(t.code,{children:"false"})," are likely the result of a typo\nor logic error. Such conditions can lead to unintended behavior, dead code, or incorrect control flow.\nThis detector helps identify these cases so they can be corrected, improving the code's reliability."]}),"\n",(0,o.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-tact",children:"const FALSE: Bool = false;\n// Bad: Always false because of operator precedence\nif ((param | value) & FALSE) {\n // ... never executed\n}\n"})}),"\n",(0,o.jsx)(t.p,{children:"Use instead:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-tact",children:"const FALSE: Bool = false;\n// OK: Fixed after the analyzer highlighted this\nif (param) {}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var o=n(6540);const i={},s=o.createContext(i);function r(e){const t=o.useContext(s);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),o.createElement(s.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f4d075b1.8ca57b63.js b/assets/js/f4d075b1.8ca57b63.js new file mode 100644 index 000000000..7ad8f1031 --- /dev/null +++ b/assets/js/f4d075b1.8ca57b63.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7378],{462:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>l});var n=i(4848),s=i(8453);const o={},a="Field Initialized Twice",d={id:"detectors/FieldDoubleInit",title:"Field Initialized Twice",description:"A detector that highlights cases where a field is initialized both in the init function and at the point of definition.",source:"@site/versioned_docs/version-0.2.2/detectors/FieldDoubleInit.md",sourceDirName:"detectors",slug:"/detectors/FieldDoubleInit",permalink:"/tools/misti/docs/0.2.2/detectors/FieldDoubleInit",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/FieldDoubleInit.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"`dump` Is Used",permalink:"/tools/misti/docs/0.2.2/detectors/DumpIsUsed"},next:{title:"Prefer Augmented Assignment",permalink:"/tools/misti/docs/0.2.2/detectors/PreferAugmentedAssign"}},r={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"field-initialized-twice",children:"Field Initialized Twice"}),"\n",(0,n.jsxs)(t.p,{children:["A detector that highlights cases where a field is initialized both in the ",(0,n.jsx)(t.code,{children:"init"})," function and at the point of definition."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["Double initialization of fields can either be a programmer's mistake or simply a waste of gas. It is always preferred to initialize values in the field declaration if they have a compile-time evaluatable default value, or in the ",(0,n.jsx)(t.code,{children:"init"})," function if they must be initialized dynamically."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 0; // Bad\n init(x: Int) { self.a = x }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int; // Fixed\n init(x: Int) { self.a = x }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>d});var n=i(6540);const s={},o=n.createContext(s);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f503d00c.e7655ff6.js b/assets/js/f503d00c.e7655ff6.js new file mode 100644 index 000000000..218261073 --- /dev/null +++ b/assets/js/f503d00c.e7655ff6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2819],{7563:(e,t,i)=>{i.r(t),i.d(t,{assets:()=>r,contentTitle:()=>a,default:()=>h,frontMatter:()=>o,metadata:()=>d,toc:()=>l});var n=i(4848),s=i(8453);const o={},a="Field Initialized Twice",d={id:"detectors/FieldDoubleInit",title:"Field Initialized Twice",description:"A detector that highlights cases where a field is initialized both in the init function and at the point of definition.",source:"@site/versioned_docs/version-0.2.1/detectors/FieldDoubleInit.md",sourceDirName:"detectors",slug:"/detectors/FieldDoubleInit",permalink:"/tools/misti/docs/0.2.1/detectors/FieldDoubleInit",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/FieldDoubleInit.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"`dump` Is Used",permalink:"/tools/misti/docs/0.2.1/detectors/DumpIsUsed"},next:{title:"Prefer Augmented Assignment",permalink:"/tools/misti/docs/0.2.1/detectors/PreferAugmentedAssign"}},r={},l=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function c(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"field-initialized-twice",children:"Field Initialized Twice"}),"\n",(0,n.jsxs)(t.p,{children:["A detector that highlights cases where a field is initialized both in the ",(0,n.jsx)(t.code,{children:"init"})," function and at the point of definition."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["Double initialization of fields can either be a programmer's mistake or simply a waste of gas. It is always preferred to initialize values in the field declaration if they have a compile-time evaluatable default value, or in the ",(0,n.jsx)(t.code,{children:"init"})," function if they must be initialized dynamically."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int = 0; // Bad\n init(x: Int) { self.a = x }\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"contract Test {\n a: Int; // Fixed\n init(x: Int) { self.a = x }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(c,{...e})}):c(e)}},8453:(e,t,i)=>{i.d(t,{R:()=>a,x:()=>d});var n=i(6540);const s={},o=n.createContext(s);function a(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f553073e.4bde77ae.js b/assets/js/f553073e.4bde77ae.js new file mode 100644 index 000000000..b3f9e0336 --- /dev/null +++ b/assets/js/f553073e.4bde77ae.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[223],{6141:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>o,default:()=>p,frontMatter:()=>i,metadata:()=>a,toc:()=>d});var n=t(4848),s=t(8453);const i={},o="StringReceiversOverlap",a={id:"detectors/StringReceiversOverlap",title:"StringReceiversOverlap",description:"A detector that finds overlapping messages between general string receivers and string receivers.",source:"@site/versioned_docs/version-0.4.0/detectors/StringReceiversOverlap.md",sourceDirName:"detectors",slug:"/detectors/StringReceiversOverlap",permalink:"/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/detectors/StringReceiversOverlap.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"ReadOnlyVariables",permalink:"/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables"},next:{title:"UnboundLoops",permalink:"/tools/misti/docs/0.4.0/detectors/UnboundLoops"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const r={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,s.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(r.h1,{id:"stringreceiversoverlap",children:"StringReceiversOverlap"}),"\n",(0,n.jsx)(r.p,{children:"A detector that finds overlapping messages between general string receivers and string receivers."}),"\n",(0,n.jsx)(r.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsx)(r.p,{children:"Constant string receivers and general string receivers can have overlapping messages\nin which case the constant string receiver always takes precedence."}),"\n",(0,n.jsx)(r.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {\n if (msg == "foobar") { throw(1043) } // Bad: Dead code\n }\n}\n'})}),"\n",(0,n.jsx)(r.p,{children:"Use instead:"}),"\n",(0,n.jsx)(r.pre,{children:(0,n.jsx)(r.code,{className:"language-tact",children:'contract Test {\n receive("foobar") { throw(1042) }\n receive(msg: String) {}\n}\n'})})]})}function p(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,n.jsx)(r,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,r,t)=>{t.d(r,{R:()=>o,x:()=>a});var n=t(6540);const s={},i=n.createContext(s);function o(e){const r=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),n.createElement(i.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f5772bf1.e894af92.js b/assets/js/f5772bf1.e894af92.js new file mode 100644 index 000000000..dd389de19 --- /dev/null +++ b/assets/js/f5772bf1.e894af92.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1697],{1611:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>l,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var i=n(4848),s=n(8453);const r={},l="Getting started",o={id:"tutorial/getting-started",title:"Getting started",description:"This guide will walk you through the steps to install and set up the Misti static analyzer.",source:"@site/versioned_docs/version-0.2.1/tutorial/getting-started.md",sourceDirName:"tutorial",slug:"/tutorial/getting-started",permalink:"/tools/misti/docs/0.2.1/tutorial/getting-started",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/tutorial/getting-started.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Introduction",permalink:"/tools/misti/docs/0.2.1/"},next:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.2.1/tutorial/ci-cd"}},a={},d=[{value:"Prerequisites",id:"prerequisites",level:2},{value:"Installation",id:"installation",level:2},{value:"Using Development Version",id:"using-development-version",level:3},{value:"Running the analysis",id:"running-the-analysis",level:2},{value:"Troubleshooting",id:"troubleshooting",level:2}];function c(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"getting-started",children:"Getting started"}),"\n",(0,i.jsx)(t.p,{children:"This guide will walk you through the steps to install and set up the Misti static analyzer."}),"\n",(0,i.jsx)(t.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,i.jsx)(t.p,{children:"Before you begin, ensure you have the following software installed on your system:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsx)(t.li,{children:"Git"}),"\n",(0,i.jsx)(t.li,{children:"Yarn"}),"\n",(0,i.jsx)(t.li,{children:"Node.js"}),"\n",(0,i.jsx)(t.li,{children:(0,i.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"installation",children:"Installation"}),"\n",(0,i.jsxs)(t.p,{children:["Misti is distributed via npm and should be added to your Tact project ",(0,i.jsx)(t.a,{href:"https://github.com/tact-lang/tact?tab=readme-ov-file#installation",children:"in the same way"})," as Tact itself:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-bash",children:"yarn add @nowarp/misti\n"})}),"\n",(0,i.jsx)(t.h3,{id:"using-development-version",children:"Using Development Version"}),"\n",(0,i.jsx)(t.p,{children:"The latest development version may be unstable, yet it includes all the recently added detectors and therefore can provide a more comprehensive analysis."}),"\n",(0,i.jsx)(t.p,{children:"To install the latest development version you should:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:["Clone Misti: ",(0,i.jsx)(t.code,{children:"git clone https://github.com/nowarp/misti"})]}),"\n",(0,i.jsxs)(t.li,{children:["Build it: ",(0,i.jsx)(t.code,{children:"cd misti && yarn install && yarn build"})]}),"\n",(0,i.jsxs)(t.li,{children:["Use it in your Tact project: ",(0,i.jsx)(t.code,{children:"cd /path/to/tact/project && yarn add file:/path/to/misti"})]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"running-the-analysis",children:"Running the analysis"}),"\n",(0,i.jsx)(t.p,{children:"Run Misti by specifying a Tact project configuration:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:"npx misti test/projects/simple/tactConfig.json\n"})}),"\n",(0,i.jsx)(t.p,{children:"This will highlight any warnings the analyzer found."}),"\n",(0,i.jsxs)(t.p,{children:["You can also add a script to your ",(0,i.jsx)(t.code,{children:"package.json"})," to simplify running the linting process:"]}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-json",children:'{\n "scripts": {\n "lint": "npx misti test/projects/simple/tactConfig.json"\n }\n}\n'})}),"\n",(0,i.jsx)(t.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsxs)(t.p,{children:["If you encounter any issues during the installation process, feel free to ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/issues/new",children:"create an issue"})," or ask in the ",(0,i.jsx)(t.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,s.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>l,x:()=>o});var i=n(6540);const s={},r=i.createContext(s);function l(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f58fcc43.14b05cf2.js b/assets/js/f58fcc43.14b05cf2.js new file mode 100644 index 000000000..ec63b30cd --- /dev/null +++ b/assets/js/f58fcc43.14b05cf2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[219],{9089:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>l,frontMatter:()=>r,metadata:()=>c,toc:()=>d});var i=n(4848),o=n(8453);const r={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.4.0/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/0.4.0/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/hacking/custom-detector.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.4.0/hacking/souffle"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Creating a Detector",id:"creating-a-detector",level:2},{value:"Testing the detector",id:"testing-the-detector",level:3},{value:"Saving the configuration",id:"saving-the-configuration",level:3},{value:"Example Detectors",id:"example-detectors",level:2}];function h(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,i.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,i.jsx)(t.a,{href:"https://nowarp.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,i.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,i.jsx)(t.h2,{id:"creating-a-detector",children:"Creating a Detector"}),"\n",(0,i.jsxs)(t.p,{children:["You can create a new custom detector by executing Misti with the ",(0,i.jsx)(t.code,{children:"--new-detector"})," option: ",(0,i.jsx)(t.code,{children:"npx misti --new-detector implicitInit"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["This will create the ",(0,i.jsx)(t.code,{children:"implicitInit.ts"})," file, which contains the template code for writing your own custom detector logic leveraging the Misti API."]}),"\n",(0,i.jsx)(t.p,{children:"Here's an example of how to implement a custom detector using Misti API:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-typescript",children:'import { ASTDetector } from "@nowarp/misti/dist/detectors/detector";\nimport { CompilationUnit } from "@nowarp/misti/dist/internals/ir";\nimport {\n MistiTactWarning,\n Severity,\n} from "@nowarp/misti/dist/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that doesn\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends ASTDetector {\n severity = Severity.INFO;\n\n async check(cu: CompilationUnit): Promise {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = this.makeWarning(\n `Contract ${contract.name} doesn\'t define an init function`,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactWarning[]);\n }\n}\n\n'})}),"\n",(0,i.jsx)(t.h3,{id:"testing-the-detector",children:"Testing the detector"}),"\n",(0,i.jsxs)(t.p,{children:["To run Misti with only your new detector, use the ",(0,i.jsx)(t.code,{children:"--detectors"})," option, specifying the path to the detector and the Detector class name: ",(0,i.jsx)(t.code,{children:"npx misti path/to/your/tact.config.json --detectors path/to/implicitInit.ts:ImplicitInit"}),"."]}),"\n",(0,i.jsxs)(t.p,{children:["That's a good way to test the detector on the first run. You could also use the ",(0,i.jsx)(t.code,{children:"--verbose"})," CLI option and set the environment variable ",(0,i.jsx)(t.code,{children:"MISTI_TRACE=1"})," to facilitate debugging."]}),"\n",(0,i.jsx)(t.h3,{id:"saving-the-configuration",children:"Saving the configuration"}),"\n",(0,i.jsx)(t.p,{children:"After testing the detector, you can specify it in your configuration to enable it in future runs. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{children:'{\n "detectors": [\n // Other detectors...\n { "className": "ImplicitInit", "modulePath": "ImplicitInit.ts" }\n ],\n}\n'})}),"\n",(0,i.jsxs)(t.p,{children:["After this, you could run Misti specifying a path to a custom configuration ",(0,i.jsx)(t.code,{children:"npx misti --config path/to/misti.config.json path/to/your/tact.config.json"}),"."]}),"\n",(0,i.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,i.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,i.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function l(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var i=n(6540);const o={},r=i.createContext(o);function s(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:s(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f5bf49b8.3b9a5601.js b/assets/js/f5bf49b8.3b9a5601.js new file mode 100644 index 000000000..fa2b367c8 --- /dev/null +++ b/assets/js/f5bf49b8.3b9a5601.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[243],{7857:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var s=n(4848),i=n(8453);const r={},o="Prefer Augmented Assignment",a={id:"detectors/PreferAugmentedAssign",title:"Prefer Augmented Assignment",description:"Detects non-idiomatic statements that can be written using augmented assignment operators like +=, -=, etc.",source:"@site/versioned_docs/version-0.2.1/detectors/PreferAugmentedAssign.md",sourceDirName:"detectors",slug:"/detectors/PreferAugmentedAssign",permalink:"/tools/misti/docs/0.2.1/detectors/PreferAugmentedAssign",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.1/detectors/PreferAugmentedAssign.md",tags:[],version:"0.2.1",frontMatter:{},sidebar:"sidebar",previous:{title:"Field Initialized Twice",permalink:"/tools/misti/docs/0.2.1/detectors/FieldDoubleInit"},next:{title:"Contributing",permalink:"/tools/misti/docs/0.2.1/hacking/contributing"}},c={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"prefer-augmented-assignment",children:"Prefer Augmented Assignment"}),"\n",(0,s.jsxs)(t.p,{children:["Detects non-idiomatic statements that can be written using augmented assignment operators like ",(0,s.jsx)(t.code,{children:"+="}),", ",(0,s.jsx)(t.code,{children:"-="}),", etc."]}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Using augmented assignment operations improves the readability of the source code and reduces the risk of mistakes, such as those that occur during copy-pasting and refactoring code."}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue = (msgValue - ctx.readForwardFee());\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"msgValue -= ctx.readForwardFee());\n"})})]})}function u(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>o,x:()=>a});var s=n(6540);const i={},r=s.createContext(i);function o(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f6f2b22b.1f2e8cc1.js b/assets/js/f6f2b22b.1f2e8cc1.js new file mode 100644 index 000000000..c2c56e07b --- /dev/null +++ b/assets/js/f6f2b22b.1f2e8cc1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[2091],{5208:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>t,metadata:()=>r,toc:()=>o});var i=s(4848),l=s(8453);const t={},d="Command-Line Interface",r={id:"tutorial/cli",title:"Command-Line Interface",description:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each.",source:"@site/versioned_docs/version-0.3.1/tutorial/cli.md",sourceDirName:"tutorial",slug:"/tutorial/cli",permalink:"/tools/misti/docs/0.3.1/tutorial/cli",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.1/tutorial/cli.md",tags:[],version:"0.3.1",frontMatter:{},sidebar:"sidebar",previous:{title:"CI/CD Integration",permalink:"/tools/misti/docs/0.3.1/tutorial/ci-cd"},next:{title:"Configuration",permalink:"/tools/misti/docs/0.3.1/tutorial/configuration"}},c={},o=[{value:" --dump-cfg <json|dot>
",id:"--dump-cfg-jsondot",level:3},{value:"--dump-ast
",id:"--dump-ast",level:3},{value:"--dump-output <PATH>
",id:"--dump-output-path",level:3},{value:"--dump-include-stdlib
",id:"--dump-include-stdlib",level:3},{value:"--dump-config
",id:"--dump-config",level:3},{value:"--souffle-binary <PATH>
",id:"--souffle-binary-path",level:3},{value:"--souffle-path <PATH>
",id:"--souffle-path-path",level:3},{value:"--souffle-verbose
",id:"--souffle-verbose",level:3},{value:"--tact-stdlib-path <PATH>
",id:"--tact-stdlib-path-path",level:3},{value:"--verbose
",id:"--verbose",level:3},{value:"--quiet
",id:"--quiet",level:3},{value:"--detectors <name|path:name>
",id:"--detectors-namepathname",level:3},{value:"--suppress <names>
",id:"--suppress-names",level:3},{value:"--all-detectors
",id:"--all-detectors",level:3},{value:"--config <PATH>
",id:"--config-path",level:3},{value:"--new-detector <PATH>
",id:"--new-detector-path",level:3}];function a(e){const n={code:"code",h1:"h1",h3:"h3",li:"li",p:"p",strong:"strong",ul:"ul",...(0,l.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"command-line-interface",children:"Command-Line Interface"}),"\n",(0,i.jsx)(n.p,{children:"Below is a list of all available CLI (Command-Line Interface) options for the project, with a brief explanation of each."}),"\n",(0,i.jsx)(n.h3,{id:"--dump-cfg-jsondot",children:(0,i.jsx)(n.code,{children:"--dump-cfg"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Dumps the Control Flow Graph (CFG) in the requested format: JSON or Graphviz Dot."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-ast",children:(0,i.jsx)(n.code,{children:"--dump-ast"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Dumps the Abstract Syntax Tree (AST) in JSON format."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-output-path",children:(0,i.jsx)(n.code,{children:"--dump-output "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Specifies the directory to save the AST/CFG dump. If ",(0,i.jsx)(n.code,{children:" "})," is ",(0,i.jsx)(n.code,{children:"-"}),", then the output is sent to stdout."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": Value of ",(0,i.jsx)(n.code,{children:"DUMP_STDOUT_PATH"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-include-stdlib",children:(0,i.jsx)(n.code,{children:"--dump-include-stdlib"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Includes standard library components in the AST/CFG dump."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--dump-config",children:(0,i.jsx)(n.code,{children:"--dump-config"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Dumps the Misti JSON configuration file in use."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--souffle-binary-path",children:(0,i.jsx)(n.code,{children:"--souffle-binary "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Path to the Souffl\xe9 binary."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:'"souffle"'})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--souffle-path-path",children:(0,i.jsx)(n.code,{children:"--souffle-path "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Directory to save the generated Souffl\xe9 files."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:'"/tmp/misti/souffle"'})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--souffle-verbose",children:(0,i.jsx)(n.code,{children:"--souffle-verbose"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Generates human-readable, but more verbose, Souffl\xe9 files."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--tact-stdlib-path-path",children:(0,i.jsx)(n.code,{children:"--tact-stdlib-path "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Path to the Tact standard library."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--verbose",children:(0,i.jsx)(n.code,{children:"--verbose"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Enables verbose output."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--quiet",children:(0,i.jsx)(n.code,{children:"--quiet"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Suppresses all output."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--detectors-namepathname",children:(0,i.jsx)(n.code,{children:"--detectors "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": A comma-separated list of detectors to enable."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Argument Validation"}),": Requires a non-empty list of detector names."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--suppress-names",children:(0,i.jsx)(n.code,{children:"--suppress "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": A comma-separated list of detector names to suppress."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Argument Validation"}),": Requires a non-empty list of detector names."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--all-detectors",children:(0,i.jsx)(n.code,{children:"--all-detectors"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Enables all the available built-in detectors."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"false"})]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--config-path",children:(0,i.jsx)(n.code,{children:"--config "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Path to the Misti configuration file."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"--new-detector-path",children:(0,i.jsx)(n.code,{children:"--new-detector "})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Description"}),": Creates a new custom detector at the specified path."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Default"}),": ",(0,i.jsx)(n.code,{children:"undefined"})]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},8453:(e,n,s)=>{s.d(n,{R:()=>d,x:()=>r});var i=s(6540);const l={},t=i.createContext(l);function d(e){const n=i.useContext(t);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:d(e.components),i.createElement(t.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f752d1db.1f995ffc.js b/assets/js/f752d1db.1f995ffc.js new file mode 100644 index 000000000..b19201fed --- /dev/null +++ b/assets/js/f752d1db.1f995ffc.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5900],{8656:(t,e,n)=>{n.r(e),n.d(e,{assets:()=>c,contentTitle:()=>r,default:()=>d,frontMatter:()=>o,metadata:()=>a,toc:()=>l});var i=n(4848),s=n(8453);const o={},r="Integrating Misti into CI/CD",a={id:"tutorial/ci-cd",title:"Integrating Misti into CI/CD",description:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle.",source:"@site/versioned_docs/version-0.4.0/tutorial/ci-cd.md",sourceDirName:"tutorial",slug:"/tutorial/ci-cd",permalink:"/tools/misti/docs/0.4.0/tutorial/ci-cd",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.4.0/tutorial/ci-cd.md",tags:[],version:"0.4.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Getting Started",permalink:"/tools/misti/docs/0.4.0/tutorial/getting-started"},next:{title:"Command-Line Interface",permalink:"/tools/misti/docs/0.4.0/tutorial/cli"}},c={},l=[{value:"Using Tact Template",id:"using-tact-template",level:2},{value:"GitHub Actions",id:"github-actions",level:2},{value:"Integration with Blueprint Projects",id:"integration-with-blueprint-projects",level:2}];function u(t){const e={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,s.R)(),...t.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(e.h1,{id:"integrating-misti-into-cicd",children:"Integrating Misti into CI/CD"}),"\n",(0,i.jsx)(e.p,{children:"Integrating Misti into your CI/CD pipeline ensures continuous code quality checks, catching issues early in the development cycle."}),"\n",(0,i.jsx)(e.h2,{id:"using-tact-template",children:"Using Tact Template"}),"\n",(0,i.jsxs)(e.p,{children:[(0,i.jsx)(e.a,{href:"https://github.com/tact-lang/tact-template",children:(0,i.jsx)(e.code,{children:"tact-template"})})," is a template project for Tact. If you started your project from this template, Misti is already installed in ",(0,i.jsx)(e.a,{href:"https://github.com/tact-lang/tact-template/tree/main/.github/workflows",children:"the CI"}),". You also have the ",(0,i.jsx)(e.code,{children:"yarn lint"})," command available in your ",(0,i.jsx)(e.code,{children:"package.json"}),"."]}),"\n",(0,i.jsx)(e.h2,{id:"github-actions",children:"GitHub Actions"}),"\n",(0,i.jsx)(e.p,{children:"To integrate Misti into your GitHub Actions workflow, you need to add a command that runs Misti as part of your CI process. Here's how you can do it:"}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"1. Open your GitHub repository"})}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"2. Create or edit the GitHub Actions workflow YAML file"})}),"\n",(0,i.jsxs)(e.p,{children:["It could be located at e.g., ",(0,i.jsx)(e.code,{children:".github/workflows/ci.yml"}),"."]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"3. Add the step to run Misti to your YAML file"})}),"\n",(0,i.jsx)(e.p,{children:"For example:"}),"\n",(0,i.jsx)(e.pre,{children:(0,i.jsx)(e.code,{className:"language-yaml",children:'name: CI\n\non:\n push:\n branches: [ "main" ]\n pull_request:\n branches: [ "main" ]\n workflow_dispatch:\n\njobs:\n test:\n strategy:\n fail-fast: false\n matrix:\n node-version: [22]\n os: [ubuntu-latest]\n runs-on: ${{ matrix.os }}\n steps:\n - name: Checkout code\n uses: actions/checkout@v2\n\n - name: Install Souffl\xe9 on Ubuntu\n if: matrix.os == \'ubuntu-latest\'\n run: |\n sudo wget https://souffle-lang.github.io/ppa/souffle-key.public -O /usr/share/keyrings/souffle-archive-keyring.gpg\n echo "deb [signed-by=/usr/share/keyrings/souffle-archive-keyring.gpg] https://souffle-lang.github.io/ppa/ubuntu/ stable main" | sudo tee /etc/apt/sources.list.d/souffle.list\n sudo apt update\n sudo apt install souffle\n\n - name: Setup Node.js\n uses: actions/setup-node@v3\n with:\n node-version: ${{ matrix.node-version }}\n\n - name: Install dependencies\n run: yarn install\n\n - name: Run Misti\n run: yarn misti --min-severity medium /path/to/your/tact.config.json\n'})}),"\n",(0,i.jsxs)(e.p,{children:["The ",(0,i.jsx)(e.code,{children:"yarn misti --min-severity medium /path/to/your/tact.config.json"})," command will run Misti against your project. If Misti detects any issues that are not suppressed by your configuration, it will return a non-zero exit code, causing the CI pipeline to fail."]}),"\n",(0,i.jsxs)(e.p,{children:["The ",(0,i.jsx)(e.code,{children:"--min-severity medium"})," will filter out low-priority warnings. You can always run Misti with all the detectors enabled locally in order to get the most comprehensive warnings output: ",(0,i.jsx)(e.code,{children:"yarn misti --all-detectors /path/to/your/tact.config.json"})]}),"\n",(0,i.jsx)(e.p,{children:(0,i.jsx)(e.strong,{children:"4. Adjusting the Misti Configuration"})}),"\n",(0,i.jsxs)(e.p,{children:["If you find that Misti is too noisy (e.g., detecting issues that are not relevant to your project), you can adjust your Misti configuration file to suppress those warnings. Refer to the ",(0,i.jsx)(e.a,{href:"./configuration",children:"Configuration"})," section for more details on how to customize your settings."]}),"\n",(0,i.jsx)(e.h2,{id:"integration-with-blueprint-projects",children:"Integration with Blueprint Projects"}),"\n",(0,i.jsx)(e.p,{children:"To add Misti to the CI for your Blueprint project, follow these steps:"}),"\n",(0,i.jsxs)(e.ol,{children:["\n",(0,i.jsxs)(e.li,{children:[(0,i.jsxs)(e.a,{href:"/tools/misti/docs/0.4.0/tutorial/blueprint",children:["Install ",(0,i.jsx)(e.code,{children:"blueprint-misti"})]}),"."]}),"\n",(0,i.jsxs)(e.li,{children:["Follow the steps to set up the GitHub action above, but replace the ",(0,i.jsx)(e.code,{children:"yarn misti"})," command with ",(0,i.jsx)(e.code,{children:"npx blueprint misti --blueprint-project "}),", where ",(0,i.jsx)(e.code,{children:" "})," is the name of the project displayed when you run ",(0,i.jsx)(e.code,{children:"npx blueprint build"}),"."]}),"\n"]})]})}function d(t={}){const{wrapper:e}={...(0,s.R)(),...t.components};return e?(0,i.jsx)(e,{...t,children:(0,i.jsx)(u,{...t})}):u(t)}},8453:(t,e,n)=>{n.d(e,{R:()=>r,x:()=>a});var i=n(6540);const s={},o=i.createContext(s);function r(t){const e=i.useContext(o);return i.useMemo((function(){return"function"==typeof t?t(e):{...e,...t}}),[e,t])}function a(t){let e;return e=t.disableParentContext?"function"==typeof t.components?t.components(s):t.components||s:r(t.components),i.createElement(o.Provider,{value:e},t.children)}}}]); \ No newline at end of file diff --git a/assets/js/f7ab1f3a.096a7a59.js b/assets/js/f7ab1f3a.096a7a59.js new file mode 100644 index 000000000..10aea86ba --- /dev/null +++ b/assets/js/f7ab1f3a.096a7a59.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[3754],{4856:(e,i,n)=>{n.r(i),n.d(i,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>l,toc:()=>c});var s=n(4848),t=n(8453);const a={},o="Design Overview",l={id:"hacking/design",title:"Design Overview",description:"Static Analysis",source:"@site/versioned_docs/version-0.1.2/hacking/design.md",sourceDirName:"hacking",slug:"/hacking/design",permalink:"/tools/misti/docs/0.1.2/hacking/design",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.1.2/hacking/design.md",tags:[],version:"0.1.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Contributing",permalink:"/tools/misti/docs/0.1.2/hacking/contributing"},next:{title:"Souffl\xe9",permalink:"/tools/misti/docs/0.1.2/hacking/souffle"}},r={},c=[{value:"Static Analysis",id:"static-analysis",level:2},{value:"Souffle Datalog Solver",id:"souffle-datalog-solver",level:2},{value:"Dataflow Analysis in Misti",id:"dataflow-analysis-in-misti",level:2},{value:"References",id:"references",level:2}];function d(e){const i={a:"a",h1:"h1",h2:"h2",li:"li",p:"p",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(i.h1,{id:"design-overview",children:"Design Overview"}),"\n",(0,s.jsx)(i.h2,{id:"static-analysis",children:"Static Analysis"}),"\n",(0,s.jsx)(i.p,{children:"Misti is a static analyzer, a tool that examines code without executing it, identifying potential errors, security vulnerabilities, and code quality issues."}),"\n",(0,s.jsx)(i.h2,{id:"souffle-datalog-solver",children:"Souffle Datalog Solver"}),"\n",(0,s.jsxs)(i.p,{children:["Misti leverages the ",(0,s.jsx)(i.a,{href:"https://souffle-lang.github.io",children:"Souffle Datalog solver"}),", an industry-grade and highly efficient Datalog solver designed specifically for program analysis. Souffle provides native parallel execution and is extremely fast, making it an ideal choice for analyzing complex codebases."]}),"\n",(0,s.jsx)(i.h2,{id:"dataflow-analysis-in-misti",children:"Dataflow Analysis in Misti"}),"\n",(0,s.jsx)(i.p,{children:"Misti offers an interface to describe classic dataflow problems. It includes a lattice interface and provides a mechanism to solve these problems using the worklist algorithm. This allows for efficient and accurate analysis of data flow within the code."}),"\n",(0,s.jsx)(i.h2,{id:"references",children:"References"}),"\n",(0,s.jsx)(i.p,{children:"For those interested in learning more about static analysis and dataflow analysis, the following books are recommended:"}),"\n",(0,s.jsxs)(i.ul,{children:["\n",(0,s.jsx)(i.li,{children:(0,s.jsx)(i.a,{href:"https://cs.au.dk/~amoeller/spa/spa.pdf",children:"Anders M\xf8ller and Michael I. Schwartzbach \u2013 Static Program Analysis"})}),"\n",(0,s.jsx)(i.li,{children:"Uday Khedker et al. \u2013 Data Flow Analysis: Theory and Practice"}),"\n"]}),"\n",(0,s.jsx)(i.p,{children:"These resources provide a solid foundation in the theory and practice of static and dataflow analysis."})]})}function h(e={}){const{wrapper:i}={...(0,t.R)(),...e.components};return i?(0,s.jsx)(i,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,i,n)=>{n.d(i,{R:()=>o,x:()=>l});var s=n(6540);const t={},a=s.createContext(t);function o(e){const i=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(i):{...i,...e}}),[i,e])}function l(e){let i;return i=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:o(e.components),s.createElement(a.Provider,{value:i},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f97c3fca.388d1a86.js b/assets/js/f97c3fca.388d1a86.js new file mode 100644 index 000000000..e9a0d1a55 --- /dev/null +++ b/assets/js/f97c3fca.388d1a86.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[877],{4297:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>d,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>c});var s=n(4848),o=n(8453);const r={},d="ConstantAddress",a={id:"detectors/ConstantAddress",title:"ConstantAddress",description:"An optional detector that highlights all the constant addresses appearing in the source code.",source:"@site/docs/detectors/ConstantAddress.md",sourceDirName:"detectors",slug:"/detectors/ConstantAddress",permalink:"/tools/misti/docs/next/detectors/ConstantAddress",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors/ConstantAddress.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"CellOverflow",permalink:"/tools/misti/docs/next/detectors/CellOverflow"},next:{title:"DivideBeforeMultiply",permalink:"/tools/misti/docs/next/detectors/DivideBeforeMultiply"}},i={},c=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"constantaddress",children:"ConstantAddress"}),"\n",(0,s.jsx)(t.p,{children:"An optional detector that highlights all the constant addresses appearing in the source code."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsxs)(t.p,{children:["Using hardcoded addresses can sometimes indicate poor contract design.\nSome constant addresses may need to be set dynamically, e.g., using\n",(0,s.jsx)(t.code,{children:"contractAddress"}),", or at least have a way to change them at runtime, for\nexample, when upgrading a contract."]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:'contract Main {\n proxy: Address;\n init() {\n // Bad: Constant address highlighted by the analyzer.\n self.proxy = address("UQBKgXCNLPexWhs2L79kiARR1phGH1LwXxRbNsCFF9doczSI");\n }\n}\n'})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"contract Main {\n proxy: Address;\n init() {\n let proxy: Proxy = initOf Proxy(myAddress());\n // OK: Address depends on how the proxy contact has been deployed\n self.proxy = contractAddress(proxy);\n }\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,o.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>d,x:()=>a});var s=n(6540);const o={},r=s.createContext(o);function d(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:d(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/f99bae31.0a506efe.js b/assets/js/f99bae31.0a506efe.js new file mode 100644 index 000000000..08b0537a6 --- /dev/null +++ b/assets/js/f99bae31.0a506efe.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8927],{8721:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>a,contentTitle:()=>o,default:()=>h,frontMatter:()=>s,metadata:()=>d,toc:()=>l});var i=t(4848),r=t(8453);const s={},o="DumpImports",d={id:"tools/DumpImports",title:"DumpImports",description:"Misti provides a feature to dump the Import Graph of your Tact code in JSON, DOT, and Mermaid formats. This tool helps you understand the dependencies between different files and modules in your project, including how contracts import each other and use the standard library.",source:"@site/docs/tools/DumpImports.md",sourceDirName:"tools",slug:"/tools/DumpImports",permalink:"/tools/misti/docs/next/tools/DumpImports",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/tools/DumpImports.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"DumpConfig",permalink:"/tools/misti/docs/next/tools/DumpConfig"},next:{title:"Design Overview",permalink:"/tools/misti/docs/next/hacking/design"}},a={},l=[{value:"Usage",id:"usage",level:2},{value:"Working with Mermaid and Graphviz",id:"working-with-mermaid-and-graphviz",level:2},{value:"Understanding the Dumps",id:"understanding-the-dumps",level:2},{value:"Including Standard Library Imports",id:"including-standard-library-imports",level:2},{value:"Example",id:"example",level:2},{value:"Interpreting the Import Graph",id:"interpreting-the-import-graph",level:2},{value:"Conclusion",id:"conclusion",level:2}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"dumpimports",children:"DumpImports"}),"\n",(0,i.jsxs)(n.p,{children:["Misti provides a feature to dump the ",(0,i.jsx)(n.strong,{children:"Import Graph"})," of your Tact code in JSON, DOT, and Mermaid formats. This tool helps you understand the dependencies between different files and modules in your project, including how contracts import each other and use the standard library."]}),"\n",(0,i.jsx)(n.h2,{id:"usage",children:"Usage"}),"\n",(0,i.jsx)(n.p,{children:"To dump the Import Graph in Mermaid format, use the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'misti -t "DumpImports:format=mmd" \n'})}),"\n",(0,i.jsx)(n.p,{children:"To dump the Import Graph in Graphviz DOT format, use the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'misti -t "DumpImports:format=dot" \n'})}),"\n",(0,i.jsx)(n.p,{children:"To dump the Import Graph in JSON format, use the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'misti -t "DumpImports:format=json" \n'})}),"\n",(0,i.jsxs)(n.p,{children:["You can also include Tact standard library imports in the dump by adding ",(0,i.jsx)(n.code,{children:"dumpStdlib=true"})," to the ",(0,i.jsx)(n.code,{children:"DumpImports"})," options:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'misti -t "DumpImports:format=dot,dumpStdlib=true" \n'})}),"\n",(0,i.jsx)(n.h2,{id:"working-with-mermaid-and-graphviz",children:"Working with Mermaid and Graphviz"}),"\n",(0,i.jsxs)(n.p,{children:["For guidance on how to work with Mermaid diagrams, Graphviz DOT files, and viewing them in Visual Studio Code, please refer to the ",(0,i.jsx)(n.a,{href:"/tools/misti/docs/next/tools/DumpCfg#working-with-mermaid",children:"DumpCfg documentation"})," and the ",(0,i.jsx)(n.a,{href:"/tools/misti/docs/next/tools/DumpCfg#working-with-graphviz",children:"Graphviz section"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"understanding-the-dumps",children:"Understanding the Dumps"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"JSON Dumps"}),": Provide a detailed representation of the Import Graph in JSON format, including nodes and edges with their properties. Useful for programmatic analysis or custom tooling."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"DOT Dumps"}),": Offer a visual representation of the project's import dependencies. Useful for understanding how files and contracts depend on each other."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Mermaid Dumps"}),": Similar to DOT dumps but using Mermaid syntax, which can be easier to work with in certain environments, especially when using markdown files or online editors."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"By utilizing these tools, developers can gain deeper insights into the dependency structure of their Tact projects, facilitating better project organization, dependency management, and code optimization."}),"\n",(0,i.jsx)(n.h2,{id:"including-standard-library-imports",children:"Including Standard Library Imports"}),"\n",(0,i.jsxs)(n.p,{children:["By default, the Import Graph excludes imports from the standard library. If you want to include standard library imports in your graph, add ",(0,i.jsx)(n.code,{children:"dumpStdlib=true"})," to the command:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'misti -t "DumpImports:format=mmd,dumpStdlib=true" contracts/main.tact\n'})}),"\n",(0,i.jsx)(n.h2,{id:"example",children:"Example"}),"\n",(0,i.jsx)(n.p,{children:"Consider a project with the following structure:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"main.tact"})}),":"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:'import "./constants.tact";\nimport "./messages.tact";\nimport "@stdlib/ownable";\ncontract C{}\n'})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"constants.tact"})}),":"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:"const SOMETHING: Int = 123;\n"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"messages.tact"})}),":"]}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-tact",children:'import "./constants.tact";\nmessage Msg { a: Bool }\n'})}),"\n",(0,i.jsx)(n.p,{children:"To dump the Import Graph in Mermaid format, run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'misti -t "DumpImports:format=mmd:dumpStdlib=true" contracts/main.tact\n'})}),"\n",(0,i.jsx)(n.p,{children:"The output will look like:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-mermaid",children:'graph TD\n node_1["main"]:::contractNode\n node_2["constants"]\n node_3["messages"]\n node_4["@stdlib/ownable.tact"]:::stdlibNode\n node_1 --\x3e node_2\n node_3 --\x3e node_2\n node_1 --\x3e node_3\n node_1 --\x3e node_4\n classDef contractNode fill:#90EE90,stroke:#333,stroke-width:2px;\n classDef stdlibNode fill:#FFFF80,stroke:#333,stroke-width:2px;\n'})}),"\n",(0,i.jsx)(n.p,{children:"Which will be rendered as:"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Mermaid Output",src:t(2479).A+"",width:"656",height:"414"})}),"\n",(0,i.jsx)(n.p,{children:"In this diagram:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Nodes"})," representing files that contain contracts are filled with green."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Edges"})," represent import relationships between files."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"You can paste this Mermaid code into the Mermaid Live Editor or view it directly in VS Code with the appropriate extension."}),"\n",(0,i.jsx)(n.h2,{id:"interpreting-the-import-graph",children:"Interpreting the Import Graph"}),"\n",(0,i.jsx)(n.p,{children:"The Import Graph shows how files in your project are interconnected through import statements. Each node represents a file, and each edge represents an import from one file to another."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Nodes"}),":","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Files containing contracts are highlighted (green in the examples)."}),"\n",(0,i.jsx)(n.li,{children:"Standard library files are highlighted differently (yellow) when included."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Edges"}),":","\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Directed edges show the import relationship (",(0,i.jsx)(n.code,{children:"A --\x3e B"})," means ",(0,i.jsx)(n.code,{children:"A"})," imports ",(0,i.jsx)(n.code,{children:"B"}),")."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Understanding the Import Graph can help you:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Identify unnecessary dependencies."}),"\n",(0,i.jsx)(n.li,{children:"Visualize the structure of your project."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,i.jsxs)(n.p,{children:["By utilizing the ",(0,i.jsx)(n.code,{children:"DumpImports"})," tool, developers can gain deeper insights into the dependency structure of their Tact projects, facilitating better project organization, dependency management, and code optimization."]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(c,{...e})}):c(e)}},2479:(e,n,t)=>{t.d(n,{A:()=>i});const i=t.p+"assets/images/dump-imports-mmd-455299aa0e63b065a70b166ab0597814.png"},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>d});var i=t(6540);const r={},s=i.createContext(r);function o(e){const n=i.useContext(s);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),i.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/faae61e5.0c385acd.js b/assets/js/faae61e5.0c385acd.js new file mode 100644 index 000000000..e55177a7f --- /dev/null +++ b/assets/js/faae61e5.0c385acd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[5859],{8714:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>o,contentTitle:()=>n,default:()=>x,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var d=s(4848),r=s(8453);const i={id:"detectors",title:"Detectors Overview"},n="Detectors Overview",c={id:"detectors",title:"Detectors Overview",description:"Built-in Detectors",source:"@site/docs/detectors.md",sourceDirName:".",slug:"/detectors",permalink:"/tools/misti/docs/next/detectors",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/detectors.md",tags:[],version:"current",frontMatter:{id:"detectors",title:"Detectors Overview"},sidebar:"sidebar",previous:{title:"Using with Blueprint",permalink:"/tools/misti/docs/next/tutorial/blueprint"},next:{title:"ArgCopyMutation",permalink:"/tools/misti/docs/next/detectors/ArgCopyMutation"}},o={},l=[{value:"Built-in Detectors",id:"built-in-detectors",level:2}];function h(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.R)(),...e.components};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(t.h1,{id:"detectors-overview",children:"Detectors Overview"}),"\n",(0,d.jsx)(t.h2,{id:"built-in-detectors",children:"Built-in Detectors"}),"\n",(0,d.jsxs)(t.table,{children:[(0,d.jsx)(t.thead,{children:(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.th,{children:"#"}),(0,d.jsx)(t.th,{children:"Detector"}),(0,d.jsx)(t.th,{children:"Severity"}),(0,d.jsx)(t.th,{children:"Requires Souffl\xe9"}),(0,d.jsx)(t.th,{children:"Enabled by default"})]})}),(0,d.jsxs)(t.tbody,{children:[(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"1"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/ArgCopyMutation",children:"ArgCopyMutation"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"2"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/AsmIsUsed",children:"AsmIsUsed"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"3"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/BranchDuplicate",children:"BranchDuplicate"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"4"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/CellOverflow",children:"CellOverflow"})}),(0,d.jsx)(t.td,{children:"Critical"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"5"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/ConstantAddress",children:"ConstantAddress"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"6"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/DivideBeforeMultiply",children:"DivideBeforeMultiply"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{children:"\u2714"}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"7"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/DumpIsUsed",children:"DumpIsUsed"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"8"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/DuplicatedCondition",children:"DuplicatedCondition"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"9"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/EnsurePrgSeed",children:"EnsurePrgSeed"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"10"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/FalseCondition",children:"FalseCondition"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"11"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/FieldDoubleInit",children:"FieldDoubleInit"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"12"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/InheritedStateMutation",children:"InheritedStateMutation"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"13"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/NeverAccessedVariables",children:"NeverAccessedVariables"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"14"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/OptimalMathFunction",children:"OptimalMathFunction"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"15"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/PreferAugmentedAssign",children:"PreferAugmentedAssign"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"16"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/PreferredStdlibApi",children:"PreferredStdlibApi"})}),(0,d.jsx)(t.td,{children:"Info"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"17"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/ReadOnlyVariables",children:"ReadOnlyVariables"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{children:"\u2714"}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"18"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/SendInLoop",children:"SendInLoop"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"19"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/ShortCircuitCondition",children:"ShortCircuitCondition"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"20"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/StringReceiversOverlap",children:"StringReceiversOverlap"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"21"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/SuspiciousMessageMode",children:"SuspiciousMessageMode"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"22"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/UnboundLoop",children:"UnboundLoop"})}),(0,d.jsx)(t.td,{children:"High"}),(0,d.jsx)(t.td,{children:"\u2714"}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"23"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/UnboundMap",children:"UnboundMap"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"24"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/UnusedExpressionResult",children:"UnusedExpressionResult"})}),(0,d.jsx)(t.td,{children:"Medium"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"25"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/UnusedOptional",children:"UnusedOptional"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]}),(0,d.jsxs)(t.tr,{children:[(0,d.jsx)(t.td,{children:"26"}),(0,d.jsx)(t.td,{children:(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/detectors/ZeroAddress",children:"ZeroAddress"})}),(0,d.jsx)(t.td,{children:"Low"}),(0,d.jsx)(t.td,{}),(0,d.jsx)(t.td,{children:"\u2714"})]})]})]}),"\n",(0,d.jsxs)(t.p,{children:["Some of the detectors require ",(0,d.jsx)(t.a,{href:"https://souffle-lang.github.io/install",children:"Souffl\xe9"})," to be installed. If no Souffl\xe9 installation is found, these detectors won't be executed."]}),"\n",(0,d.jsxs)(t.p,{children:["A few detectors are optional and aimed at auditors to help uncover subtle issues in the source code. To enable all detectors, use the ",(0,d.jsx)(t.code,{children:"--all-detectors"})," option. You can find a full list of configuration options on the ",(0,d.jsx)(t.a,{href:"/tools/misti/docs/next/tutorial/configuration",children:"configuration page"}),"."]}),"\n",(0,d.jsx)(t.p,{children:"Each detector targets a specific type of problem in your code. Click on the detector name to learn more."})]})}function x(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,d.jsx)(t,{...e,children:(0,d.jsx)(h,{...e})}):h(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>n,x:()=>c});var d=s(6540);const r={},i=d.createContext(r);function n(e){const t=d.useContext(i);return d.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:n(e.components),d.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fafa7ec8.f8fc7c04.js b/assets/js/fafa7ec8.f8fc7c04.js new file mode 100644 index 000000000..845a67ed1 --- /dev/null +++ b/assets/js/fafa7ec8.f8fc7c04.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[4330],{706:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>c,contentTitle:()=>d,default:()=>h,frontMatter:()=>o,metadata:()=>r,toc:()=>a});var n=s(4848),i=s(8453);const o={},d="dump Is Used",r={id:"detectors/DumpIsUsed",title:"dump Is Used",description:"An optional detector that highlights all the dump function calls.",source:"@site/versioned_docs/version-0.2.2/detectors/DumpIsUsed.md",sourceDirName:"detectors",slug:"/detectors/DumpIsUsed",permalink:"/tools/misti/docs/0.2.2/detectors/DumpIsUsed",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/detectors/DumpIsUsed.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Branch Duplicate",permalink:"/tools/misti/docs/0.2.2/detectors/BranchDuplicate"},next:{title:"Field Initialized Twice",permalink:"/tools/misti/docs/0.2.2/detectors/FieldDoubleInit"}},c={},a=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsxs)(t.h1,{id:"dump-is-used",children:[(0,n.jsx)(t.code,{children:"dump"})," Is Used"]}),"\n",(0,n.jsxs)(t.p,{children:["An optional detector that highlights all the ",(0,n.jsx)(t.code,{children:"dump"})," function calls."]}),"\n",(0,n.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,n.jsxs)(t.p,{children:["The ",(0,n.jsx)(t.code,{children:"dump"})," function is a debug print that shouldn't be in the final code. Even though the compiler removes it in production, its presence suggests the developer was debugging something. This can flag areas where issues might exist, so auditors should take a closer look at these parts of the code."]}),"\n",(0,n.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = (RANDOM_SEED >> half_shift) &\n (MAGIC_CONSTANT << DIVIDE_BY_TWO) ^ shift_mask;\n dump(combined); // Suspicious: Highlighted by the detector\n}\n"})}),"\n",(0,n.jsx)(t.p,{children:"Use instead:"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-tact",children:"fun test(): Int {\n // ... other computations\n let combined: Int = this.seed ^ shift_mask\n // OK: The code was reviewed and simplified; `dump` was removed\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(l,{...e})}):l(e)}},8453:(e,t,s)=>{s.d(t,{R:()=>d,x:()=>r});var n=s(6540);const i={},o=n.createContext(i);function d(e){const t=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:d(e.components),n.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fbbe250b.0abc4220.js b/assets/js/fbbe250b.0abc4220.js new file mode 100644 index 000000000..1c0d36f96 --- /dev/null +++ b/assets/js/fbbe250b.0abc4220.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[7173],{3034:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var s=i(4848),t=i(8453);const o={},r="Configuration",l={id:"tutorial/configuration",title:"Configuration",description:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set.",source:"@site/docs/tutorial/configuration.md",sourceDirName:"tutorial",slug:"/tutorial/configuration",permalink:"/tools/misti/docs/next/tutorial/configuration",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/docs/tutorial/configuration.md",tags:[],version:"current",frontMatter:{},sidebar:"sidebar",previous:{title:"Command-Line Interface",permalink:"/tools/misti/docs/next/tutorial/cli"},next:{title:"Using with Blueprint",permalink:"/tools/misti/docs/next/tutorial/blueprint"}},a={},c=[{value:"Configuration Options",id:"configuration-options",level:3},{value:"Running Misti with Configuration",id:"running-misti-with-configuration",level:2},{value:"Default Configuration File",id:"default-configuration-file",level:2},{value:"Environment Variables",id:"environment-variables",level:2},{value:"Getting Help",id:"getting-help",level:2}];function d(e){const n={a:"a",br:"br",code:"code",h1:"h1",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"configuration",children:"Configuration"}),"\n",(0,s.jsx)(n.p,{children:"This guide provides an example of the JSON configuration file for Misti, detailing the possible options you can set."}),"\n",(0,s.jsx)(n.h3,{id:"configuration-options",children:"Configuration Options"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"detectors"})," (array of objects, optional): List of detectors to run. Each detector can be specified with a ",(0,s.jsx)(n.code,{children:"className"})," and optionally a ",(0,s.jsx)(n.code,{children:"modulePath"})," if it\u2019s a custom detector."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"className"})," (string, required): The class name of the detector."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"modulePath"})," (string, optional): The file path of the detector module if it's a custom implementation."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"tools"})," (array of objects, optional): List of tools to enable, each with its own configuration."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"className"})," (string, required): The class name of the tool."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"options"})," (object, optional): Key-value configuration options for the tool."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"suppressions"})," (array of objects, optional): A list of suppressions for warnings."]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"detector"})," (string, required): The detector to suppress warnings for."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"position"})," (string, required): The position in the code where the warning should be suppressed."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"ignoredProjects"})," (array of strings, optional): List of Tact projects to ignore during analysis."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"soufflePath"})," (string, optional): Directory to save generated Souffl\xe9 files, useful for debugging purposes. If not set, a temporary directory will be used."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"souffleVerbose"})," (boolean, optional): If set, generates more readable Souffl\xe9 files instead of optimizing the output for size."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"tactStdlibPath"})," (string, optional): Path to the Tact standard library. If not set, the default standard library from the active Tact setup will be used."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"unusedPrefix"}),' (string, default: "_"): Identifiers starting with this prefix won\'t be reported as unused by the built-in detectors.']}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"verbosity"}),' (string, optional, default: "default"): Verbosity level of the logs. Possible values are ',(0,s.jsx)(n.code,{children:"quiet"}),", ",(0,s.jsx)(n.code,{children:"debug"}),", and ",(0,s.jsx)(n.code,{children:"default"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"running-misti-with-configuration",children:"Running Misti with Configuration"}),"\n",(0,s.jsx)(n.p,{children:"To run Misti with the specified configuration file, use the following command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"misti --config path/to/mistiConfig.json test/projects/simple/tactConfig.json\n"})}),"\n",(0,s.jsx)(n.p,{children:"This command tells Misti to use the provided configuration file to analyze the specified Tact project configuration."}),"\n",(0,s.jsx)(n.h2,{id:"default-configuration-file",children:"Default Configuration File"}),"\n",(0,s.jsx)(n.p,{children:"By default, Misti enables all built-in detectors. Below is an example of the default configuration file:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "detectors": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n { "className": "BranchDuplicate" },\n { "className": "FieldDoubleInit" },\n { "className": "PreferAugmentedAssign" },\n { "className": "StringReceiversOverlap" },\n { "className": "ArgCopyMutation" }\n ],\n "ignoredProjects": [],\n "soufflePath": "/tmp/misti/souffle",\n "souffleVerbose": false,\n "unusedPrefix": "_",\n "verbosity": "default"\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["All the built-in detectors are enabled by default. You can find the complete configuration schema and default configuration file on GitHub: ",(0,s.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/configSchema.json",children:"configSchema.json"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["You can always dump the Misti configuration file in use by passing the ",(0,s.jsx)(n.code,{children:"--dump-config"})," option in the CLI:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"misti --dump-config path/to/your/tact.config.json\n"})}),"\n",(0,s.jsx)(n.p,{children:"If there is no Misti config in the directory, Misti dumps the default config. This can be used to adjust it, such as adding or suppressing some detectors."}),"\n",(0,s.jsx)(n.h2,{id:"environment-variables",children:"Environment Variables"}),"\n",(0,s.jsx)(n.p,{children:"Misti offers advanced configuration through environment variables to control specific options."}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"MISTI_TIMEOUT"})}),(0,s.jsx)(n.br,{}),"\n","Sets the timeout for detector execution in milliseconds.",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"15000"}),(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Example"}),":","\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"export MISTI_TIMEOUT=20000\n"})}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:(0,s.jsx)(n.code,{children:"MISTI_TRACE"})}),(0,s.jsx)(n.br,{}),"\n","Enables tracing of the execution. Set to ",(0,s.jsx)(n.code,{children:"1"})," to enable tracing, otherwise it is disabled.",(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Default"}),": ",(0,s.jsx)(n.code,{children:"false"}),(0,s.jsx)(n.br,{}),"\n",(0,s.jsx)(n.strong,{children:"Example"}),":","\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"export MISTI_TRACE=1\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"getting-help",children:"Getting Help"}),"\n",(0,s.jsxs)(n.p,{children:["If you need assistance or encounter any issues, please create an issue on GitHub at ",(0,s.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"nowarp/misti"})," or ask in the ",(0,s.jsx)(n.a,{href:"https://t.me/misti_dev",children:"Misti Telegram group"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>r,x:()=>l});var s=i(6540);const t={},o=s.createContext(t);function r(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fcd86191.e1395157.js b/assets/js/fcd86191.e1395157.js new file mode 100644 index 000000000..b0cf64236 --- /dev/null +++ b/assets/js/fcd86191.e1395157.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6752],{6493:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>s,default:()=>u,frontMatter:()=>i,metadata:()=>c,toc:()=>d});var o=n(4848),r=n(8453);const i={},s="Custom Detector Guide",c={id:"hacking/custom-detector",title:"Custom Detector Guide",description:"Introduction",source:"@site/versioned_docs/version-0.2.2/hacking/custom-detector.md",sourceDirName:"hacking",slug:"/hacking/custom-detector",permalink:"/tools/misti/docs/0.2.2/hacking/custom-detector",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.2/hacking/custom-detector.md",tags:[],version:"0.2.2",frontMatter:{},sidebar:"sidebar",previous:{title:"Tools",permalink:"/tools/misti/docs/0.2.2/hacking/tools"}},a={},d=[{value:"Introduction",id:"introduction",level:2},{value:"Writing a Detector",id:"writing-a-detector",level:2},{value:"Example Detectors",id:"example-detectors",level:2}];function l(e){const t={a:"a",code:"code",h1:"h1",h2:"h2",p:"p",pre:"pre",...(0,r.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(t.h1,{id:"custom-detector-guide",children:"Custom Detector Guide"}),"\n",(0,o.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,o.jsxs)(t.p,{children:["Misti provides an API to write custom detectors, allowing you to implement your own linting rules. These custom detectors enable you to identify specific issues in your codebase, much like other static analysis tools. The API reference can be found here: ",(0,o.jsx)(t.a,{href:"https://nowarp.github.io/tools/misti/api/",children:"Misti API Reference"}),"."]}),"\n",(0,o.jsxs)(t.p,{children:["Detectors are designed to be dynamically loaded by the Misti driver, and they are present by TypeScript classes that implement the ",(0,o.jsx)(t.a,{href:"https://nowarp.github.io/tools/misti/api/classes/detectors_detector.Detector.html",children:(0,o.jsx)(t.code,{children:"Detector"})})," interface."]}),"\n",(0,o.jsx)(t.h2,{id:"writing-a-detector",children:"Writing a Detector"}),"\n",(0,o.jsx)(t.p,{children:"To write a custom detector, create a TypeScript file using the Misti API. Here's an example of how to implement a custom detector:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{className:"language-typescript",children:'import { Detector } from "../../src/detectors/detector";\nimport { MistiContext } from "../../src/internals/context";\nimport { CompilationUnit } from "../../src/internals/ir";\nimport {\n createError,\n MistiTactError,\n Severity,\n} from "../../src/internals/errors";\n\n/**\n * An example of a custom detector that showcases the usage of the detector API.\n *\n * It reports all the contracts that don\'t have an explicit implementation of the init function.\n */\nexport class ImplicitInit extends Detector {\n check(ctx: MistiContext, cu: CompilationUnit): MistiTactError[] {\n return Array.from(cu.contracts).reduce((foundErrors, [_, contract]) => {\n if (!cu.findMethodCFGByName(contract.name, "init")) {\n const err = createError(\n ctx,\n `contract ${contract.name} doesn\'t define an init function`,\n Severity.INFO,\n contract.ref,\n );\n foundErrors.push(err);\n }\n return foundErrors;\n }, [] as MistiTactError[]);\n }\n}\n'})}),"\n",(0,o.jsx)(t.p,{children:"After creating a detector, you need to specify it in your configuration. Update your Misti configuration file to include the path to your custom detector implementation, e.g.:"}),"\n",(0,o.jsx)(t.pre,{children:(0,o.jsx)(t.code,{children:'{\n "detectors": [\n { "className": "DivideBeforeMultiply" },\n { "className": "ReadOnlyVariables" },\n { "className": "NeverAccessedVariables" },\n { "className": "UnboundLoops" },\n { "className": "ZeroAddress" },\n\n { "className": "ImplicitInit", "modulePath": "/path/to/implicitInit.ts" }\n ],\n "ignored_projects": [],\n "verbosity": "default"\n}\n\n'})}),"\n",(0,o.jsxs)(t.p,{children:["After this, you could run the created detector specifying a path to it: ",(0,o.jsx)(t.code,{children:"--config path/to/mistiConfig.json test/projects/simple/tactConfig.json"}),"."]}),"\n",(0,o.jsx)(t.h2,{id:"example-detectors",children:"Example Detectors"}),"\n",(0,o.jsxs)(t.p,{children:["The best way to examine how to use the Misti API is to look at the example detectors. Navigate to the ",(0,o.jsx)(t.a,{href:"https://github.com/nowarp/misti/tree/master/examples",children:"examples directory"})," in the Misti repository to see how various detectors are implemented. Additionally, the built-in detectors are present in the project and are well-documented, providing further insight into writing effective custom detectors."]})]})}function u(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,o.jsx)(t,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>s,x:()=>c});var o=n(6540);const r={},i=o.createContext(r);function s(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function c(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/fe7c01fc.f82580ba.js b/assets/js/fe7c01fc.f82580ba.js new file mode 100644 index 000000000..dfdf3125b --- /dev/null +++ b/assets/js/fe7c01fc.f82580ba.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[6854],{7437:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>c,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>d});var s=n(4848),i=n(8453);const r={},c="BranchDuplicate",o={id:"detectors/BranchDuplicate",title:"BranchDuplicate",description:"Detector that reports duplicated code in conditional branches.",source:"@site/versioned_docs/version-0.3.0/detectors/BranchDuplicate.md",sourceDirName:"detectors",slug:"/detectors/BranchDuplicate",permalink:"/tools/misti/docs/0.3.0/detectors/BranchDuplicate",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.3.0/detectors/BranchDuplicate.md",tags:[],version:"0.3.0",frontMatter:{},sidebar:"sidebar",previous:{title:"AsmIsUsed",permalink:"/tools/misti/docs/0.3.0/detectors/AsmIsUsed"},next:{title:"ConstantAddress",permalink:"/tools/misti/docs/0.3.0/detectors/ConstantAddress"}},a={},d=[{value:"Why is it bad?",id:"why-is-it-bad",level:2},{value:"Example",id:"example",level:2}];function l(e){const t={code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"branchduplicate",children:"BranchDuplicate"}),"\n",(0,s.jsx)(t.p,{children:"Detector that reports duplicated code in conditional branches."}),"\n",(0,s.jsx)(t.h2,{id:"why-is-it-bad",children:"Why is it bad?"}),"\n",(0,s.jsx)(t.p,{children:"Duplicated code in branches is bad because it:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Reduces Readability"}),": Repetition makes the code harder to understand."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Increases Maintenance"}),": Changes must be made in multiple places, risking errors."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Signals Poor Design"}),": It suggests missed opportunities for cleaner, more abstract code."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"example",children:"Example"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = 43; // bad: duplicated code\n} else {\n a = 43;\n}\n"})}),"\n",(0,s.jsx)(t.p,{children:"Use instead:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-tact",children:"if (a > 42) {\n a = inc(b); // ok\n} else {\n a = 43;\n}\n"})})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(l,{...e})}):l(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>c,x:()=>o});var s=n(6540);const i={},r=s.createContext(i);function c(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:c(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/ff0db780.e64f7648.js b/assets/js/ff0db780.e64f7648.js new file mode 100644 index 000000000..df8869dc4 --- /dev/null +++ b/assets/js/ff0db780.e64f7648.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[1598],{4263:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>c,contentTitle:()=>o,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var t=i(4848),s=i(8453);const r={},o="Contributing Guide",a={id:"hacking/contributing",title:"Contributing Guide",description:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better.",source:"@site/versioned_docs/version-0.2.0/hacking/contributing.md",sourceDirName:"hacking",slug:"/hacking/contributing",permalink:"/tools/misti/docs/0.2.0/hacking/contributing",draft:!1,unlisted:!1,editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/versioned_docs/version-0.2.0/hacking/contributing.md",tags:[],version:"0.2.0",frontMatter:{},sidebar:"sidebar",previous:{title:"Prefer Augmented Assignment",permalink:"/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign"},next:{title:"Design Overview",permalink:"/tools/misti/docs/0.2.0/hacking/design"}},c={},d=[{value:"Issues reporting",id:"issues-reporting",level:2},{value:"Documentation contribution",id:"documentation-contribution",level:2},{value:"Code contribution",id:"code-contribution",level:2}];function l(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"contributing-guide",children:"Contributing Guide"}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your interest in contributing to Misti. This guide provides the information you need to start, from reporting issues to coding and documentation. Your participation makes this project better."}),"\n",(0,t.jsx)(n.h2,{id:"issues-reporting",children:"Issues reporting"}),"\n",(0,t.jsx)(n.p,{children:"When Misti encounters an error and crashes, it generates a report and saves it to a file, displaying a message similar to the following:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{children:"The error report was saved to the file: /tmp/misti/reports/2024-07-29T08-48-59-308Z.txt.\nPlease help us by publishing it and the input sources at:\nhttps://github.com/nowarp/misti/issues/new.\n"})}),"\n",(0,t.jsx)(n.p,{children:"We encourage you to report these issues as it helps improve the project and enhances the tool's reliability for everyone. Sharing these reports ensures that we can address and fix problems promptly, benefiting all users."}),"\n",(0,t.jsx)(n.h2,{id:"documentation-contribution",children:"Documentation contribution"}),"\n",(0,t.jsxs)(n.p,{children:["We welcome contributions to our documentation. If you find areas that need improvement or clarification, feel free to edit, add, or suggest changes. You can create new issues related to documentation in our docs repository: ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/nowarp.github.io/issues",children:"nowarp.github.io Issues"}),". Additionally, many documentation pages have an ",(0,t.jsx)(n.code,{children:"Edit"})," button that allows you to make direct contributions easily."]}),"\n",(0,t.jsx)(n.h2,{id:"code-contribution",children:"Code contribution"}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Navigate Issues and Find Tasks"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Browse the issues ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/issues",children:"here"}),". Sometimes, it can be beneficial to find TODOs in the source code and tests for easy issues."]}),"\n",(0,t.jsx)(n.li,{children:"Choose an issue suitable for you and mention in the issue that you're working on it."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Implement Your Changes"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Implement your changes. Feel free to ask questions in the issue if needed."}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Ensure Tests Pass"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Before creating a PR, make sure all tests and CI checks are passing by running:","\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"yarn test-all\n"})}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Create a PR"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Submit your pull request ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/pulls",children:"here"})]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.li,{children:["\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.strong,{children:"Add a CHANGELOG entry"})}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:["Describe your changes in the ",(0,t.jsx)(n.code,{children:"CHANGELOG.md"})," file according to the existing structure."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["All guidelines and additional hacking tips are available in the repo. For low-level details not present in the docs, refer to ",(0,t.jsx)(n.a,{href:"https://github.com/nowarp/misti/blob/master/HACKING.md",children:"HACKING.md"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Thank you for your contributions!"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>o,x:()=>a});var t=i(6540);const s={},r=t.createContext(s);function o(e){const n=t.useContext(r);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:o(e.components),t.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/assets/js/main.ebcc6cf7.js b/assets/js/main.ebcc6cf7.js new file mode 100644 index 000000000..883c88eac --- /dev/null +++ b/assets/js/main.ebcc6cf7.js @@ -0,0 +1,2 @@ +/*! For license information please see main.ebcc6cf7.js.LICENSE.txt */ +(self.webpackChunknowarp_github_io=self.webpackChunknowarp_github_io||[]).push([[8792],{8328:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});n(6540);var o=n(3259),r=n.n(o),i=n(4054);const s={"012e8e66":[()=>n.e(8700).then(n.bind(n,7337)),"@site/docs/tools/DumpConfig.md",7337],"01419b1f":[()=>n.e(4371).then(n.bind(n,4622)),"@site/versioned_docs/version-0.2.0/tutorial/getting-started.md",4622],"03b4256a":[()=>n.e(7354).then(n.t.bind(n,2682,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-4-0-43f.json",2682],"0600087e":[()=>n.e(9713).then(n.bind(n,8078)),"@site/versioned_docs/version-0.5/detectors/ZeroAddress.md",8078],"06bf7bd2":[()=>n.e(804).then(n.bind(n,6538)),"@site/versioned_docs/version-0.2.2/hacking/tools.md",6538],"070671b7":[()=>n.e(8607).then(n.bind(n,3620)),"@site/docs/detectors/PreferAugmentedAssign.md",3620],"07f2fad9":[()=>n.e(3462).then(n.bind(n,8092)),"@site/versioned_docs/version-0.3.0/index.md",8092],"0ac52da9":[()=>n.e(7702).then(n.bind(n,8288)),"@site/versioned_docs/version-0.3.1/tutorial/configuration.md",8288],"0b705376":[()=>n.e(2903).then(n.bind(n,9153)),"@site/versioned_docs/version-0.3.1/detectors/AsmIsUsed.md",9153],"0c390d31":[()=>n.e(1200).then(n.bind(n,934)),"@site/versioned_docs/version-0.4.0/tutorial/cli.md",934],"0c3de8e2":[()=>n.e(4875).then(n.bind(n,9689)),"@site/docs/detectors/InheritedStateMutation.md",9689],"0c8d0168":[()=>n.e(607).then(n.bind(n,5843)),"@site/docs/tutorial/blueprint.md",5843],"0e4e7ef7":[()=>n.e(1070).then(n.bind(n,2210)),"@site/versioned_docs/version-0.4.0/tutorial/configuration.md",2210],"0f37fc5e":[()=>n.e(9692).then(n.bind(n,7141)),"@site/docs/detectors/StringReceiversOverlap.md",7141],"0fb6ae9c":[()=>n.e(5983).then(n.bind(n,5091)),"@site/docs/hacking/souffle.md",5091],"104c66c9":[()=>n.e(6695).then(n.bind(n,1806)),"@site/versioned_docs/version-0.2.1/detectors/ZeroAddress.md",1806],"110db9ee":[()=>n.e(8164).then(n.bind(n,5547)),"@site/versioned_docs/version-0.5/detectors/UnboundMap.md",5547],"122f6b32":[()=>n.e(25).then(n.bind(n,9648)),"@site/versioned_docs/version-0.3.0/detectors/DivideBeforeMultiply.md",9648],"1295da86":[()=>n.e(559).then(n.bind(n,7413)),"@site/versioned_docs/version-0.3.1/tutorial/blueprint.md",7413],"129b217c":[()=>n.e(5422).then(n.bind(n,4558)),"@site/versioned_docs/version-0.5/detectors/AsmIsUsed.md",4558],"138db073":[()=>n.e(1519).then(n.bind(n,3331)),"@site/docs/detectors/AsmIsUsed.md",3331],"1418388c":[()=>n.e(8917).then(n.bind(n,0)),"@site/versioned_docs/version-0.2.1/hacking/custom-detector.md",0],"150b97d9":[()=>n.e(1258).then(n.bind(n,7254)),"@site/versioned_docs/version-0.4.0/tools.md",7254],"1598dd73":[()=>n.e(8708).then(n.bind(n,4661)),"@site/versioned_docs/version-0.1.2/tutorial/configuration.md",4661],"15d13f14":[()=>n.e(3884).then(n.bind(n,6662)),"@site/versioned_docs/version-0.2.1/hacking/contributing.md",6662],"17406c9d":[()=>n.e(8513).then(n.bind(n,1027)),"@site/versioned_docs/version-0.3.0/detectors/ReadOnlyVariables.md",1027],17896441:[()=>Promise.all([n.e(1869),n.e(3658),n.e(8401)]).then(n.bind(n,6365)),"@theme/DocItem",6365],"1869ccd1":[()=>n.e(9108).then(n.bind(n,9400)),"@site/versioned_docs/version-0.2.2/detectors/PreferAugmentedAssign.md",9400],"1a2cd3da":[()=>n.e(4006).then(n.bind(n,3020)),"@site/versioned_docs/version-0.5/detectors/ConstantAddress.md",3020],"1a50d306":[()=>n.e(6999).then(n.bind(n,5669)),"@site/versioned_docs/version-0.3.1/detectors/NeverAccessedVariables.md",5669],"1a8310a1":[()=>n.e(7743).then(n.bind(n,9881)),"@site/versioned_docs/version-0.4.0/hacking/contributing.md",9881],"1b73222b":[()=>n.e(3420).then(n.t.bind(n,5274,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-3-0-3f9.json",5274],"1b960128":[()=>n.e(8920).then(n.bind(n,3265)),"@site/versioned_docs/version-0.4.0/tools/DumpConfig.md",3265],"1c26cb06":[()=>n.e(5602).then(n.bind(n,8164)),"@site/versioned_docs/version-0.2.2/tutorial/ci-cd.md",8164],"1df93b7f":[()=>n.e(4583).then(n.bind(n,6866)),"@site/src/pages/index.tsx",6866],"1f391b9e":[()=>Promise.all([n.e(1869),n.e(3658),n.e(6061)]).then(n.bind(n,7973)),"@theme/MDXPage",7973],"2018b81b":[()=>n.e(7677).then(n.bind(n,6964)),"@site/versioned_docs/version-0.3.0/tutorial/blueprint.md",6964],"2257d06b":[()=>n.e(1687).then(n.bind(n,111)),"@site/versioned_docs/version-0.2.1/detectors.md",111],"230b3a10":[()=>n.e(3031).then(n.bind(n,3940)),"@site/versioned_docs/version-0.5/detectors/CellOverflow.md",3940],"23b0c962":[()=>n.e(6784).then(n.bind(n,7838)),"@site/docs/tutorial/cli.md",7838],"2424092d":[()=>n.e(420).then(n.bind(n,512)),"@site/versioned_docs/version-0.2.0/detectors/ReadOnlyVariables.md",512],"24652b08":[()=>n.e(7406).then(n.bind(n,2208)),"@site/versioned_docs/version-0.2.0/detectors/DumpIsUsed.md",2208],"24ab0ec7":[()=>n.e(9439).then(n.bind(n,2592)),"@site/docs/detectors/SuspiciousMessageMode.md",2592],"25eb63f7":[()=>n.e(6941).then(n.bind(n,2637)),"@site/versioned_docs/version-0.5/detectors/DumpIsUsed.md",2637],"26592ea2":[()=>n.e(3543).then(n.bind(n,3178)),"@site/docs/detectors/FieldDoubleInit.md",3178],"26b19808":[()=>n.e(3339).then(n.bind(n,8267)),"@site/versioned_docs/version-0.5/detectors/FieldDoubleInit.md",8267],"273168fb":[()=>n.e(1492).then(n.bind(n,7079)),"@site/versioned_docs/version-0.1.2/tutorial/getting-started.md",7079],"2aa59687":[()=>n.e(3196).then(n.bind(n,542)),"@site/versioned_docs/version-0.3.1/tutorial/ci-cd.md",542],"2ace25e9":[()=>n.e(4013).then(n.bind(n,5111)),"@site/versioned_docs/version-0.2.1/hacking/tools.md",5111],"2b6a80d0":[()=>n.e(1084).then(n.bind(n,3646)),"@site/docs/detectors/DumpIsUsed.md",3646],"2b785902":[()=>n.e(4806).then(n.bind(n,2814)),"@site/docs/tools.md",2814],"2bdf0f82":[()=>n.e(321).then(n.bind(n,3842)),"@site/versioned_docs/version-0.1.2/hacking/CHANGELOG.md",3842],"2c038e81":[()=>n.e(7393).then(n.bind(n,3268)),"@site/docs/detectors/UnboundMap.md",3268],"2c17c501":[()=>n.e(23).then(n.bind(n,2458)),"@site/versioned_docs/version-0.5/detectors/ArgCopyMutation.md",2458],"2cebbb1e":[()=>n.e(5345).then(n.bind(n,730)),"@site/versioned_docs/version-0.3.1/detectors/PreferAugmentedAssign.md",730],"2d07d137":[()=>n.e(5097).then(n.bind(n,6097)),"@site/versioned_docs/version-0.2.0/detectors/DivideBeforeMultiply.md",6097],"2f30e490":[()=>n.e(1638).then(n.bind(n,2380)),"@site/versioned_docs/version-0.2.1/detectors/DivideBeforeMultiply.md",2380],"2fbff8b1":[()=>n.e(1330).then(n.bind(n,3832)),"@site/versioned_docs/version-0.5/tools/DumpImports.md",3832],"304edb56":[()=>n.e(4088).then(n.bind(n,8271)),"@site/docs/detectors/ArgCopyMutation.md",8271],"30835b52":[()=>n.e(6269).then(n.bind(n,3116)),"@site/versioned_docs/version-0.5/detectors/DivideBeforeMultiply.md",3116],"322eba7d":[()=>n.e(1193).then(n.bind(n,1535)),"@site/versioned_docs/version-0.5/detectors.md",1535],"35d1ab0d":[()=>n.e(4787).then(n.bind(n,1322)),"@site/versioned_docs/version-0.5/tools/DumpAst.md",1322],"36ebdf3e":[()=>n.e(7787).then(n.bind(n,7162)),"@site/versioned_docs/version-0.1.2/detectors/ZeroAddress.md",7162],"377c4f81":[()=>n.e(3448).then(n.bind(n,235)),"@site/versioned_docs/version-0.3.0/hacking/tools.md",235],"393be207":[()=>n.e(4134).then(n.bind(n,633)),"@site/src/pages/markdown-page.md",633],"3b3a1a75":[()=>n.e(2478).then(n.bind(n,4727)),"@site/versioned_docs/version-0.4.0/detectors/ArgCopyMutation.md",4727],"3bfe497f":[()=>n.e(5381).then(n.bind(n,4512)),"@site/versioned_docs/version-0.4.0/detectors/DivideBeforeMultiply.md",4512],"3c9b1461":[()=>n.e(3988).then(n.bind(n,849)),"@site/versioned_docs/version-0.5/detectors/PreferAugmentedAssign.md",849],"3db5102b":[()=>n.e(6774).then(n.bind(n,6931)),"@site/versioned_docs/version-0.2.1/tutorial/ci-cd.md",6931],"40440f59":[()=>n.e(5671).then(n.bind(n,8246)),"@site/versioned_docs/version-0.5/hacking/contributing.md",8246],"40be7dfa":[()=>n.e(6602).then(n.bind(n,7991)),"@site/versioned_docs/version-0.2.0/index.md",7991],"42510f93":[()=>n.e(2913).then(n.bind(n,5875)),"@site/versioned_docs/version-0.4.0/hacking/developing-misti.md",5875],"432cb5a5":[()=>n.e(3840).then(n.bind(n,4303)),"@site/versioned_docs/version-0.4.0/hacking/design.md",4303],"43c93918":[()=>n.e(1299).then(n.bind(n,955)),"@site/versioned_docs/version-0.3.1/index.md",955],"4518efa7":[()=>n.e(6544).then(n.bind(n,2308)),"@site/versioned_docs/version-0.2.2/detectors/BranchDuplicate.md",2308],"4624921c":[()=>n.e(9510).then(n.bind(n,9567)),"@site/versioned_docs/version-0.5/detectors/ReadOnlyVariables.md",9567],"46947df5":[()=>n.e(4992).then(n.bind(n,1904)),"@site/versioned_docs/version-0.5/detectors/EnsurePrgSeed.md",1904],"474ce197":[()=>n.e(4069).then(n.t.bind(n,7715,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-2-1-a64.json",7715],49256311:[()=>n.e(2734).then(n.bind(n,9475)),"@site/versioned_docs/version-0.3.1/detectors/ConstantAddress.md",9475],"4ab26116":[()=>n.e(9276).then(n.bind(n,1857)),"@site/versioned_docs/version-0.4.0/detectors/ConstantAddress.md",1857],"4b89306f":[()=>n.e(6769).then(n.bind(n,1821)),"@site/versioned_docs/version-0.3.1/hacking/souffle.md",1821],"4d74b396":[()=>n.e(9802).then(n.bind(n,1167)),"@site/versioned_docs/version-0.2.1/detectors/ReadOnlyVariables.md",1167],"4f2bb7ce":[()=>n.e(6156).then(n.bind(n,8867)),"@site/versioned_docs/version-0.3.1/hacking/custom-detector.md",8867],"4fd06f05":[()=>n.e(6948).then(n.bind(n,7402)),"@site/versioned_docs/version-0.2.0/tutorial/ci-cd.md",7402],"51fe41a6":[()=>n.e(8290).then(n.bind(n,723)),"@site/versioned_docs/version-0.4.0/detectors/NeverAccessedVariables.md",723],"53023ca8":[()=>n.e(2712).then(n.bind(n,4228)),"@site/versioned_docs/version-0.5/detectors/NeverAccessedVariables.md",4228],"54df6b9c":[()=>n.e(8962).then(n.bind(n,7852)),"@site/versioned_docs/version-0.5/detectors/DuplicatedCondition.md",7852],"55e1201d":[()=>n.e(8422).then(n.bind(n,2165)),"@site/docs/detectors/OptimalMathFunction.md",2165],"563af34e":[()=>n.e(3890).then(n.bind(n,1410)),"@site/versioned_docs/version-0.3.0/detectors/StringReceiversOverlap.md",1410],"566d8483":[()=>n.e(6551).then(n.bind(n,5437)),"@site/versioned_docs/version-0.2.2/index.md",5437],"5815e0d3":[()=>n.e(186).then(n.bind(n,9644)),"@site/versioned_docs/version-0.2.0/tutorial/configuration.md",9644],59016342:[()=>n.e(6751).then(n.bind(n,9027)),"@site/versioned_docs/version-0.4.0/detectors/UnusedOptional.md",9027],"5a7ecd5b":[()=>n.e(1417).then(n.bind(n,26)),"@site/versioned_docs/version-0.3.0/detectors/ZeroAddress.md",26],"5c07db7d":[()=>n.e(4575).then(n.bind(n,342)),"@site/versioned_docs/version-0.5/detectors/InheritedStateMutation.md",342],"5e95c892":[()=>n.e(9647).then(n.bind(n,7121)),"@theme/DocsRoot",7121],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,4784)),"@generated/docusaurus.config",4784],"5ec2195c":[()=>n.e(9708).then(n.bind(n,1484)),"@site/versioned_docs/version-0.2.1/detectors/ConstantAddress.md",1484],"602c5d84":[()=>n.e(4719).then(n.bind(n,8930)),"@site/versioned_docs/version-0.4.0/detectors/FieldDoubleInit.md",8930],"61c19607":[()=>n.e(5794).then(n.bind(n,8628)),"@site/versioned_docs/version-0.2.2/tutorial/getting-started.md",8628],"6362ac9f":[()=>n.e(9431).then(n.bind(n,2219)),"@site/versioned_docs/version-0.4.0/tutorial/blueprint.md",2219],"63a541b5":[()=>n.e(5122).then(n.bind(n,1105)),"@site/versioned_docs/version-0.3.1/detectors/ArgCopyMutation.md",1105],"63bb535a":[()=>n.e(3684).then(n.bind(n,3494)),"@site/versioned_docs/version-0.4.0/detectors/PreferredStdlibApi.md",3494],"6696f09b":[()=>n.e(9417).then(n.bind(n,1469)),"@site/versioned_docs/version-0.4.0/tools/DumpCfg.md",1469],"6934ebe4":[()=>n.e(3175).then(n.bind(n,4919)),"@site/versioned_docs/version-0.3.0/tutorial/ci-cd.md",4919],"693ffdbc":[()=>n.e(1204).then(n.bind(n,7567)),"@site/versioned_docs/version-0.2.2/hacking/souffle.md",7567],"6afbdc7c":[()=>n.e(4701).then(n.bind(n,6400)),"@site/versioned_docs/version-0.5/hacking/custom-detector.md",6400],"6bb9ad58":[()=>n.e(9448).then(n.bind(n,693)),"@site/versioned_docs/version-0.5/tutorial/cli.md",693],"6bfbb660":[()=>n.e(5173).then(n.bind(n,2963)),"@site/versioned_docs/version-0.5/tutorial/ci-cd.md",2963],"6f277b0e":[()=>n.e(6340).then(n.bind(n,701)),"@site/versioned_docs/version-0.2.2/detectors/UnboundLoops.md",701],"6f60ccd2":[()=>n.e(4861).then(n.bind(n,3316)),"@site/versioned_docs/version-0.3.1/detectors/ReadOnlyVariables.md",3316],"719e5d48":[()=>n.e(106).then(n.bind(n,4878)),"@site/versioned_docs/version-0.4.0/detectors/ReadOnlyVariables.md",4878],"72b7ad48":[()=>n.e(2378).then(n.bind(n,6878)),"@site/versioned_docs/version-0.2.1/detectors/UnboundLoops.md",6878],"740c342d":[()=>n.e(4910).then(n.bind(n,8670)),"@site/versioned_docs/version-0.5/tools/DumpConfig.md",8670],"743bfbca":[()=>n.e(121).then(n.bind(n,3372)),"@site/versioned_docs/version-0.1.2/hacking/custom-detector.md",3372],"7499c02a":[()=>n.e(3150).then(n.bind(n,4019)),"@site/versioned_docs/version-0.4.0/detectors/BranchDuplicate.md",4019],"754ccd45":[()=>n.e(3304).then(n.bind(n,1643)),"@site/docs/hacking/developing-misti.md",1643],76268162:[()=>n.e(7005).then(n.bind(n,1943)),"@site/versioned_docs/version-0.2.0/detectors/UnboundLoops.md",1943],"770027e6":[()=>n.e(7709).then(n.bind(n,4951)),"@site/versioned_docs/version-0.5/detectors/UnusedExpressionResult.md",4951],"773c7ee4":[()=>n.e(1564).then(n.bind(n,9113)),"@site/versioned_docs/version-0.2.0/hacking/souffle.md",9113],"775287ab":[()=>n.e(8342).then(n.bind(n,1402)),"@site/versioned_docs/version-0.1.2/hacking/contributing.md",1402],"776efca7":[()=>n.e(7151).then(n.bind(n,1883)),"@site/versioned_docs/version-0.3.1/detectors/StringReceiversOverlap.md",1883],"7b5b3cc2":[()=>n.e(6612).then(n.bind(n,8962)),"@site/versioned_docs/version-0.3.0/detectors/InheritedStateMutation.md",8962],"8078ad78":[()=>n.e(6208).then(n.bind(n,210)),"@site/versioned_docs/version-0.5/detectors/FalseCondition.md",210],"81087c81":[()=>n.e(6869).then(n.bind(n,2140)),"@site/versioned_docs/version-0.3.0/hacking/custom-detector.md",2140],"8272dc48":[()=>n.e(1529).then(n.bind(n,2184)),"@site/versioned_docs/version-0.2.0/hacking/tools.md",2184],"8306354c":[()=>n.e(7877).then(n.bind(n,9164)),"@site/versioned_docs/version-0.4.0/detectors/PreferAugmentedAssign.md",9164],"844f22a2":[()=>n.e(5316).then(n.bind(n,9095)),"@site/versioned_docs/version-0.3.0/tutorial/getting-started.md",9095],"866ed13d":[()=>n.e(6974).then(n.bind(n,9515)),"@site/docs/detectors/ZeroAddress.md",9515],"8685a76e":[()=>n.e(3583).then(n.bind(n,3950)),"@site/versioned_docs/version-0.5/hacking/souffle.md",3950],"86d22c3d":[()=>n.e(1407).then(n.t.bind(n,5012,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-653.json",5012],"86d70222":[()=>n.e(3812).then(n.bind(n,2759)),"@site/versioned_docs/version-0.2.0/hacking/custom-detector.md",2759],"87ce9660":[()=>n.e(7495).then(n.bind(n,7049)),"@site/versioned_docs/version-0.2.0/detectors/ZeroAddress.md",7049],"883df8cc":[()=>n.e(7238).then(n.bind(n,6395)),"@site/docs/detectors/DivideBeforeMultiply.md",6395],"888071ca":[()=>n.e(9187).then(n.bind(n,903)),"@site/docs/detectors/ShortCircuitCondition.md",903],"8c01191f":[()=>n.e(494).then(n.bind(n,1017)),"@site/versioned_docs/version-0.2.0/detectors/NeverAccessedVariables.md",1017],"8c0243db":[()=>n.e(7839).then(n.bind(n,9520)),"@site/versioned_docs/version-0.1.2/detectors/DivideBeforeMultiply.md",9520],"8c74c05e":[()=>n.e(9198).then(n.bind(n,8981)),"@site/versioned_docs/version-0.2.0/hacking/design.md",8981],"8c9dd45b":[()=>n.e(6286).then(n.bind(n,7579)),"@site/versioned_docs/version-0.2.2/hacking/design.md",7579],"8cf7c613":[()=>n.e(6274).then(n.bind(n,2234)),"@site/versioned_docs/version-0.3.1/tutorial/getting-started.md",2234],"8d6fa39c":[()=>n.e(2187).then(n.bind(n,453)),"@site/versioned_docs/version-0.2.2/detectors/ConstantAddress.md",453],"8d91c04d":[()=>n.e(4024).then(n.bind(n,2850)),"@site/versioned_docs/version-0.3.0/detectors/UnboundLoops.md",2850],"8df82fb6":[()=>n.e(301).then(n.bind(n,2964)),"@site/versioned_docs/version-0.2.1/detectors/NeverAccessedVariables.md",2964],"8e426e62":[()=>n.e(2991).then(n.bind(n,8966)),"@site/versioned_docs/version-0.4.0/detectors/DumpIsUsed.md",8966],"8e8fe4d7":[()=>n.e(9924).then(n.bind(n,2917)),"@site/versioned_docs/version-0.3.1/detectors/DivideBeforeMultiply.md",2917],"9016a10e":[()=>n.e(2906).then(n.bind(n,7216)),"@site/docs/detectors/UnusedExpressionResult.md",7216],"9081c3e5":[()=>n.e(6805).then(n.bind(n,1445)),"@site/versioned_docs/version-0.5/detectors/PreferredStdlibApi.md",1445],"90b5d830":[()=>n.e(4318).then(n.bind(n,7230)),"@site/versioned_docs/version-0.2.2/detectors.md",7230],"91acf703":[()=>n.e(3291).then(n.bind(n,7619)),"@site/versioned_docs/version-0.4.0/detectors/ZeroAddress.md",7619],"91ee281c":[()=>n.e(2397).then(n.bind(n,3505)),"@site/versioned_docs/version-0.3.0/tutorial/cli.md",3505],"926d5e8d":[()=>n.e(2526).then(n.bind(n,2737)),"@site/versioned_docs/version-0.5/detectors/SendInLoop.md",2737],"94d07e36":[()=>n.e(8235).then(n.bind(n,2345)),"@site/versioned_docs/version-0.4.0/detectors/EnsurePrgSeed.md",2345],"96e77fcb":[()=>n.e(5922).then(n.bind(n,7021)),"@site/versioned_docs/version-0.3.0/detectors/PreferAugmentedAssign.md",7021],"972c9666":[()=>n.e(1179).then(n.bind(n,590)),"@site/versioned_docs/version-0.2.0/detectors/PreferAugmentedAssign.md",590],"987a8a5d":[()=>n.e(1318).then(n.bind(n,9490)),"@site/versioned_docs/version-0.1.2/detectors/UnboundLoops.md",9490],"988b076a":[()=>n.e(9758).then(n.bind(n,2426)),"@site/versioned_docs/version-0.3.0/hacking/contributing.md",2426],"9983337e":[()=>n.e(3320).then(n.bind(n,1337)),"@site/versioned_docs/version-0.5/detectors/SuspiciousMessageMode.md",1337],"9fedf60a":[()=>n.e(3388).then(n.bind(n,9957)),"@site/versioned_docs/version-0.3.1/detectors/ZeroAddress.md",9957],a291c19d:[()=>n.e(4903).then(n.bind(n,7937)),"@site/versioned_docs/version-0.4.0/detectors/InheritedStateMutation.md",7937],a2e1ac23:[()=>n.e(9977).then(n.bind(n,1682)),"@site/docs/detectors/UnboundLoop.md",1682],a3df6930:[()=>n.e(767).then(n.bind(n,4152)),"@site/versioned_docs/version-0.4.0/tutorial/getting-started.md",4152],a4516edb:[()=>n.e(9415).then(n.t.bind(n,1664,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-1-2-a72.json",1664],a5055d90:[()=>n.e(5484).then(n.bind(n,535)),"@site/docs/hacking/design.md",535],a66f2ff0:[()=>n.e(1332).then(n.bind(n,5467)),"@site/versioned_docs/version-0.3.1/detectors/UnboundLoops.md",5467],a7456010:[()=>n.e(1235).then(n.t.bind(n,8552,19)),"@generated/docusaurus-plugin-content-pages/default/__plugin.json",8552],a7bd4aaa:[()=>n.e(7098).then(n.bind(n,4532)),"@theme/DocVersionRoot",4532],a7eb4927:[()=>n.e(8262).then(n.bind(n,936)),"@site/versioned_docs/version-0.3.0/hacking/design.md",936],a8c496ca:[()=>n.e(9304).then(n.bind(n,8812)),"@site/versioned_docs/version-0.3.1/detectors/DumpIsUsed.md",8812],a8d7d639:[()=>n.e(6701).then(n.t.bind(n,1831,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-2-0-5cb.json",1831],a94703ab:[()=>Promise.all([n.e(1869),n.e(9048)]).then(n.bind(n,2559)),"@theme/DocRoot",2559],aac87eb6:[()=>n.e(684).then(n.bind(n,4646)),"@site/versioned_docs/version-0.3.1/detectors/BranchDuplicate.md",4646],ab64460a:[()=>n.e(2467).then(n.bind(n,6083)),"@site/versioned_docs/version-0.5/detectors/UnboundLoop.md",6083],aba21aa0:[()=>n.e(5742).then(n.t.bind(n,7093,19)),"@generated/docusaurus-plugin-content-docs/default/__plugin.json",7093],acef80f0:[()=>n.e(1468).then(n.bind(n,2492)),"@site/versioned_docs/version-0.2.1/hacking/design.md",2492],aee0b8cc:[()=>n.e(5622).then(n.bind(n,3023)),"@site/versioned_docs/version-0.4.0/tools/DumpAst.md",3023],b05af762:[()=>n.e(6670).then(n.bind(n,6683)),"@site/versioned_docs/version-0.3.0/detectors.md",6683],b12d76e5:[()=>n.e(9359).then(n.bind(n,9813)),"@site/docs/detectors/DuplicatedCondition.md",9813],b2b6aa30:[()=>n.e(6216).then(n.bind(n,7828)),"@site/versioned_docs/version-0.5/detectors/OptimalMathFunction.md",7828],b3799bec:[()=>n.e(8031).then(n.bind(n,4207)),"@site/versioned_docs/version-0.2.0/detectors/ConstantAddress.md",4207],b64540ae:[()=>n.e(6412).then(n.bind(n,8560)),"@site/docs/tutorial/getting-started.md",8560],b64aaedd:[()=>n.e(5588).then(n.bind(n,4913)),"@site/versioned_docs/version-0.4.0/detectors/FalseCondition.md",4913],b78952d0:[()=>n.e(7682).then(n.bind(n,4428)),"@site/versioned_docs/version-0.3.1/detectors/FieldDoubleInit.md",4428],b80eaa74:[()=>n.e(4111).then(n.bind(n,8050)),"@site/versioned_docs/version-0.3.0/hacking/souffle.md",8050],b91dc83b:[()=>n.e(9601).then(n.bind(n,3137)),"@site/versioned_docs/version-0.2.1/tutorial/configuration.md",3137],b9de2907:[()=>n.e(4913).then(n.bind(n,5144)),"@site/versioned_docs/version-0.5/tutorial/blueprint.md",5144],bce595e9:[()=>n.e(8692).then(n.bind(n,3117)),"@site/versioned_docs/version-0.2.2/hacking/contributing.md",3117],bd72ef9b:[()=>n.e(1114).then(n.bind(n,9712)),"@site/versioned_docs/version-0.2.0/detectors/FieldDoubleInit.md",9712],be04c9f2:[()=>n.e(44).then(n.bind(n,2322)),"@site/docs/detectors/SendInLoop.md",2322],be8ab43b:[()=>n.e(6584).then(n.bind(n,3308)),"@site/versioned_docs/version-0.3.1/hacking/tools.md",3308],c00ee666:[()=>n.e(906).then(n.bind(n,3425)),"@site/versioned_docs/version-0.3.0/detectors/PreferredStdlibApi.md",3425],c05c6791:[()=>n.e(8677).then(n.bind(n,3820)),"@site/versioned_docs/version-0.3.1/detectors/PreferredStdlibApi.md",3820],c252c345:[()=>n.e(2798).then(n.bind(n,3618)),"@site/versioned_docs/version-0.3.0/detectors/AsmIsUsed.md",3618],c2845dc0:[()=>n.e(5378).then(n.bind(n,830)),"@site/versioned_docs/version-0.5/detectors/StringReceiversOverlap.md",830],c377a04b:[()=>n.e(3361).then(n.bind(n,8321)),"@site/docs/index.md",8321],c49af6bd:[()=>n.e(1006).then(n.bind(n,8765)),"@site/versioned_docs/version-0.2.1/detectors/DumpIsUsed.md",8765],c55f1521:[()=>n.e(7083).then(n.bind(n,384)),"@site/versioned_docs/version-0.3.0/detectors/ConstantAddress.md",384],c5c1850c:[()=>n.e(7837).then(n.bind(n,2134)),"@site/versioned_docs/version-0.2.2/tutorial/configuration.md",2134],c5d65102:[()=>n.e(8221).then(n.bind(n,415)),"@site/versioned_docs/version-0.2.2/detectors/ZeroAddress.md",415],c734b99d:[()=>n.e(872).then(n.bind(n,8956)),"@site/versioned_docs/version-0.5/detectors/UnusedOptional.md",8956],c7ee6afe:[()=>n.e(5459).then(n.bind(n,4729)),"@site/versioned_docs/version-0.4.0/index.md",4729],c82192ae:[()=>n.e(5321).then(n.bind(n,4482)),"@site/versioned_docs/version-0.4.0/detectors.md",4482],c926d0d4:[()=>n.e(8771).then(n.bind(n,3608)),"@site/versioned_docs/version-0.3.1/detectors.md",3608],c96954fa:[()=>n.e(2312).then(n.bind(n,263)),"@site/versioned_docs/version-0.2.2/detectors/DivideBeforeMultiply.md",263],ca178ca4:[()=>n.e(2195).then(n.bind(n,5778)),"@site/versioned_docs/version-0.2.2/detectors/ReadOnlyVariables.md",5778],cb77e040:[()=>n.e(6757).then(n.bind(n,4318)),"@site/docs/detectors/PreferredStdlibApi.md",4318],cc6d1ce2:[()=>n.e(3750).then(n.bind(n,433)),"@site/versioned_docs/version-0.3.0/detectors/ArgCopyMutation.md",433],cd411a47:[()=>n.e(4442).then(n.bind(n,4802)),"@site/versioned_docs/version-0.1.2/hacking/souffle.md",4802],ce7f72c2:[()=>n.e(5200).then(n.bind(n,4795)),"@site/versioned_docs/version-0.3.1/hacking/contributing.md",4795],cf2c24d9:[()=>n.e(338).then(n.bind(n,9)),"@site/versioned_docs/version-0.4.0/detectors/UnboundLoops.md",9],cf5f971a:[()=>n.e(7003).then(n.bind(n,1963)),"@site/versioned_docs/version-0.1.2/hacking/tools.md",1963],d147047e:[()=>n.e(7965).then(n.bind(n,2643)),"@site/versioned_docs/version-0.3.1/detectors/InheritedStateMutation.md",2643],d15cc687:[()=>n.e(6406).then(n.bind(n,7033)),"@site/versioned_docs/version-0.2.1/detectors/BranchDuplicate.md",7033],d1781038:[()=>n.e(6633).then(n.bind(n,5e3)),"@site/versioned_docs/version-0.2.1/index.md",5e3],d2aaf676:[()=>n.e(4040).then(n.bind(n,9323)),"@site/docs/detectors/NeverAccessedVariables.md",9323],d2d53d04:[()=>n.e(2537).then(n.bind(n,8023)),"@site/versioned_docs/version-0.2.2/tutorial/blueprint.md",8023],d2f295f4:[()=>n.e(7242).then(n.bind(n,5077)),"@site/docs/tools/DumpCfg.md",5077],d3996cd7:[()=>n.e(5664).then(n.bind(n,9735)),"@site/docs/tools/DumpAst.md",9735],d46ee8ed:[()=>n.e(8072).then(n.t.bind(n,7884,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-3-1-0dc.json",7884],d6f3e79e:[()=>n.e(1678).then(n.bind(n,1747)),"@site/versioned_docs/version-0.1.2/detectors/ReadOnlyVariables.md",1747],d7c99f30:[()=>n.e(8904).then(n.bind(n,7389)),"@site/versioned_docs/version-0.4.0/detectors/OptimalMathFunction.md",7389],d7d99e1d:[()=>n.e(9076).then(n.bind(n,668)),"@site/versioned_docs/version-0.2.2/detectors/NeverAccessedVariables.md",668],d7ebd85b:[()=>n.e(5308).then(n.bind(n,6659)),"@site/versioned_docs/version-0.5/tools.md",6659],d9542fcf:[()=>n.e(3590).then(n.bind(n,2866)),"@site/versioned_docs/version-0.2.0/detectors/BranchDuplicate.md",2866],d9941f94:[()=>n.e(8183).then(n.bind(n,7084)),"@site/versioned_docs/version-0.5/tools/DumpCfg.md",7084],dc55925b:[()=>n.e(8546).then(n.bind(n,5729)),"@site/docs/detectors/EnsurePrgSeed.md",5729],dd8730c9:[()=>n.e(8137).then(n.t.bind(n,2205,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-next-ec9.json",2205],dda96275:[()=>n.e(7193).then(n.bind(n,6924)),"@site/versioned_docs/version-0.5/hacking/design.md",6924],de7c269b:[()=>n.e(6309).then(n.bind(n,5275)),"@site/docs/detectors/CellOverflow.md",5275],df3f8a78:[()=>n.e(6474).then(n.bind(n,9633)),"@site/versioned_docs/version-0.5/tutorial/configuration.md",9633],e0636556:[()=>n.e(8047).then(n.bind(n,3944)),"@site/versioned_docs/version-0.5/index.md",3944],e1c88a01:[()=>n.e(488).then(n.t.bind(n,9423,19)),"@generated/docusaurus-plugin-content-docs/default/p/tools-misti-docs-0-2-2-574.json",9423],e2ad9c7a:[()=>n.e(5945).then(n.bind(n,4193)),"@site/versioned_docs/version-0.3.1/hacking/design.md",4193],e3b47995:[()=>n.e(1171).then(n.bind(n,7112)),"@site/docs/detectors/BranchDuplicate.md",7112],e3c4fe0a:[()=>n.e(9428).then(n.bind(n,503)),"@site/versioned_docs/version-0.3.0/detectors/FieldDoubleInit.md",503],e4a43c7d:[()=>Promise.all([n.e(1869),n.e(5604),n.e(7348)]).then(n.bind(n,3888)),"@site/src/pages/tools/misti/index.tsx",3888],e530f65e:[()=>n.e(738).then(n.bind(n,425)),"@site/versioned_docs/version-0.5/detectors/BranchDuplicate.md",425],e5aa38d8:[()=>n.e(4082).then(n.bind(n,7817)),"@site/versioned_docs/version-0.3.0/detectors/DumpIsUsed.md",7817],e63578c3:[()=>n.e(9641).then(n.bind(n,7717)),"@site/versioned_docs/version-0.3.0/tutorial/configuration.md",7717],e6ef21e7:[()=>n.e(4984).then(n.bind(n,1053)),"@site/versioned_docs/version-0.4.0/detectors/DuplicatedCondition.md",1053],e9524270:[()=>n.e(2167).then(n.bind(n,7019)),"@site/docs/tutorial/ci-cd.md",7019],ea064c97:[()=>n.e(5508).then(n.bind(n,3195)),"@site/versioned_docs/version-0.4.0/detectors/AsmIsUsed.md",3195],ea8d0df0:[()=>n.e(335).then(n.bind(n,4905)),"@site/docs/hacking/custom-detector.md",4905],eb1a8185:[()=>n.e(5656).then(n.bind(n,3872)),"@site/versioned_docs/version-0.5/hacking/developing-misti.md",3872],ebcc9167:[()=>n.e(6387).then(n.bind(n,4416)),"@site/versioned_docs/version-0.3.0/detectors/NeverAccessedVariables.md",4416],ed017323:[()=>n.e(4138).then(n.bind(n,8065)),"@site/docs/hacking/contributing.md",8065],ed2e6971:[()=>n.e(8300).then(n.bind(n,8315)),"@site/docs/detectors/UnusedOptional.md",8315],edf1e52e:[()=>n.e(3434).then(n.bind(n,3744)),"@site/versioned_docs/version-0.1.2/detectors/NeverAccessedVariables.md",3744],ef43b7e4:[()=>n.e(9623).then(n.bind(n,3467)),"@site/versioned_docs/version-0.5/tutorial/getting-started.md",3467],effcc73a:[()=>n.e(485).then(n.bind(n,968)),"@site/versioned_docs/version-0.4.0/hacking/souffle.md",968],f18c7db7:[()=>n.e(9959).then(n.bind(n,4172)),"@site/versioned_docs/version-0.2.0/detectors.md",4172],f2bdb0f5:[()=>n.e(8836).then(n.bind(n,1582)),"@site/versioned_docs/version-0.2.1/hacking/souffle.md",1582],f3297ff5:[()=>n.e(1537).then(n.bind(n,7942)),"@site/docs/detectors/ReadOnlyVariables.md",7942],f3466e67:[()=>n.e(278).then(n.bind(n,252)),"@site/versioned_docs/version-0.1.2/index.md",252],f34cb5e0:[()=>n.e(9337).then(n.bind(n,9385)),"@site/docs/detectors/FalseCondition.md",9385],f4d075b1:[()=>n.e(7378).then(n.bind(n,462)),"@site/versioned_docs/version-0.2.2/detectors/FieldDoubleInit.md",462],f503d00c:[()=>n.e(2819).then(n.bind(n,7563)),"@site/versioned_docs/version-0.2.1/detectors/FieldDoubleInit.md",7563],f553073e:[()=>n.e(223).then(n.bind(n,6141)),"@site/versioned_docs/version-0.4.0/detectors/StringReceiversOverlap.md",6141],f5772bf1:[()=>n.e(1697).then(n.bind(n,1611)),"@site/versioned_docs/version-0.2.1/tutorial/getting-started.md",1611],f58fcc43:[()=>n.e(219).then(n.bind(n,9089)),"@site/versioned_docs/version-0.4.0/hacking/custom-detector.md",9089],f5bf49b8:[()=>n.e(243).then(n.bind(n,7857)),"@site/versioned_docs/version-0.2.1/detectors/PreferAugmentedAssign.md",7857],f6f2b22b:[()=>n.e(2091).then(n.bind(n,5208)),"@site/versioned_docs/version-0.3.1/tutorial/cli.md",5208],f752d1db:[()=>n.e(5900).then(n.bind(n,8656)),"@site/versioned_docs/version-0.4.0/tutorial/ci-cd.md",8656],f7ab1f3a:[()=>n.e(3754).then(n.bind(n,4856)),"@site/versioned_docs/version-0.1.2/hacking/design.md",4856],f97c3fca:[()=>n.e(877).then(n.bind(n,4297)),"@site/docs/detectors/ConstantAddress.md",4297],f99bae31:[()=>n.e(8927).then(n.bind(n,8721)),"@site/docs/tools/DumpImports.md",8721],faae61e5:[()=>n.e(5859).then(n.bind(n,8714)),"@site/docs/detectors.md",8714],fafa7ec8:[()=>n.e(4330).then(n.bind(n,706)),"@site/versioned_docs/version-0.2.2/detectors/DumpIsUsed.md",706],fbbe250b:[()=>n.e(7173).then(n.bind(n,3034)),"@site/docs/tutorial/configuration.md",3034],fcd86191:[()=>n.e(6752).then(n.bind(n,6493)),"@site/versioned_docs/version-0.2.2/hacking/custom-detector.md",6493],fe7c01fc:[()=>n.e(6854).then(n.bind(n,7437)),"@site/versioned_docs/version-0.3.0/detectors/BranchDuplicate.md",7437],ff0db780:[()=>n.e(1598).then(n.bind(n,4263)),"@site/versioned_docs/version-0.2.0/hacking/contributing.md",4263]};var a=n(4848);function l(e){let{error:t,retry:n,pastDelay:o}=e;return t?(0,a.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,a.jsx)("p",{children:String(t)}),(0,a.jsx)("div",{children:(0,a.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):o?(0,a.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,a.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,a.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,a.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,a.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,a.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,a.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,a.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,a.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,a.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,a.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,a.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,a.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(6921),d=n(3102);function u(e,t){if("*"===e)return r()({loading:l,loader:()=>n.e(2237).then(n.bind(n,2237)),modules:["@theme/NotFound"],webpack:()=>[2237],render(e,t){const n=e.default;return(0,a.jsx)(d.W,{value:{plugin:{name:"native",id:"default"}},children:(0,a.jsx)(n,{...t})})}});const o=i[`${e}-${t}`],u={},p=[],f=[],m=(0,c.A)(o);return Object.entries(m).forEach((e=>{let[t,n]=e;const o=s[n];o&&(u[t]=o[0],p.push(o[1]),f.push(o[2]))})),r().Map({loading:l,loader:u,modules:p,webpack:()=>f,render(t,n){const r=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,o]=t;const i=o.default;if(!i)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof i&&"function"!=typeof i||Object.keys(o).filter((e=>"default"!==e)).forEach((e=>{i[e]=o[e]}));let s=r;const a=n.split(".");a.slice(0,-1).forEach((e=>{s=s[e]})),s[a[a.length-1]]=i}));const i=r.__comp;delete r.__comp;const s=r.__context;delete r.__context;const l=r.__props;return delete r.__props,(0,a.jsx)(d.W,{value:s,children:(0,a.jsx)(i,{...r,...l,...n})})}})}const p=[{path:"/markdown-page",component:u("/markdown-page","3d7"),exact:!0},{path:"/tools/misti/",component:u("/tools/misti/","64a"),exact:!0},{path:"/tools/misti/docs",component:u("/tools/misti/docs","063"),routes:[{path:"/tools/misti/docs/0.1.2",component:u("/tools/misti/docs/0.1.2","f8a"),routes:[{path:"/tools/misti/docs/0.1.2",component:u("/tools/misti/docs/0.1.2","a68"),routes:[{path:"/tools/misti/docs/0.1.2/",component:u("/tools/misti/docs/0.1.2/","e00"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.1.2/detectors/DivideBeforeMultiply","d7c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables","95b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables","ec0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/detectors/UnboundLoops",component:u("/tools/misti/docs/0.1.2/detectors/UnboundLoops","097"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/detectors/ZeroAddress",component:u("/tools/misti/docs/0.1.2/detectors/ZeroAddress","051"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/hacking/CHANGELOG",component:u("/tools/misti/docs/0.1.2/hacking/CHANGELOG","87f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/hacking/contributing",component:u("/tools/misti/docs/0.1.2/hacking/contributing","a2a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/hacking/custom-detector",component:u("/tools/misti/docs/0.1.2/hacking/custom-detector","00e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/hacking/design",component:u("/tools/misti/docs/0.1.2/hacking/design","745"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/hacking/souffle",component:u("/tools/misti/docs/0.1.2/hacking/souffle","cc7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/hacking/tools",component:u("/tools/misti/docs/0.1.2/hacking/tools","d9d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/tutorial/configuration",component:u("/tools/misti/docs/0.1.2/tutorial/configuration","c1b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.1.2/tutorial/getting-started",component:u("/tools/misti/docs/0.1.2/tutorial/getting-started","3e0"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/0.2.0",component:u("/tools/misti/docs/0.2.0","2c6"),routes:[{path:"/tools/misti/docs/0.2.0",component:u("/tools/misti/docs/0.2.0","635"),routes:[{path:"/tools/misti/docs/0.2.0/",component:u("/tools/misti/docs/0.2.0/","7ad"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors",component:u("/tools/misti/docs/0.2.0/detectors","e72"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/BranchDuplicate",component:u("/tools/misti/docs/0.2.0/detectors/BranchDuplicate","69d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/ConstantAddress",component:u("/tools/misti/docs/0.2.0/detectors/ConstantAddress","969"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.2.0/detectors/DivideBeforeMultiply","505"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/DumpIsUsed",component:u("/tools/misti/docs/0.2.0/detectors/DumpIsUsed","02c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/FieldDoubleInit",component:u("/tools/misti/docs/0.2.0/detectors/FieldDoubleInit","785"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.2.0/detectors/NeverAccessedVariables","308"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign","653"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.2.0/detectors/ReadOnlyVariables","89d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/UnboundLoops",component:u("/tools/misti/docs/0.2.0/detectors/UnboundLoops","e75"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/detectors/ZeroAddress",component:u("/tools/misti/docs/0.2.0/detectors/ZeroAddress","f88"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/hacking/contributing",component:u("/tools/misti/docs/0.2.0/hacking/contributing","576"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/hacking/custom-detector",component:u("/tools/misti/docs/0.2.0/hacking/custom-detector","7e7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/hacking/design",component:u("/tools/misti/docs/0.2.0/hacking/design","0d7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/hacking/souffle",component:u("/tools/misti/docs/0.2.0/hacking/souffle","7c7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/hacking/tools",component:u("/tools/misti/docs/0.2.0/hacking/tools","a79"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/tutorial/ci-cd",component:u("/tools/misti/docs/0.2.0/tutorial/ci-cd","d75"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/tutorial/configuration",component:u("/tools/misti/docs/0.2.0/tutorial/configuration","cf5"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.0/tutorial/getting-started",component:u("/tools/misti/docs/0.2.0/tutorial/getting-started","692"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/0.2.1",component:u("/tools/misti/docs/0.2.1","5f6"),routes:[{path:"/tools/misti/docs/0.2.1",component:u("/tools/misti/docs/0.2.1","ee6"),routes:[{path:"/tools/misti/docs/0.2.1/",component:u("/tools/misti/docs/0.2.1/","b26"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors",component:u("/tools/misti/docs/0.2.1/detectors","854"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/BranchDuplicate",component:u("/tools/misti/docs/0.2.1/detectors/BranchDuplicate","763"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/ConstantAddress",component:u("/tools/misti/docs/0.2.1/detectors/ConstantAddress","265"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.2.1/detectors/DivideBeforeMultiply","607"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/DumpIsUsed",component:u("/tools/misti/docs/0.2.1/detectors/DumpIsUsed","f66"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/FieldDoubleInit",component:u("/tools/misti/docs/0.2.1/detectors/FieldDoubleInit","9c2"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.2.1/detectors/NeverAccessedVariables","586"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/0.2.1/detectors/PreferAugmentedAssign","10d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables","c93"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/UnboundLoops",component:u("/tools/misti/docs/0.2.1/detectors/UnboundLoops","56e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/detectors/ZeroAddress",component:u("/tools/misti/docs/0.2.1/detectors/ZeroAddress","460"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/hacking/contributing",component:u("/tools/misti/docs/0.2.1/hacking/contributing","2b2"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/hacking/custom-detector",component:u("/tools/misti/docs/0.2.1/hacking/custom-detector","be8"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/hacking/design",component:u("/tools/misti/docs/0.2.1/hacking/design","813"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/hacking/souffle",component:u("/tools/misti/docs/0.2.1/hacking/souffle","844"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/hacking/tools",component:u("/tools/misti/docs/0.2.1/hacking/tools","452"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/tutorial/ci-cd",component:u("/tools/misti/docs/0.2.1/tutorial/ci-cd","988"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/tutorial/configuration",component:u("/tools/misti/docs/0.2.1/tutorial/configuration","910"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.1/tutorial/getting-started",component:u("/tools/misti/docs/0.2.1/tutorial/getting-started","f03"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/0.2.2",component:u("/tools/misti/docs/0.2.2","211"),routes:[{path:"/tools/misti/docs/0.2.2",component:u("/tools/misti/docs/0.2.2","1f0"),routes:[{path:"/tools/misti/docs/0.2.2/",component:u("/tools/misti/docs/0.2.2/","4ce"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors",component:u("/tools/misti/docs/0.2.2/detectors","a63"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/BranchDuplicate",component:u("/tools/misti/docs/0.2.2/detectors/BranchDuplicate","c5b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/ConstantAddress",component:u("/tools/misti/docs/0.2.2/detectors/ConstantAddress","21b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply","4dc"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/DumpIsUsed",component:u("/tools/misti/docs/0.2.2/detectors/DumpIsUsed","fe3"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/FieldDoubleInit",component:u("/tools/misti/docs/0.2.2/detectors/FieldDoubleInit","50d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables","716"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/0.2.2/detectors/PreferAugmentedAssign","0d0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables","3b1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/UnboundLoops",component:u("/tools/misti/docs/0.2.2/detectors/UnboundLoops","b9e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/detectors/ZeroAddress",component:u("/tools/misti/docs/0.2.2/detectors/ZeroAddress","98a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/hacking/contributing",component:u("/tools/misti/docs/0.2.2/hacking/contributing","894"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/hacking/custom-detector",component:u("/tools/misti/docs/0.2.2/hacking/custom-detector","2df"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/hacking/design",component:u("/tools/misti/docs/0.2.2/hacking/design","fe0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/hacking/souffle",component:u("/tools/misti/docs/0.2.2/hacking/souffle","8b1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/hacking/tools",component:u("/tools/misti/docs/0.2.2/hacking/tools","191"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/tutorial/blueprint",component:u("/tools/misti/docs/0.2.2/tutorial/blueprint","9e1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/tutorial/ci-cd",component:u("/tools/misti/docs/0.2.2/tutorial/ci-cd","260"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/tutorial/configuration",component:u("/tools/misti/docs/0.2.2/tutorial/configuration","7d4"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.2.2/tutorial/getting-started",component:u("/tools/misti/docs/0.2.2/tutorial/getting-started","825"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/0.3.0",component:u("/tools/misti/docs/0.3.0","d97"),routes:[{path:"/tools/misti/docs/0.3.0",component:u("/tools/misti/docs/0.3.0","be7"),routes:[{path:"/tools/misti/docs/0.3.0/",component:u("/tools/misti/docs/0.3.0/","d94"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors",component:u("/tools/misti/docs/0.3.0/detectors","558"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/ArgCopyMutation",component:u("/tools/misti/docs/0.3.0/detectors/ArgCopyMutation","0ef"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/AsmIsUsed",component:u("/tools/misti/docs/0.3.0/detectors/AsmIsUsed","dc6"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/BranchDuplicate",component:u("/tools/misti/docs/0.3.0/detectors/BranchDuplicate","656"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/ConstantAddress",component:u("/tools/misti/docs/0.3.0/detectors/ConstantAddress","74f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.3.0/detectors/DivideBeforeMultiply","963"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/DumpIsUsed",component:u("/tools/misti/docs/0.3.0/detectors/DumpIsUsed","e8b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/FieldDoubleInit",component:u("/tools/misti/docs/0.3.0/detectors/FieldDoubleInit","aa1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/InheritedStateMutation",component:u("/tools/misti/docs/0.3.0/detectors/InheritedStateMutation","911"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables","6bb"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign","46a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/PreferredStdlibApi",component:u("/tools/misti/docs/0.3.0/detectors/PreferredStdlibApi","544"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.3.0/detectors/ReadOnlyVariables","460"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/StringReceiversOverlap",component:u("/tools/misti/docs/0.3.0/detectors/StringReceiversOverlap","bea"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/UnboundLoops",component:u("/tools/misti/docs/0.3.0/detectors/UnboundLoops","d61"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/detectors/ZeroAddress",component:u("/tools/misti/docs/0.3.0/detectors/ZeroAddress","7e8"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/hacking/contributing",component:u("/tools/misti/docs/0.3.0/hacking/contributing","e13"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/hacking/custom-detector",component:u("/tools/misti/docs/0.3.0/hacking/custom-detector","178"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/hacking/design",component:u("/tools/misti/docs/0.3.0/hacking/design","653"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/hacking/souffle",component:u("/tools/misti/docs/0.3.0/hacking/souffle","35c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/hacking/tools",component:u("/tools/misti/docs/0.3.0/hacking/tools","b51"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/tutorial/blueprint",component:u("/tools/misti/docs/0.3.0/tutorial/blueprint","894"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/tutorial/ci-cd",component:u("/tools/misti/docs/0.3.0/tutorial/ci-cd","2c5"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/tutorial/cli",component:u("/tools/misti/docs/0.3.0/tutorial/cli","e3e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/tutorial/configuration",component:u("/tools/misti/docs/0.3.0/tutorial/configuration","1f6"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.0/tutorial/getting-started",component:u("/tools/misti/docs/0.3.0/tutorial/getting-started","989"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/0.3.1",component:u("/tools/misti/docs/0.3.1","ce6"),routes:[{path:"/tools/misti/docs/0.3.1",component:u("/tools/misti/docs/0.3.1","7d2"),routes:[{path:"/tools/misti/docs/0.3.1/",component:u("/tools/misti/docs/0.3.1/","6da"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors",component:u("/tools/misti/docs/0.3.1/detectors","36d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/ArgCopyMutation",component:u("/tools/misti/docs/0.3.1/detectors/ArgCopyMutation","742"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/AsmIsUsed",component:u("/tools/misti/docs/0.3.1/detectors/AsmIsUsed","f46"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/BranchDuplicate",component:u("/tools/misti/docs/0.3.1/detectors/BranchDuplicate","a80"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/ConstantAddress",component:u("/tools/misti/docs/0.3.1/detectors/ConstantAddress","eb7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply","908"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/DumpIsUsed",component:u("/tools/misti/docs/0.3.1/detectors/DumpIsUsed","6bc"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit",component:u("/tools/misti/docs/0.3.1/detectors/FieldDoubleInit","385"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/InheritedStateMutation",component:u("/tools/misti/docs/0.3.1/detectors/InheritedStateMutation","810"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.3.1/detectors/NeverAccessedVariables","7d1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/0.3.1/detectors/PreferAugmentedAssign","e3f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi",component:u("/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi","05c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables","501"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap",component:u("/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap","1a3"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/UnboundLoops",component:u("/tools/misti/docs/0.3.1/detectors/UnboundLoops","92f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/detectors/ZeroAddress",component:u("/tools/misti/docs/0.3.1/detectors/ZeroAddress","ccb"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/hacking/contributing",component:u("/tools/misti/docs/0.3.1/hacking/contributing","b74"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/hacking/custom-detector",component:u("/tools/misti/docs/0.3.1/hacking/custom-detector","3e6"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/hacking/design",component:u("/tools/misti/docs/0.3.1/hacking/design","40b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/hacking/souffle",component:u("/tools/misti/docs/0.3.1/hacking/souffle","53a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/hacking/tools",component:u("/tools/misti/docs/0.3.1/hacking/tools","035"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/tutorial/blueprint",component:u("/tools/misti/docs/0.3.1/tutorial/blueprint","5ec"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/tutorial/ci-cd",component:u("/tools/misti/docs/0.3.1/tutorial/ci-cd","e30"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/tutorial/cli",component:u("/tools/misti/docs/0.3.1/tutorial/cli","3c0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/tutorial/configuration",component:u("/tools/misti/docs/0.3.1/tutorial/configuration","160"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.3.1/tutorial/getting-started",component:u("/tools/misti/docs/0.3.1/tutorial/getting-started","493"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/0.4.0",component:u("/tools/misti/docs/0.4.0","e81"),routes:[{path:"/tools/misti/docs/0.4.0",component:u("/tools/misti/docs/0.4.0","bc8"),routes:[{path:"/tools/misti/docs/0.4.0/",component:u("/tools/misti/docs/0.4.0/","6f1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors",component:u("/tools/misti/docs/0.4.0/detectors","df6"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/ArgCopyMutation",component:u("/tools/misti/docs/0.4.0/detectors/ArgCopyMutation","761"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/AsmIsUsed",component:u("/tools/misti/docs/0.4.0/detectors/AsmIsUsed","6ef"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/BranchDuplicate",component:u("/tools/misti/docs/0.4.0/detectors/BranchDuplicate","051"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/ConstantAddress",component:u("/tools/misti/docs/0.4.0/detectors/ConstantAddress","1fb"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply","33e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/DumpIsUsed",component:u("/tools/misti/docs/0.4.0/detectors/DumpIsUsed","b24"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/DuplicatedCondition",component:u("/tools/misti/docs/0.4.0/detectors/DuplicatedCondition","477"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed",component:u("/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed","a2b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/FalseCondition",component:u("/tools/misti/docs/0.4.0/detectors/FalseCondition","f06"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/FieldDoubleInit",component:u("/tools/misti/docs/0.4.0/detectors/FieldDoubleInit","cc7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/InheritedStateMutation",component:u("/tools/misti/docs/0.4.0/detectors/InheritedStateMutation","d7f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables","e94"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/OptimalMathFunction",component:u("/tools/misti/docs/0.4.0/detectors/OptimalMathFunction","849"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign","127"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi",component:u("/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi","d75"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables","4b9"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap",component:u("/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap","c8e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/UnboundLoops",component:u("/tools/misti/docs/0.4.0/detectors/UnboundLoops","813"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/UnusedOptional",component:u("/tools/misti/docs/0.4.0/detectors/UnusedOptional","492"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/detectors/ZeroAddress",component:u("/tools/misti/docs/0.4.0/detectors/ZeroAddress","b6d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/hacking/contributing",component:u("/tools/misti/docs/0.4.0/hacking/contributing","39d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/hacking/custom-detector",component:u("/tools/misti/docs/0.4.0/hacking/custom-detector","45e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/hacking/design",component:u("/tools/misti/docs/0.4.0/hacking/design","ed4"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/hacking/developing-misti",component:u("/tools/misti/docs/0.4.0/hacking/developing-misti","172"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/hacking/souffle",component:u("/tools/misti/docs/0.4.0/hacking/souffle","144"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tools",component:u("/tools/misti/docs/0.4.0/tools","28d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tools/DumpAst",component:u("/tools/misti/docs/0.4.0/tools/DumpAst","2aa"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tools/DumpCfg",component:u("/tools/misti/docs/0.4.0/tools/DumpCfg","d27"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tools/DumpConfig",component:u("/tools/misti/docs/0.4.0/tools/DumpConfig","7b4"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tutorial/blueprint",component:u("/tools/misti/docs/0.4.0/tutorial/blueprint","d90"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tutorial/ci-cd",component:u("/tools/misti/docs/0.4.0/tutorial/ci-cd","096"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tutorial/cli",component:u("/tools/misti/docs/0.4.0/tutorial/cli","179"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tutorial/configuration",component:u("/tools/misti/docs/0.4.0/tutorial/configuration","e42"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/0.4.0/tutorial/getting-started",component:u("/tools/misti/docs/0.4.0/tutorial/getting-started","0f1"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs/next",component:u("/tools/misti/docs/next","13c"),routes:[{path:"/tools/misti/docs/next",component:u("/tools/misti/docs/next","46d"),routes:[{path:"/tools/misti/docs/next/",component:u("/tools/misti/docs/next/","ac0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors",component:u("/tools/misti/docs/next/detectors","3fb"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/ArgCopyMutation",component:u("/tools/misti/docs/next/detectors/ArgCopyMutation","e79"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/AsmIsUsed",component:u("/tools/misti/docs/next/detectors/AsmIsUsed","be7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/BranchDuplicate",component:u("/tools/misti/docs/next/detectors/BranchDuplicate","046"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/CellOverflow",component:u("/tools/misti/docs/next/detectors/CellOverflow","347"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/ConstantAddress",component:u("/tools/misti/docs/next/detectors/ConstantAddress","6d7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/next/detectors/DivideBeforeMultiply","004"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/DumpIsUsed",component:u("/tools/misti/docs/next/detectors/DumpIsUsed","58e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/DuplicatedCondition",component:u("/tools/misti/docs/next/detectors/DuplicatedCondition","f7a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/EnsurePrgSeed",component:u("/tools/misti/docs/next/detectors/EnsurePrgSeed","d1b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/FalseCondition",component:u("/tools/misti/docs/next/detectors/FalseCondition","472"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/FieldDoubleInit",component:u("/tools/misti/docs/next/detectors/FieldDoubleInit","c32"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/InheritedStateMutation",component:u("/tools/misti/docs/next/detectors/InheritedStateMutation","d8d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/next/detectors/NeverAccessedVariables","94c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/OptimalMathFunction",component:u("/tools/misti/docs/next/detectors/OptimalMathFunction","b0f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/next/detectors/PreferAugmentedAssign","951"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/PreferredStdlibApi",component:u("/tools/misti/docs/next/detectors/PreferredStdlibApi","ed1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/next/detectors/ReadOnlyVariables","c98"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/SendInLoop",component:u("/tools/misti/docs/next/detectors/SendInLoop","d81"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/ShortCircuitCondition",component:u("/tools/misti/docs/next/detectors/ShortCircuitCondition","96a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/StringReceiversOverlap",component:u("/tools/misti/docs/next/detectors/StringReceiversOverlap","992"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/SuspiciousMessageMode",component:u("/tools/misti/docs/next/detectors/SuspiciousMessageMode","7ac"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/UnboundLoop",component:u("/tools/misti/docs/next/detectors/UnboundLoop","e09"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/UnboundMap",component:u("/tools/misti/docs/next/detectors/UnboundMap","8d3"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/UnusedExpressionResult",component:u("/tools/misti/docs/next/detectors/UnusedExpressionResult","4c9"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/UnusedOptional",component:u("/tools/misti/docs/next/detectors/UnusedOptional","1be"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/detectors/ZeroAddress",component:u("/tools/misti/docs/next/detectors/ZeroAddress","f62"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/hacking/contributing",component:u("/tools/misti/docs/next/hacking/contributing","6f2"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/hacking/custom-detector",component:u("/tools/misti/docs/next/hacking/custom-detector","249"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/hacking/design",component:u("/tools/misti/docs/next/hacking/design","f37"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/hacking/developing-misti",component:u("/tools/misti/docs/next/hacking/developing-misti","1c9"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/hacking/souffle",component:u("/tools/misti/docs/next/hacking/souffle","6f2"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tools",component:u("/tools/misti/docs/next/tools","13f"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tools/DumpAst",component:u("/tools/misti/docs/next/tools/DumpAst","959"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tools/DumpCfg",component:u("/tools/misti/docs/next/tools/DumpCfg","579"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tools/DumpConfig",component:u("/tools/misti/docs/next/tools/DumpConfig","d2a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tools/DumpImports",component:u("/tools/misti/docs/next/tools/DumpImports","bfa"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tutorial/blueprint",component:u("/tools/misti/docs/next/tutorial/blueprint","885"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tutorial/ci-cd",component:u("/tools/misti/docs/next/tutorial/ci-cd","c7b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tutorial/cli",component:u("/tools/misti/docs/next/tutorial/cli","a3d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tutorial/configuration",component:u("/tools/misti/docs/next/tutorial/configuration","79b"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/next/tutorial/getting-started",component:u("/tools/misti/docs/next/tutorial/getting-started","390"),exact:!0,sidebar:"sidebar"}]}]},{path:"/tools/misti/docs",component:u("/tools/misti/docs","018"),routes:[{path:"/tools/misti/docs",component:u("/tools/misti/docs","fc9"),routes:[{path:"/tools/misti/docs/",component:u("/tools/misti/docs/","40c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors",component:u("/tools/misti/docs/detectors","946"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/ArgCopyMutation",component:u("/tools/misti/docs/detectors/ArgCopyMutation","5be"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/AsmIsUsed",component:u("/tools/misti/docs/detectors/AsmIsUsed","a1e"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/BranchDuplicate",component:u("/tools/misti/docs/detectors/BranchDuplicate","dcd"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/CellOverflow",component:u("/tools/misti/docs/detectors/CellOverflow","0e4"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/ConstantAddress",component:u("/tools/misti/docs/detectors/ConstantAddress","ca0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/DivideBeforeMultiply",component:u("/tools/misti/docs/detectors/DivideBeforeMultiply","e18"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/DumpIsUsed",component:u("/tools/misti/docs/detectors/DumpIsUsed","d93"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/DuplicatedCondition",component:u("/tools/misti/docs/detectors/DuplicatedCondition","636"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/EnsurePrgSeed",component:u("/tools/misti/docs/detectors/EnsurePrgSeed","cf1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/FalseCondition",component:u("/tools/misti/docs/detectors/FalseCondition","b70"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/FieldDoubleInit",component:u("/tools/misti/docs/detectors/FieldDoubleInit","24a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/InheritedStateMutation",component:u("/tools/misti/docs/detectors/InheritedStateMutation","7a0"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/NeverAccessedVariables",component:u("/tools/misti/docs/detectors/NeverAccessedVariables","517"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/OptimalMathFunction",component:u("/tools/misti/docs/detectors/OptimalMathFunction","19d"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/PreferAugmentedAssign",component:u("/tools/misti/docs/detectors/PreferAugmentedAssign","6e1"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/PreferredStdlibApi",component:u("/tools/misti/docs/detectors/PreferredStdlibApi","b23"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/ReadOnlyVariables",component:u("/tools/misti/docs/detectors/ReadOnlyVariables","972"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/SendInLoop",component:u("/tools/misti/docs/detectors/SendInLoop","499"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/StringReceiversOverlap",component:u("/tools/misti/docs/detectors/StringReceiversOverlap","6d4"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/SuspiciousMessageMode",component:u("/tools/misti/docs/detectors/SuspiciousMessageMode","7bd"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/UnboundLoop",component:u("/tools/misti/docs/detectors/UnboundLoop","9ae"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/UnboundMap",component:u("/tools/misti/docs/detectors/UnboundMap","f1a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/UnusedExpressionResult",component:u("/tools/misti/docs/detectors/UnusedExpressionResult","b7c"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/UnusedOptional",component:u("/tools/misti/docs/detectors/UnusedOptional","d35"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/detectors/ZeroAddress",component:u("/tools/misti/docs/detectors/ZeroAddress","d48"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/hacking/contributing",component:u("/tools/misti/docs/hacking/contributing","768"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/hacking/custom-detector",component:u("/tools/misti/docs/hacking/custom-detector","dd3"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/hacking/design",component:u("/tools/misti/docs/hacking/design","43a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/hacking/developing-misti",component:u("/tools/misti/docs/hacking/developing-misti","fe7"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/hacking/souffle",component:u("/tools/misti/docs/hacking/souffle","f46"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tools",component:u("/tools/misti/docs/tools","5d4"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tools/DumpAst",component:u("/tools/misti/docs/tools/DumpAst","ade"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tools/DumpCfg",component:u("/tools/misti/docs/tools/DumpCfg","280"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tools/DumpConfig",component:u("/tools/misti/docs/tools/DumpConfig","511"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tools/DumpImports",component:u("/tools/misti/docs/tools/DumpImports","513"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tutorial/blueprint",component:u("/tools/misti/docs/tutorial/blueprint","6cf"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tutorial/ci-cd",component:u("/tools/misti/docs/tutorial/ci-cd","a83"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tutorial/cli",component:u("/tools/misti/docs/tutorial/cli","edd"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tutorial/configuration",component:u("/tools/misti/docs/tutorial/configuration","a4a"),exact:!0,sidebar:"sidebar"},{path:"/tools/misti/docs/tutorial/getting-started",component:u("/tools/misti/docs/tutorial/getting-started","7a0"),exact:!0,sidebar:"sidebar"}]}]}]},{path:"/",component:u("/","e5f"),exact:!0},{path:"*",component:u("*")}]},6125:(e,t,n)=>{"use strict";n.d(t,{o:()=>i,x:()=>s});var o=n(6540),r=n(4848);const i=o.createContext(!1);function s(e){let{children:t}=e;const[n,s]=(0,o.useState)(!1);return(0,o.useEffect)((()=>{s(!0)}),[]),(0,r.jsx)(i.Provider,{value:n,children:t})}},8536:(e,t,n)=>{"use strict";var o=n(6540),r=n(5338),i=n(545),s=n(4625),a=n(4784),l=n(8193);const c=[n(119),n(661),n(6294),n(1043),n(1911)];var d=n(8328),u=n(6347),p=n(2831),f=n(4848);function m(e){let{children:t}=e;return(0,f.jsx)(f.Fragment,{children:t})}var h=n(5260),b=n(4586),g=n(6025),v=n(6342),y=n(1003),w=n(2131),k=n(4090),x=n(2967),_=n(440),S=n(1463);function A(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,b.A)(),o=(0,w.o)(),r=n[e].htmlLang,i=e=>e.replace("-","_");return(0,f.jsxs)(h.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,f.jsx)("link",{rel:"alternate",href:o.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,f.jsx)("link",{rel:"alternate",href:o.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,f.jsx)("meta",{property:"og:locale",content:i(r)}),Object.values(n).filter((e=>r!==e.htmlLang)).map((e=>(0,f.jsx)("meta",{property:"og:locale:alternate",content:i(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function C(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,b.A)(),o=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,b.A)(),{pathname:o}=(0,u.zy)();return e+(0,_.applyTrailingSlash)((0,g.Ay)(o),{trailingSlash:n,baseUrl:t})}(),r=t?`${n}${t}`:o;return(0,f.jsxs)(h.A,{children:[(0,f.jsx)("meta",{property:"og:url",content:r}),(0,f.jsx)("link",{rel:"canonical",href:r})]})}function E(){const{i18n:{currentLocale:e}}=(0,b.A)(),{metadata:t,image:n}=(0,v.p)();return(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(h.A,{children:[(0,f.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,f.jsx)("body",{className:k.w})]}),n&&(0,f.jsx)(y.be,{image:n}),(0,f.jsx)(C,{}),(0,f.jsx)(A,{}),(0,f.jsx)(S.A,{tag:x.Cy,locale:e}),(0,f.jsx)(h.A,{children:t.map(((e,t)=>(0,f.jsx)("meta",{...e},t)))})]})}const D=new Map;var T=n(6125),R=n(6988),L=n(205);function O(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),o=1;o {const o=t.default?.[e]??t[e];return o?.(...n)}));return()=>r.forEach((e=>e?.()))}const P=function(e){let{children:t,location:n,previousLocation:o}=e;return(0,L.A)((()=>{o!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const o=t.pathname===n.pathname,r=t.hash===n.hash,i=t.search===n.search;if(o&&r&&!i)return;const{hash:s}=t;if(s){const e=decodeURIComponent(s.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:o}),O("onRouteDidUpdate",{previousLocation:o,location:n}))}),[o,n]),t};function N(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,p.u)(d.A,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class I extends o.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=l.A.canUseDOM?O("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=O("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),N(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,f.jsx)(P,{previousLocation:this.previousLocation,location:t,children:(0,f.jsx)(u.qh,{location:t,render:()=>e})})}}const j=I,M="__docusaurus-base-url-issue-banner-container",F="__docusaurus-base-url-issue-banner",U="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${M}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n \n\n`}(e)).replace(/{let{route:t}=e;return!0===t.exact})))return D.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return D.set(e.pathname,t),{...e,pathname:t}}((0,u.zy)());return(0,f.jsx)(j,{location:e,children:W})}function Q(){return(0,f.jsx)(q.A,{children:(0,f.jsx)(R.l,{children:(0,f.jsxs)(T.x,{children:[(0,f.jsxs)(m,{children:[(0,f.jsx)(V,{}),(0,f.jsx)(E,{}),(0,f.jsx)($,{}),(0,f.jsx)(Z,{})]}),(0,f.jsx)(G,{})]})})})}var K=n(4054);const Y=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const o=document.createElement("link");o.setAttribute("rel","prefetch"),o.setAttribute("href",e),o.onload=()=>t(),o.onerror=()=>n();const r=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;r?.appendChild(o)}))}:function(e){return new Promise(((t,n)=>{const o=new XMLHttpRequest;o.open("GET",e,!0),o.withCredentials=!0,o.onload=()=>{200===o.status?t():n()},o.send(null)}))};var X=n(6921);const J=new Set,ee=new Set,te=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ne={prefetch:e=>{if(!(e=>!te()&&!ee.has(e)&&!J.has(e))(e))return!1;J.add(e);const t=(0,p.u)(d.A,e).flatMap((e=>{return t=e.route.path,Object.entries(K).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,X.A)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Y(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!te()&&!ee.has(e))(e)&&(ee.add(e),N(e))},oe=Object.freeze(ne);function re(e){let{children:t}=e;return"hash"===a.default.future.experimental_router?(0,f.jsx)(s.I9,{children:t}):(0,f.jsx)(s.Kd,{children:t})}const ie=Boolean(!0);if(l.A.canUseDOM){window.docusaurus=oe;const e=document.getElementById("__docusaurus"),t=(0,f.jsx)(i.vd,{children:(0,f.jsx)(re,{children:(0,f.jsx)(Q,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},s=()=>{if(window.docusaurusRoot)window.docusaurusRoot.render(t);else if(ie)window.docusaurusRoot=r.hydrateRoot(e,t,{onRecoverableError:n});else{const o=r.createRoot(e,{onRecoverableError:n});o.render(t),window.docusaurusRoot=o}};N(window.location.pathname).then((()=>{(0,o.startTransition)(s)}))}},6988:(e,t,n)=>{"use strict";n.d(t,{o:()=>u,l:()=>p});var o=n(6540),r=n(4784);const i=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/tools/misti/docs","versions":[{"name":"current","label":"Next","isLast":false,"path":"/tools/misti/docs/next","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/next/detectors","sidebar":"sidebar"},{"id":"detectors/ArgCopyMutation","path":"/tools/misti/docs/next/detectors/ArgCopyMutation","sidebar":"sidebar"},{"id":"detectors/AsmIsUsed","path":"/tools/misti/docs/next/detectors/AsmIsUsed","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/next/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/CellOverflow","path":"/tools/misti/docs/next/detectors/CellOverflow","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/next/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/next/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/next/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/DuplicatedCondition","path":"/tools/misti/docs/next/detectors/DuplicatedCondition","sidebar":"sidebar"},{"id":"detectors/EnsurePrgSeed","path":"/tools/misti/docs/next/detectors/EnsurePrgSeed","sidebar":"sidebar"},{"id":"detectors/FalseCondition","path":"/tools/misti/docs/next/detectors/FalseCondition","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/next/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/InheritedStateMutation","path":"/tools/misti/docs/next/detectors/InheritedStateMutation","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/next/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/OptimalMathFunction","path":"/tools/misti/docs/next/detectors/OptimalMathFunction","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/next/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/PreferredStdlibApi","path":"/tools/misti/docs/next/detectors/PreferredStdlibApi","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/next/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/SendInLoop","path":"/tools/misti/docs/next/detectors/SendInLoop","sidebar":"sidebar"},{"id":"detectors/ShortCircuitCondition","path":"/tools/misti/docs/next/detectors/ShortCircuitCondition","sidebar":"sidebar"},{"id":"detectors/StringReceiversOverlap","path":"/tools/misti/docs/next/detectors/StringReceiversOverlap","sidebar":"sidebar"},{"id":"detectors/SuspiciousMessageMode","path":"/tools/misti/docs/next/detectors/SuspiciousMessageMode","sidebar":"sidebar"},{"id":"detectors/UnboundLoop","path":"/tools/misti/docs/next/detectors/UnboundLoop","sidebar":"sidebar"},{"id":"detectors/UnboundMap","path":"/tools/misti/docs/next/detectors/UnboundMap","sidebar":"sidebar"},{"id":"detectors/UnusedExpressionResult","path":"/tools/misti/docs/next/detectors/UnusedExpressionResult","sidebar":"sidebar"},{"id":"detectors/UnusedOptional","path":"/tools/misti/docs/next/detectors/UnusedOptional","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/next/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/next/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/next/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/next/hacking/design","sidebar":"sidebar"},{"id":"hacking/developing-misti","path":"/tools/misti/docs/next/hacking/developing-misti","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/next/hacking/souffle","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/next/","sidebar":"sidebar"},{"id":"tools","path":"/tools/misti/docs/next/tools","sidebar":"sidebar"},{"id":"tools/DumpAst","path":"/tools/misti/docs/next/tools/DumpAst","sidebar":"sidebar"},{"id":"tools/DumpCfg","path":"/tools/misti/docs/next/tools/DumpCfg","sidebar":"sidebar"},{"id":"tools/DumpConfig","path":"/tools/misti/docs/next/tools/DumpConfig","sidebar":"sidebar"},{"id":"tools/DumpImports","path":"/tools/misti/docs/next/tools/DumpImports","sidebar":"sidebar"},{"id":"tutorial/blueprint","path":"/tools/misti/docs/next/tutorial/blueprint","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/next/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/cli","path":"/tools/misti/docs/next/tutorial/cli","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/next/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/next/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/next/","label":"Introduction"}}}},{"name":"0.5","label":"0.5","isLast":true,"path":"/tools/misti/docs","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/detectors","sidebar":"sidebar"},{"id":"detectors/ArgCopyMutation","path":"/tools/misti/docs/detectors/ArgCopyMutation","sidebar":"sidebar"},{"id":"detectors/AsmIsUsed","path":"/tools/misti/docs/detectors/AsmIsUsed","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/CellOverflow","path":"/tools/misti/docs/detectors/CellOverflow","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/DuplicatedCondition","path":"/tools/misti/docs/detectors/DuplicatedCondition","sidebar":"sidebar"},{"id":"detectors/EnsurePrgSeed","path":"/tools/misti/docs/detectors/EnsurePrgSeed","sidebar":"sidebar"},{"id":"detectors/FalseCondition","path":"/tools/misti/docs/detectors/FalseCondition","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/InheritedStateMutation","path":"/tools/misti/docs/detectors/InheritedStateMutation","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/OptimalMathFunction","path":"/tools/misti/docs/detectors/OptimalMathFunction","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/PreferredStdlibApi","path":"/tools/misti/docs/detectors/PreferredStdlibApi","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/SendInLoop","path":"/tools/misti/docs/detectors/SendInLoop","sidebar":"sidebar"},{"id":"detectors/StringReceiversOverlap","path":"/tools/misti/docs/detectors/StringReceiversOverlap","sidebar":"sidebar"},{"id":"detectors/SuspiciousMessageMode","path":"/tools/misti/docs/detectors/SuspiciousMessageMode","sidebar":"sidebar"},{"id":"detectors/UnboundLoop","path":"/tools/misti/docs/detectors/UnboundLoop","sidebar":"sidebar"},{"id":"detectors/UnboundMap","path":"/tools/misti/docs/detectors/UnboundMap","sidebar":"sidebar"},{"id":"detectors/UnusedExpressionResult","path":"/tools/misti/docs/detectors/UnusedExpressionResult","sidebar":"sidebar"},{"id":"detectors/UnusedOptional","path":"/tools/misti/docs/detectors/UnusedOptional","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/hacking/design","sidebar":"sidebar"},{"id":"hacking/developing-misti","path":"/tools/misti/docs/hacking/developing-misti","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/hacking/souffle","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/","sidebar":"sidebar"},{"id":"tools","path":"/tools/misti/docs/tools","sidebar":"sidebar"},{"id":"tools/DumpAst","path":"/tools/misti/docs/tools/DumpAst","sidebar":"sidebar"},{"id":"tools/DumpCfg","path":"/tools/misti/docs/tools/DumpCfg","sidebar":"sidebar"},{"id":"tools/DumpConfig","path":"/tools/misti/docs/tools/DumpConfig","sidebar":"sidebar"},{"id":"tools/DumpImports","path":"/tools/misti/docs/tools/DumpImports","sidebar":"sidebar"},{"id":"tutorial/blueprint","path":"/tools/misti/docs/tutorial/blueprint","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/cli","path":"/tools/misti/docs/tutorial/cli","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/","label":"Introduction"}}}},{"name":"0.4.0","label":"0.4.0","isLast":false,"path":"/tools/misti/docs/0.4.0","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/0.4.0/detectors","sidebar":"sidebar"},{"id":"detectors/ArgCopyMutation","path":"/tools/misti/docs/0.4.0/detectors/ArgCopyMutation","sidebar":"sidebar"},{"id":"detectors/AsmIsUsed","path":"/tools/misti/docs/0.4.0/detectors/AsmIsUsed","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/0.4.0/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/0.4.0/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.4.0/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/0.4.0/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/DuplicatedCondition","path":"/tools/misti/docs/0.4.0/detectors/DuplicatedCondition","sidebar":"sidebar"},{"id":"detectors/EnsurePrgSeed","path":"/tools/misti/docs/0.4.0/detectors/EnsurePrgSeed","sidebar":"sidebar"},{"id":"detectors/FalseCondition","path":"/tools/misti/docs/0.4.0/detectors/FalseCondition","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/0.4.0/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/InheritedStateMutation","path":"/tools/misti/docs/0.4.0/detectors/InheritedStateMutation","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.4.0/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/OptimalMathFunction","path":"/tools/misti/docs/0.4.0/detectors/OptimalMathFunction","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/0.4.0/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/PreferredStdlibApi","path":"/tools/misti/docs/0.4.0/detectors/PreferredStdlibApi","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.4.0/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/StringReceiversOverlap","path":"/tools/misti/docs/0.4.0/detectors/StringReceiversOverlap","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.4.0/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/UnusedOptional","path":"/tools/misti/docs/0.4.0/detectors/UnusedOptional","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.4.0/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.4.0/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.4.0/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.4.0/hacking/design","sidebar":"sidebar"},{"id":"hacking/developing-misti","path":"/tools/misti/docs/0.4.0/hacking/developing-misti","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.4.0/hacking/souffle","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.4.0/","sidebar":"sidebar"},{"id":"tools","path":"/tools/misti/docs/0.4.0/tools","sidebar":"sidebar"},{"id":"tools/DumpAst","path":"/tools/misti/docs/0.4.0/tools/DumpAst","sidebar":"sidebar"},{"id":"tools/DumpCfg","path":"/tools/misti/docs/0.4.0/tools/DumpCfg","sidebar":"sidebar"},{"id":"tools/DumpConfig","path":"/tools/misti/docs/0.4.0/tools/DumpConfig","sidebar":"sidebar"},{"id":"tutorial/blueprint","path":"/tools/misti/docs/0.4.0/tutorial/blueprint","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/0.4.0/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/cli","path":"/tools/misti/docs/0.4.0/tutorial/cli","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.4.0/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.4.0/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.4.0/","label":"Introduction"}}}},{"name":"0.3.1","label":"0.3.1","isLast":false,"path":"/tools/misti/docs/0.3.1","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/0.3.1/detectors","sidebar":"sidebar"},{"id":"detectors/ArgCopyMutation","path":"/tools/misti/docs/0.3.1/detectors/ArgCopyMutation","sidebar":"sidebar"},{"id":"detectors/AsmIsUsed","path":"/tools/misti/docs/0.3.1/detectors/AsmIsUsed","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/0.3.1/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/0.3.1/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.3.1/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/0.3.1/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/0.3.1/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/InheritedStateMutation","path":"/tools/misti/docs/0.3.1/detectors/InheritedStateMutation","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.3.1/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/0.3.1/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/PreferredStdlibApi","path":"/tools/misti/docs/0.3.1/detectors/PreferredStdlibApi","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.3.1/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/StringReceiversOverlap","path":"/tools/misti/docs/0.3.1/detectors/StringReceiversOverlap","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.3.1/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.3.1/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.3.1/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.3.1/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.3.1/hacking/design","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.3.1/hacking/souffle","sidebar":"sidebar"},{"id":"hacking/tools","path":"/tools/misti/docs/0.3.1/hacking/tools","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.3.1/","sidebar":"sidebar"},{"id":"tutorial/blueprint","path":"/tools/misti/docs/0.3.1/tutorial/blueprint","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/0.3.1/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/cli","path":"/tools/misti/docs/0.3.1/tutorial/cli","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.3.1/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.3.1/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.3.1/","label":"Introduction"}}}},{"name":"0.3.0","label":"0.3.0","isLast":false,"path":"/tools/misti/docs/0.3.0","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/0.3.0/detectors","sidebar":"sidebar"},{"id":"detectors/ArgCopyMutation","path":"/tools/misti/docs/0.3.0/detectors/ArgCopyMutation","sidebar":"sidebar"},{"id":"detectors/AsmIsUsed","path":"/tools/misti/docs/0.3.0/detectors/AsmIsUsed","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/0.3.0/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/0.3.0/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.3.0/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/0.3.0/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/0.3.0/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/InheritedStateMutation","path":"/tools/misti/docs/0.3.0/detectors/InheritedStateMutation","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.3.0/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/0.3.0/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/PreferredStdlibApi","path":"/tools/misti/docs/0.3.0/detectors/PreferredStdlibApi","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.3.0/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/StringReceiversOverlap","path":"/tools/misti/docs/0.3.0/detectors/StringReceiversOverlap","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.3.0/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.3.0/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.3.0/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.3.0/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.3.0/hacking/design","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.3.0/hacking/souffle","sidebar":"sidebar"},{"id":"hacking/tools","path":"/tools/misti/docs/0.3.0/hacking/tools","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.3.0/","sidebar":"sidebar"},{"id":"tutorial/blueprint","path":"/tools/misti/docs/0.3.0/tutorial/blueprint","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/0.3.0/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/cli","path":"/tools/misti/docs/0.3.0/tutorial/cli","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.3.0/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.3.0/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.3.0/","label":"Introduction"}}}},{"name":"0.2.2","label":"0.2.2","isLast":false,"path":"/tools/misti/docs/0.2.2","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/0.2.2/detectors","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/0.2.2/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/0.2.2/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.2.2/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/0.2.2/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/0.2.2/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.2.2/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/0.2.2/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.2.2/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.2.2/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.2.2/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.2.2/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.2.2/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.2.2/hacking/design","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.2.2/hacking/souffle","sidebar":"sidebar"},{"id":"hacking/tools","path":"/tools/misti/docs/0.2.2/hacking/tools","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.2.2/","sidebar":"sidebar"},{"id":"tutorial/blueprint","path":"/tools/misti/docs/0.2.2/tutorial/blueprint","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/0.2.2/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.2.2/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.2.2/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.2.2/","label":"Introduction"}}}},{"name":"0.2.1","label":"0.2.1","isLast":false,"path":"/tools/misti/docs/0.2.1","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/0.2.1/detectors","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/0.2.1/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/0.2.1/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.2.1/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/0.2.1/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/0.2.1/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.2.1/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/0.2.1/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.2.1/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.2.1/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.2.1/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.2.1/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.2.1/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.2.1/hacking/design","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.2.1/hacking/souffle","sidebar":"sidebar"},{"id":"hacking/tools","path":"/tools/misti/docs/0.2.1/hacking/tools","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.2.1/","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/0.2.1/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.2.1/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.2.1/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.2.1/","label":"Introduction"}}}},{"name":"0.2.0","label":"0.2.0","isLast":false,"path":"/tools/misti/docs/0.2.0","mainDocId":"intro","docs":[{"id":"detectors","path":"/tools/misti/docs/0.2.0/detectors","sidebar":"sidebar"},{"id":"detectors/BranchDuplicate","path":"/tools/misti/docs/0.2.0/detectors/BranchDuplicate","sidebar":"sidebar"},{"id":"detectors/ConstantAddress","path":"/tools/misti/docs/0.2.0/detectors/ConstantAddress","sidebar":"sidebar"},{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.2.0/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/DumpIsUsed","path":"/tools/misti/docs/0.2.0/detectors/DumpIsUsed","sidebar":"sidebar"},{"id":"detectors/FieldDoubleInit","path":"/tools/misti/docs/0.2.0/detectors/FieldDoubleInit","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.2.0/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/PreferAugmentedAssign","path":"/tools/misti/docs/0.2.0/detectors/PreferAugmentedAssign","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.2.0/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.2.0/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.2.0/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.2.0/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.2.0/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.2.0/hacking/design","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.2.0/hacking/souffle","sidebar":"sidebar"},{"id":"hacking/tools","path":"/tools/misti/docs/0.2.0/hacking/tools","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.2.0/","sidebar":"sidebar"},{"id":"tutorial/ci-cd","path":"/tools/misti/docs/0.2.0/tutorial/ci-cd","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.2.0/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.2.0/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.2.0/","label":"Introduction"}}}},{"name":"0.1.2","label":"0.1.2","isLast":false,"path":"/tools/misti/docs/0.1.2","mainDocId":"intro","docs":[{"id":"detectors/DivideBeforeMultiply","path":"/tools/misti/docs/0.1.2/detectors/DivideBeforeMultiply","sidebar":"sidebar"},{"id":"detectors/NeverAccessedVariables","path":"/tools/misti/docs/0.1.2/detectors/NeverAccessedVariables","sidebar":"sidebar"},{"id":"detectors/ReadOnlyVariables","path":"/tools/misti/docs/0.1.2/detectors/ReadOnlyVariables","sidebar":"sidebar"},{"id":"detectors/UnboundLoops","path":"/tools/misti/docs/0.1.2/detectors/UnboundLoops","sidebar":"sidebar"},{"id":"detectors/ZeroAddress","path":"/tools/misti/docs/0.1.2/detectors/ZeroAddress","sidebar":"sidebar"},{"id":"hacking/CHANGELOG","path":"/tools/misti/docs/0.1.2/hacking/CHANGELOG","sidebar":"sidebar"},{"id":"hacking/contributing","path":"/tools/misti/docs/0.1.2/hacking/contributing","sidebar":"sidebar"},{"id":"hacking/custom-detector","path":"/tools/misti/docs/0.1.2/hacking/custom-detector","sidebar":"sidebar"},{"id":"hacking/design","path":"/tools/misti/docs/0.1.2/hacking/design","sidebar":"sidebar"},{"id":"hacking/souffle","path":"/tools/misti/docs/0.1.2/hacking/souffle","sidebar":"sidebar"},{"id":"hacking/tools","path":"/tools/misti/docs/0.1.2/hacking/tools","sidebar":"sidebar"},{"id":"intro","path":"/tools/misti/docs/0.1.2/","sidebar":"sidebar"},{"id":"tutorial/configuration","path":"/tools/misti/docs/0.1.2/tutorial/configuration","sidebar":"sidebar"},{"id":"tutorial/getting-started","path":"/tools/misti/docs/0.1.2/tutorial/getting-started","sidebar":"sidebar"}],"draftIds":[],"sidebars":{"sidebar":{"link":{"path":"/tools/misti/docs/0.1.2/","label":"Introduction"}}}}],"breadcrumbs":true}},"docusaurus-plugin-google-gtag":{"default":{"trackingID":["G-8VLF6VGHH5"],"anonymizeIP":true,"id":"default"}}}'),s=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var a=n(2654);const l=JSON.parse('{"docusaurusVersion":"3.4.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.4.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.4.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.4.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.4.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.4.0"},"docusaurus-plugin-google-gtag":{"type":"package","name":"@docusaurus/plugin-google-gtag","version":"3.4.0"}}}');var c=n(4848);const d={siteConfig:r.default,siteMetadata:l,globalData:i,i18n:s,codeTranslations:a},u=o.createContext(d);function p(e){let{children:t}=e;return(0,c.jsx)(u.Provider,{value:d,children:t})}},7489:(e,t,n)=>{"use strict";n.d(t,{A:()=>h});var o=n(6540),r=n(8193),i=n(5260),s=n(440),a=n(781),l=n(3102),c=n(4848);function d(e){let{error:t,tryAgain:n}=e;return(0,c.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,c.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,c.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,c.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,s.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,c.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function p(e){let{children:t}=e;return(0,c.jsx)(l.W,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function f(e){let{error:t,tryAgain:n}=e;return(0,c.jsx)(p,{children:(0,c.jsxs)(h,{fallback:()=>(0,c.jsx)(d,{error:t,tryAgain:n}),children:[(0,c.jsx)(i.A,{children:(0,c.jsx)("title",{children:"Page Error"})}),(0,c.jsx)(a.A,{children:(0,c.jsx)(d,{error:t,tryAgain:n})})]})})}const m=e=>(0,c.jsx)(f,{...e});class h extends o.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){r.A.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??m)(e)}return e??null}}},8193:(e,t,n)=>{"use strict";n.d(t,{A:()=>r});const o="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,r={canUseDOM:o,canUseEventListeners:o&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:o&&"IntersectionObserver"in window,canUseViewport:o&&"screen"in window}},5260:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});n(6540);var o=n(545),r=n(4848);function i(e){return(0,r.jsx)(o.mg,{...e})}},8774:(e,t,n)=>{"use strict";n.d(t,{A:()=>f});var o=n(6540),r=n(4625),i=n(440),s=n(4586),a=n(6654),l=n(8193),c=n(3427),d=n(6025),u=n(4848);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:m,isActive:h,"data-noBrokenLinkCheck":b,autoAddBaseUrl:g=!0,...v}=e;const{siteConfig:y}=(0,s.A)(),{trailingSlash:w,baseUrl:k}=y,x=y.future.experimental_router,{withBaseUrl:_}=(0,d.hH)(),S=(0,c.A)(),A=(0,o.useRef)(null);(0,o.useImperativeHandle)(t,(()=>A.current));const C=p||f;const E=(0,a.A)(C),D=C?.replace("pathname://","");let T=void 0!==D?(R=D,g&&(e=>e.startsWith("/"))(R)?_(R):R):void 0;var R;"hash"===x&&T?.startsWith("./")&&(T=T?.slice(1)),T&&E&&(T=(0,i.applyTrailingSlash)(T,{trailingSlash:w,baseUrl:k}));const L=(0,o.useRef)(!1),O=n?r.k2:r.N_,P=l.A.canUseIntersectionObserver,N=(0,o.useRef)(),I=()=>{L.current||null==T||(window.docusaurus.preload(T),L.current=!0)};(0,o.useEffect)((()=>(!P&&E&&null!=T&&window.docusaurus.prefetch(T),()=>{P&&N.current&&N.current.disconnect()})),[N,T,P,E]);const j=T?.startsWith("#")??!1,M=!v.target||"_self"===v.target,F=!T||!E||!M;return b||!j&&F||S.collectLink(T),v.id&&S.collectAnchor(v.id),F?(0,u.jsx)("a",{ref:A,href:T,...C&&!E&&{target:"_blank",rel:"noopener noreferrer"},...v}):(0,u.jsx)(O,{...v,onMouseEnter:I,onTouchStart:I,innerRef:e=>{A.current=e,P&&e&&E&&(N.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(N.current.unobserve(e),N.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),N.current.observe(e))},to:T,...n&&{isActive:h,activeClassName:m}})}const f=o.forwardRef(p)},418:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const o=()=>null},1312:(e,t,n)=>{"use strict";n.d(t,{A:()=>c,T:()=>l});var o=n(6540),r=n(4848);function i(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,o.isValidElement)(e)))?n.map(((e,t)=>(0,o.isValidElement)(e)?o.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var s=n(2654);function a(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return s[t??n]??n??t}function l(e,t){let{message:n,id:o}=e;return i(a({message:n,id:o}),t)}function c(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("IllegalYour Docusaurus site did not load properly.
\nA very common reason is a wrong site baseUrl configuration.
\nCurrent configured baseUrl = ${e} ${"/"===e?" (default value)":""}
\nWe suggest trying baseUrl =
\nchildren",t),new Error("The Docusaurus component only accept simple string values");const s=a({message:t,id:n});return(0,r.jsx)(r.Fragment,{children:i(s,o)})}},7065:(e,t,n)=>{"use strict";n.d(t,{W:()=>o});const o="default"},6654:(e,t,n)=>{"use strict";function o(e){return/^(?:\w*:|\/\/)/.test(e)}function r(e){return void 0!==e&&!o(e)}n.d(t,{A:()=>r,z:()=>o})},6025:(e,t,n)=>{"use strict";n.d(t,{Ay:()=>a,hH:()=>s});var o=n(6540),r=n(4586),i=n(6654);function s(){const{siteConfig:e}=(0,r.A)(),{baseUrl:t,url:n}=e,s=e.future.experimental_router,a=(0,o.useCallback)(((e,o)=>function(e){let{siteUrl:t,baseUrl:n,url:o,options:{forcePrependBaseUrl:r=!1,absolute:s=!1}={},router:a}=e;if(!o||o.startsWith("#")||(0,i.z)(o))return o;if("hash"===a)return o.startsWith("/")?`.${o}`:`./${o}`;if(r)return n+o.replace(/^\//,"");if(o===n.replace(/\/$/,""))return n;const l=o.startsWith(n)?o:n+o.replace(/^\//,"");return s?t+l:l}({siteUrl:n,baseUrl:t,url:e,options:o,router:s})),[n,t,s]);return{withBaseUrl:a}}function a(e,t){void 0===t&&(t={});const{withBaseUrl:n}=s();return n(e,t)}},3427:(e,t,n)=>{"use strict";n.d(t,{A:()=>s});var o=n(6540);n(4848);const r=o.createContext({collectAnchor:()=>{},collectLink:()=>{}}),i=()=>(0,o.useContext)(r);function s(){return i()}},4586:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var o=n(6540),r=n(6988);function i(){return(0,o.useContext)(r.o)}},2303:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var o=n(6540),r=n(6125);function i(){return(0,o.useContext)(r.o)}},205:(e,t,n)=>{"use strict";n.d(t,{A:()=>r});var o=n(6540);const r=n(8193).A.canUseDOM?o.useLayoutEffect:o.useEffect},6921:(e,t,n)=>{"use strict";n.d(t,{A:()=>r});const o=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function r(e){const t={};return function e(n,r){Object.entries(n).forEach((n=>{let[i,s]=n;const a=r?`${r}.${i}`:i;o(s)?e(s,a):t[a]=s}))}(e),t}},3102:(e,t,n)=>{"use strict";n.d(t,{W:()=>s,o:()=>i});var o=n(6540),r=n(4848);const i=o.createContext(null);function s(e){let{children:t,value:n}=e;const s=o.useContext(i),a=(0,o.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const o={...t.data,...n?.data};return{plugin:t.plugin,data:o}}({parent:s,value:n})),[s,n]);return(0,r.jsx)(i.Provider,{value:a,children:t})}},4070:(e,t,n)=>{"use strict";n.d(t,{zK:()=>h,vT:()=>p,Gy:()=>d,HW:()=>b,ht:()=>u,r7:()=>m,jh:()=>f});var o=n(6347),r=n(4586),i=n(7065);function s(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.A)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const a=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=function(e,t){const n=a(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,o.B6)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),r=n?.docs.find((e=>!!(0,o.B6)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:r,alternateDocVersions:r?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((o=>{o.id===t&&(n[e.name]=o)}))})),n}(r.id):{}}}const c={},d=()=>s("docusaurus-plugin-content-docs")??c,u=e=>{try{return function(e,t,n){void 0===t&&(t=i.W),void 0===n&&(n={});const o=s(e),r=o?.[t];if(!r&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return r}("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw new Error("You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled"+("Default"===e?"":` (pluginId=${e}`),{cause:t})}};function p(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,o.zy)();return function(e,t,n){void 0===n&&(n={});const r=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,o.B6)(t,{path:n.path,exact:!1,strict:!1})})),i=r?{pluginId:r[0],pluginData:r[1]}:void 0;if(!i&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return i}(t,n,e)}function f(e){return u(e).versions}function m(e){const t=u(e);return a(t)}function h(e){const t=u(e),{pathname:n}=(0,o.zy)();return l(t,n)}function b(e){const t=u(e),{pathname:n}=(0,o.zy)();return function(e,t){const n=a(e);return{latestDocSuggestion:l(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},1911:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});const o={onRouteDidUpdate(e){let{location:t,previousLocation:n}=e;!n||t.pathname===n.pathname&&t.search===n.search&&t.hash===n.hash||setTimeout((()=>{window.gtag("set","page_path",t.pathname+t.search+t.hash),window.gtag("event","page_view")}))}}},6294:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var o=n(5947),r=n.n(o);r().configure({showSpinner:!1});const i={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{r().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){r().done()}}},661:(e,t,n)=>{"use strict";var o=n(1765),r=n(4784);!function(e){const{themeConfig:{prism:t}}=r.default,{additionalLanguages:o}=t;globalThis.Prism=e,o.forEach((e=>{n(8692)(`./prism-${e}`)})),n(9325),n(8287),delete globalThis.Prism}(o.My)},1107:(e,t,n)=>{"use strict";n.d(t,{A:()=>d});n(6540);var o=n(4164),r=n(1312),i=n(6342),s=n(8774),a=n(3427);const l={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var c=n(4848);function d(e){let{as:t,id:n,...d}=e;const u=(0,a.A)(),{navbar:{hideOnScroll:p}}=(0,i.p)();if("h1"===t||!n)return(0,c.jsx)(t,{...d,id:void 0});u.collectAnchor(n);const f=(0,r.T)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof d.children?d.children:n});return(0,c.jsxs)(t,{...d,className:(0,o.A)("anchor",p?l.anchorWithHideOnScrollNavbar:l.anchorWithStickyNavbar,d.className),id:n,children:[d.children,(0,c.jsx)(s.A,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},3186:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});n(6540);const o={iconExternalLink:"iconExternalLink_nPIU"};var r=n(4848);function i(e){let{width:t=13.5,height:n=13.5}=e;return(0,r.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:o.iconExternalLink,children:(0,r.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},781:(e,t,n)=>{"use strict";n.d(t,{A:()=>ft});var o=n(6540),r=n(4164),i=n(7489),s=n(1003),a=n(6347),l=n(1312),c=n(5062),d=n(4848);const u="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,o.useRef)(null),{action:t}=(0,a.W6)(),n=(0,o.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(u);t&&p(t)}),[]);return(0,c.$)((n=>{let{location:o}=n;e.current&&!o.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const m=(0,l.T)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??m,{containerRef:n,onClick:o}=f();return(0,d.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,d.jsx)("a",{...e,href:`#${u}`,onClick:o,children:t})})}var b=n(7559),g=n(4090);const v={skipToContent:"skipToContent_fXgn"};function y(){return(0,d.jsx)(h,{className:v.skipToContent})}var w=n(6342),k=n(5041);function x(e){let{width:t=21,height:n=21,color:o="currentColor",strokeWidth:r=1.2,className:i,...s}=e;return(0,d.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...s,children:(0,d.jsx)("g",{stroke:o,strokeWidth:r,children:(0,d.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const _={closeButton:"closeButton_CVFx"};function S(e){return(0,d.jsx)("button",{type:"button","aria-label":(0,l.T)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,r.A)("clean-btn close",_.closeButton,e.className),children:(0,d.jsx)(x,{width:14,height:14,strokeWidth:3.1})})}const A={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,w.p)(),{content:n}=t;return(0,d.jsx)("div",{...e,className:(0,r.A)(A.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const E={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function D(){const{announcementBar:e}=(0,w.p)(),{isActive:t,close:n}=(0,k.M)();if(!t)return null;const{backgroundColor:o,textColor:r,isCloseable:i}=e;return(0,d.jsxs)("div",{className:E.announcementBar,style:{backgroundColor:o,color:r},role:"banner",children:[i&&(0,d.jsx)("div",{className:E.announcementBarPlaceholder}),(0,d.jsx)(C,{className:E.announcementBarContent}),i&&(0,d.jsx)(S,{onClick:n,className:E.announcementBarClose})]})}var T=n(9876),R=n(3104);var L=n(9532),O=n(5600);const P=o.createContext(null);function N(e){let{children:t}=e;const n=function(){const e=(0,T.M)(),t=(0,O.YL)(),[n,r]=(0,o.useState)(!1),i=null!==t.component,s=(0,L.ZC)(i);return(0,o.useEffect)((()=>{i&&!s&&r(!0)}),[i,s]),(0,o.useEffect)((()=>{i?e.shown||r(!0):r(!1)}),[e.shown,i]),(0,o.useMemo)((()=>[n,r]),[n])}();return(0,d.jsx)(P.Provider,{value:n,children:t})}function I(e){if(e.component){const t=e.component;return(0,d.jsx)(t,{...e.props})}}function j(){const e=(0,o.useContext)(P);if(!e)throw new L.dV("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,r=(0,o.useCallback)((()=>n(!1)),[n]),i=(0,O.YL)();return(0,o.useMemo)((()=>({shown:t,hide:r,content:I(i)})),[r,i,t])}function M(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=j();return(0,d.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,d.jsxs)("div",{className:(0,r.A)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i}),children:[(0,d.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,d.jsx)("div",{className:"navbar-sidebar__item menu",children:o})]})]})}var F=n(5293),U=n(2303);function B(e){return(0,d.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,d.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function z(e){return(0,d.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,d.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const $={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function V(e){let{className:t,buttonClassName:n,value:o,onChange:i}=e;const s=(0,U.A)(),a=(0,l.T)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===o?(0,l.T)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.T)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,d.jsx)("div",{className:(0,r.A)($.toggle,t),children:(0,d.jsxs)("button",{className:(0,r.A)("clean-btn",$.toggleButton,!s&&$.toggleButtonDisabled,n),type:"button",onClick:()=>i("dark"===o?"light":"dark"),disabled:!s,title:a,"aria-label":a,"aria-live":"polite",children:[(0,d.jsx)(B,{className:(0,r.A)($.toggleIcon,$.lightToggleIcon)}),(0,d.jsx)(z,{className:(0,r.A)($.toggleIcon,$.darkToggleIcon)})]})})}const q=o.memo(V),H={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function G(e){let{className:t}=e;const n=(0,w.p)().navbar.style,o=(0,w.p)().colorMode.disableSwitch,{colorMode:r,setColorMode:i}=(0,F.G)();return o?null:(0,d.jsx)(q,{className:t,buttonClassName:"dark"===n?H.darkNavbarColorModeToggle:void 0,value:r,onChange:i})}var W=n(3465);function Z(){return(0,d.jsx)(W.A,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,T.M)();return(0,d.jsx)("button",{type:"button","aria-label":(0,l.T)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,d.jsx)(x,{color:"var(--ifm-color-emphasis-600)"})})}function K(){return(0,d.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,d.jsx)(Z,{}),(0,d.jsx)(G,{className:"margin-right--md"}),(0,d.jsx)(Q,{})]})}var Y=n(8774),X=n(6025),J=n(6654);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(3186);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:o,href:r,label:i,html:s,isDropdownLink:a,prependBaseUrlToHref:l,...c}=e;const u=(0,X.Ay)(o),p=(0,X.Ay)(t),f=(0,X.Ay)(r,{forcePrependBaseUrl:!0}),m=i&&r&&!(0,J.A)(r),h=s?{dangerouslySetInnerHTML:{__html:s}}:{children:(0,d.jsxs)(d.Fragment,{children:[i,m&&(0,d.jsx)(te.A,{...a&&{width:12,height:12}})]})};return r?(0,d.jsx)(Y.A,{href:l?f:r,...c,...h}):(0,d.jsx)(Y.A,{to:u,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(p)},...c,...h})}function oe(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=(0,d.jsx)(ne,{className:(0,r.A)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...o});return n?(0,d.jsx)("li",{children:i}):i}function re(e){let{className:t,isDropdownItem:n,...o}=e;return(0,d.jsx)("li",{className:"menu__list-item",children:(0,d.jsx)(ne,{className:(0,r.A)("menu__link",t),...o})})}function ie(e){let{mobile:t=!1,position:n,...o}=e;const r=t?re:oe;return(0,d.jsx)(r,{...o,activeClassName:o.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var se=n(1422),ae=n(9169),le=n(4586);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function de(e,t){return e.some((e=>function(e,t){return!!(0,ae.ys)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:i,onClick:s,...a}=e;const l=(0,o.useRef)(null),[c,u]=(0,o.useState)(!1);return(0,o.useEffect)((()=>{const e=e=>{l.current&&!l.current.contains(e.target)&&u(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[l]),(0,d.jsxs)("div",{ref:l,className:(0,r.A)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,d.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:a.to?void 0:"#",className:(0,r.A)("navbar__link",i),...a,onClick:a.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),u(!c))},children:a.children??a.label}),(0,d.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,o.createElement)(Ae,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:i,onClick:s,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.A)(),{pathname:t}=(0,a.zy)();return t.replace(e,"/")}(),u=de(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:m}=(0,se.u)({initialState:()=>!u});return(0,o.useEffect)((()=>{u&&m(!u)}),[c,u,m]),(0,d.jsxs)("li",{className:(0,r.A)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,d.jsx)(ne,{role:"button",className:(0,r.A)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,d.jsx)(se.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,o.createElement)(Ae,{mobile:!0,isDropdownItem:!0,onClick:s,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const o=t?pe:ue;return(0,d.jsx)(o,{...n})}var me=n(2131);function he(e){let{width:t=20,height:n=20,...o}=e;return(0,d.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...o,children:(0,d.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const be="iconLanguage_nlXk";var ge=n(418);const ve={navbarSearchContainer:"navbarSearchContainer_Bca1"};function ye(e){let{children:t,className:n}=e;return(0,d.jsx)("div",{className:(0,r.A)(n,ve.navbarSearchContainer),children:t})}var we=n(4070),ke=n(1754);var xe=n(5597);const _e=e=>e.docs.find((t=>t.id===e.mainDocId));const Se={default:ie,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:o,queryString:r="",...i}=e;const{i18n:{currentLocale:s,locales:c,localeConfigs:u}}=(0,le.A)(),p=(0,me.o)(),{search:f,hash:m}=(0,a.zy)(),h=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${m}${r}`;return{label:u[e].label,lang:u[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===s?t?"menu__link--active":"dropdown__link--active":""}})),...o],b=t?(0,l.T)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):u[s].label;return(0,d.jsx)(fe,{...i,mobile:t,label:(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(he,{className:be}),b]}),items:h})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,d.jsx)(ye,{className:n,children:(0,d.jsx)(ge.A,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const s=i?"li":"div";return(0,d.jsx)(s,{className:(0,r.A)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:o,...r}=e;const{activeDoc:i}=(0,we.zK)(o),s=(0,ke.QB)(t,o),a=i?.path===s?.path;return null===s||s.unlisted&&!a?null:(0,d.jsx)(ie,{exact:!0,...r,isActive:()=>a||!!i?.sidebar&&i.sidebar===s.sidebar,label:n??s.id,to:s.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:o,...r}=e;const{activeDoc:i}=(0,we.zK)(o),s=(0,ke.fW)(t,o).link;if(!s)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,d.jsx)(ie,{exact:!0,...r,isActive:()=>i?.sidebar===t,label:n??s.label,to:s.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:o,...r}=e;const i=(0,ke.Vd)(o)[0],s=t??i.label,a=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return(0,d.jsx)(ie,{...r,label:s,to:a})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:o,dropdownItemsBefore:r,dropdownItemsAfter:i,...s}=e;const{search:c,hash:u}=(0,a.zy)(),p=(0,we.zK)(n),f=(0,we.jh)(n),{savePreferredVersionName:m}=(0,xe.g1)(n),h=[...r,...f.map((e=>{const t=p.alternateDocVersions[e.name]??_e(e);return{label:e.label,to:`${t.path}${c}${u}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...i],b=(0,ke.Vd)(n)[0],g=t&&h.length>1?(0,l.T)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,v=t&&h.length>1?void 0:_e(b).path;return h.length<=1?(0,d.jsx)(ie,{...s,mobile:t,label:g,to:v,isActive:o?()=>!1:void 0}):(0,d.jsx)(fe,{...s,mobile:t,label:g,to:v,items:h,isActive:o?()=>!1:void 0})}};function Ae(e){let{type:t,...n}=e;const o=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),r=Se[o];if(!r)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,d.jsx)(r,{...n})}function Ce(){const e=(0,T.M)(),t=(0,w.p)().navbar.items;return(0,d.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,o.createElement)(Ae,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Ee(e){return(0,d.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,d.jsx)(l.A,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function De(){const e=0===(0,w.p)().navbar.items.length,t=j();return(0,d.jsxs)(d.Fragment,{children:[!e&&(0,d.jsx)(Ee,{onClick:()=>t.hide()}),t.content]})}function Te(){const e=(0,T.M)();var t;return void 0===(t=e.shown)&&(t=!0),(0,o.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,d.jsx)(M,{header:(0,d.jsx)(K,{}),primaryMenu:(0,d.jsx)(Ce,{}),secondaryMenu:(0,d.jsx)(De,{})}):null}const Re={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Le(e){return(0,d.jsx)("div",{role:"presentation",...e,className:(0,r.A)("navbar-sidebar__backdrop",e.className)})}function Oe(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:i}}=(0,w.p)(),s=(0,T.M)(),{navbarRef:a,isNavbarVisible:u}=function(e){const[t,n]=(0,o.useState)(e),r=(0,o.useRef)(!1),i=(0,o.useRef)(0),s=(0,o.useCallback)((e=>{null!==e&&(i.current=e.getBoundingClientRect().height)}),[]);return(0,R.Mq)(((t,o)=>{let{scrollY:s}=t;if(!e)return;if(s =a?n(!1):s+c {if(!e)return;const o=t.location.hash;if(o?document.getElementById(o.substring(1)):void 0)return r.current=!0,void n(!1);n(!0)})),{navbarRef:s,isNavbarVisible:t}}(n);return(0,d.jsxs)("nav",{ref:a,"aria-label":(0,l.T)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,r.A)("navbar","navbar--fixed-top",n&&[Re.navbarHideable,!u&&Re.navbarHidden],{"navbar--dark":"dark"===i,"navbar--primary":"primary"===i,"navbar-sidebar--show":s.shown}),children:[t,(0,d.jsx)(Le,{onClick:s.toggle}),(0,d.jsx)(Te,{})]})}var Pe=n(440);const Ne={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function Ie(e){return(0,d.jsx)("button",{type:"button",...e,children:(0,d.jsx)(l.A,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function je(e){let{error:t}=e;const n=(0,Pe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,d.jsx)("p",{className:Ne.errorBoundaryError,children:n})}class Me extends o.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const Fe="right";function Ue(e){let{width:t=30,height:n=30,className:o,...r}=e;return(0,d.jsx)("svg",{className:o,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...r,children:(0,d.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function Be(){const{toggle:e,shown:t}=(0,T.M)();return(0,d.jsx)("button",{onClick:e,"aria-label":(0,l.T)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,d.jsx)(Ue,{})})}const ze={colorModeToggle:"colorModeToggle_DEke"};function $e(e){let{items:t}=e;return(0,d.jsx)(d.Fragment,{children:t.map(((e,t)=>(0,d.jsx)(Me,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,d.jsx)(Ae,{...e})},t)))})}function Ve(e){let{left:t,right:n}=e;return(0,d.jsxs)("div",{className:"navbar__inner",children:[(0,d.jsx)("div",{className:"navbar__items",children:t}),(0,d.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function qe(){const e=(0,T.M)(),t=(0,w.p)().navbar.items,[n,o]=function(e){function t(e){return"left"===(e.position??Fe)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),r=t.find((e=>"search"===e.type));return(0,d.jsx)(Ve,{left:(0,d.jsxs)(d.Fragment,{children:[!e.disabled&&(0,d.jsx)(Be,{}),(0,d.jsx)(Z,{}),(0,d.jsx)($e,{items:n})]}),right:(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)($e,{items:o}),(0,d.jsx)(G,{className:ze.colorModeToggle}),!r&&(0,d.jsx)(ye,{children:(0,d.jsx)(ge.A,{})})]})})}function He(){return(0,d.jsx)(Oe,{children:(0,d.jsx)(qe,{})})}function Ge(e){let{item:t}=e;const{to:n,href:o,label:r,prependBaseUrlToHref:i,...s}=t,a=(0,X.Ay)(n),l=(0,X.Ay)(o,{forcePrependBaseUrl:!0});return(0,d.jsxs)(Y.A,{className:"footer__link-item",...o?{href:i?l:o}:{to:a},...s,children:[r,o&&!(0,J.A)(o)&&(0,d.jsx)(te.A,{})]})}function We(e){let{item:t}=e;return t.html?(0,d.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,d.jsx)("li",{className:"footer__item",children:(0,d.jsx)(Ge,{item:t})},t.href??t.to)}function Ze(e){let{column:t}=e;return(0,d.jsxs)("div",{className:"col footer__col",children:[(0,d.jsx)("div",{className:"footer__title",children:t.title}),(0,d.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,d.jsx)(We,{item:e},t)))})]})}function Qe(e){let{columns:t}=e;return(0,d.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,d.jsx)(Ze,{column:e},t)))})}function Ke(){return(0,d.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function Ye(e){let{item:t}=e;return t.html?(0,d.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,d.jsx)(Ge,{item:t})}function Xe(e){let{links:t}=e;return(0,d.jsx)("div",{className:"footer__links text--center",children:(0,d.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,d.jsxs)(o.Fragment,{children:[(0,d.jsx)(Ye,{item:e}),t.length!==n+1&&(0,d.jsx)(Ke,{})]},n)))})})}function Je(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,d.jsx)(Qe,{columns:t}):(0,d.jsx)(Xe,{links:t})}var et=n(1122);const tt={footerLogoLink:"footerLogoLink_BH7S"};function nt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.hH)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,d.jsx)(et.A,{className:(0,r.A)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function ot(e){let{logo:t}=e;return t.href?(0,d.jsx)(Y.A,{href:t.href,className:tt.footerLogoLink,target:t.target,children:(0,d.jsx)(nt,{logo:t})}):(0,d.jsx)(nt,{logo:t})}function rt(e){let{copyright:t}=e;return(0,d.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function it(e){let{style:t,links:n,logo:o,copyright:i}=e;return(0,d.jsx)("footer",{className:(0,r.A)("footer",{"footer--dark":"dark"===t}),children:(0,d.jsxs)("div",{className:"container container-fluid",children:[n,(o||i)&&(0,d.jsxs)("div",{className:"footer__bottom text--center",children:[o&&(0,d.jsx)("div",{className:"margin-bottom--sm",children:o}),i]})]})})}function st(){const{footer:e}=(0,w.p)();if(!e)return null;const{copyright:t,links:n,logo:o,style:r}=e;return(0,d.jsx)(it,{style:r,links:n&&n.length>0&&(0,d.jsx)(Je,{links:n}),logo:o&&(0,d.jsx)(ot,{logo:o}),copyright:t&&(0,d.jsx)(rt,{copyright:t})})}const at=o.memo(st),lt=(0,L.fM)([F.a,k.o,R.Tv,xe.VQ,s.Jx,function(e){let{children:t}=e;return(0,d.jsx)(O.y_,{children:(0,d.jsx)(T.e,{children:(0,d.jsx)(N,{children:t})})})}]);function ct(e){let{children:t}=e;return(0,d.jsx)(lt,{children:t})}var dt=n(1107);function ut(e){let{error:t,tryAgain:n}=e;return(0,d.jsx)("main",{className:"container margin-vert--xl",children:(0,d.jsx)("div",{className:"row",children:(0,d.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,d.jsx)(dt.A,{as:"h1",className:"hero__title",children:(0,d.jsx)(l.A,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,d.jsx)("div",{className:"margin-vert--lg",children:(0,d.jsx)(Ie,{onClick:n,className:"button button--primary shadow--lw"})}),(0,d.jsx)("hr",{}),(0,d.jsx)("div",{className:"margin-vert--md",children:(0,d.jsx)(je,{error:t})})]})})})}const pt={mainWrapper:"mainWrapper_z2l0"};function ft(e){const{children:t,noFooter:n,wrapperClassName:o,title:a,description:l}=e;return(0,g.J)(),(0,d.jsxs)(ct,{children:[(0,d.jsx)(s.be,{title:a,description:l}),(0,d.jsx)(y,{}),(0,d.jsx)(D,{}),(0,d.jsx)(He,{}),(0,d.jsx)("div",{id:u,className:(0,r.A)(b.G.wrapper.main,pt.mainWrapper,o),children:(0,d.jsx)(i.A,{fallback:e=>(0,d.jsx)(ut,{...e}),children:t})}),!n&&(0,d.jsx)(at,{})]})}},3465:(e,t,n)=>{"use strict";n.d(t,{A:()=>d});n(6540);var o=n(8774),r=n(6025),i=n(4586),s=n(6342),a=n(1122),l=n(4848);function c(e){let{logo:t,alt:n,imageClassName:o}=e;const i={light:(0,r.Ay)(t.src),dark:(0,r.Ay)(t.srcDark||t.src)},s=(0,l.jsx)(a.A,{className:t.className,sources:i,height:t.height,width:t.width,alt:n,style:t.style});return o?(0,l.jsx)("div",{className:o,children:s}):s}function d(e){const{siteConfig:{title:t}}=(0,i.A)(),{navbar:{title:n,logo:a}}=(0,s.p)(),{imageClassName:d,titleClassName:u,...p}=e,f=(0,r.Ay)(a?.href||"/"),m=n?"":t,h=a?.alt??m;return(0,l.jsxs)(o.A,{to:f,...p,...a?.target&&{target:a.target},children:[a&&(0,l.jsx)(c,{logo:a,alt:h,imageClassName:d}),null!=n&&(0,l.jsx)("b",{className:u,children:n})]})}},1463:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});n(6540);var o=n(5260),r=n(4848);function i(e){let{locale:t,version:n,tag:i}=e;const s=t;return(0,r.jsxs)(o.A,{children:[t&&(0,r.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,r.jsx)("meta",{name:"docusaurus_version",content:n}),i&&(0,r.jsx)("meta",{name:"docusaurus_tag",content:i}),s&&(0,r.jsx)("meta",{name:"docsearch:language",content:s}),n&&(0,r.jsx)("meta",{name:"docsearch:version",content:n}),i&&(0,r.jsx)("meta",{name:"docsearch:docusaurus_tag",content:i})]})}},1122:(e,t,n)=>{"use strict";n.d(t,{A:()=>d});var o=n(6540),r=n(4164),i=n(2303),s=n(5293);const a={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var l=n(4848);function c(e){let{className:t,children:n}=e;const c=(0,i.A)(),{colorMode:d}=(0,s.G)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===d?["dark"]:["light"]:["light","dark"]).map((e=>{const i=n({theme:e,className:(0,r.A)(t,a.themedComponent,a[`themedComponent--${e}`])});return(0,l.jsx)(o.Fragment,{children:i},e)}))})}function d(e){const{sources:t,className:n,alt:o,...r}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:i}=e;return(0,l.jsx)("img",{src:t[n],alt:o,className:i,...r})}})}},1422:(e,t,n)=>{"use strict";n.d(t,{N:()=>g,u:()=>c});var o=n(6540),r=n(8193),i=n(205),s=n(3109),a=n(4848);const l="ease-in-out";function c(e){let{initialState:t}=e;const[n,r]=(0,o.useState)(t??!1),i=(0,o.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:i}}const d={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?d:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const i=(0,o.useRef)(!1);(0,o.useEffect)((()=>{const e=t.current;function o(){const t=e.scrollHeight,n=r?.duration??function(e){if((0,s.O)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??l}`,height:`${t}px`}}function a(){const t=o();e.style.transition=t.transition,e.style.height=t.height}if(!i.current)return p(e,n),void(i.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(a(),requestAnimationFrame((()=>{e.style.height=d.height,e.style.overflow=d.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{a()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function m(e){if(!r.A.canUseDOM)return e?d:u}function h(e){let{as:t="div",collapsed:n,children:r,animation:i,onCollapseTransitionEnd:s,className:l,disableSSRStyle:c}=e;const d=(0,o.useRef)(null);return f({collapsibleRef:d,collapsed:n,animation:i}),(0,a.jsx)(t,{ref:d,style:c?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(d.current,n),s?.(n))},className:l,children:r})}function b(e){let{collapsed:t,...n}=e;const[r,s]=(0,o.useState)(!t),[l,c]=(0,o.useState)(t);return(0,i.A)((()=>{t||s(!0)}),[t]),(0,i.A)((()=>{r&&c(t)}),[r,t]),r?(0,a.jsx)(h,{...n,collapsed:l}):null}function g(e){let{lazy:t,...n}=e;const o=t?b:h;return(0,a.jsx)(o,{...n})}},5041:(e,t,n)=>{"use strict";n.d(t,{M:()=>h,o:()=>m});var o=n(6540),r=n(2303),i=n(679),s=n(9532),a=n(6342),l=n(4848);const c=(0,i.Wf)("docusaurus.announcement.dismiss"),d=(0,i.Wf)("docusaurus.announcement.id"),u=()=>"true"===c.get(),p=e=>c.set(String(e)),f=o.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,a.p)(),t=(0,r.A)(),[n,i]=(0,o.useState)((()=>!!t&&u()));(0,o.useEffect)((()=>{i(u())}),[]);const s=(0,o.useCallback)((()=>{p(!0),i(!0)}),[]);return(0,o.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=d.get();"annoucement-bar"===n&&(n="announcement-bar");const o=t!==n;d.set(t),o&&p(!1),!o&&u()||i(!1)}),[e]),(0,o.useMemo)((()=>({isActive:!!e&&!n,close:s})),[e,n,s])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function h(){const e=(0,o.useContext)(f);if(!e)throw new s.dV("AnnouncementBarProvider");return e}},5293:(e,t,n)=>{"use strict";n.d(t,{G:()=>g,a:()=>b});var o=n(6540),r=n(8193),i=n(9532),s=n(679),a=n(6342),l=n(4848);const c=o.createContext(void 0),d="theme",u=(0,s.Wf)(d),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,m=e=>r.A.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),h=e=>{u.set(f(e))};function b(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,a.p)(),[r,i]=(0,o.useState)(m(e));(0,o.useEffect)((()=>{t&&u.del()}),[t]);const s=(0,o.useCallback)((function(t,o){void 0===o&&(o={});const{persist:r=!0}=o;t?(i(t),r&&h(t)):(i(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),u.del())}),[n,e]);(0,o.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(r))}),[r]),(0,o.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==d)return;const t=u.get();null!==t&&s(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,s]);const l=(0,o.useRef)(!1);return(0,o.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),o=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:s(null)};return e.addListener(o),()=>e.removeListener(o)}),[s,t,n]),(0,o.useMemo)((()=>({colorMode:r,setColorMode:s,get isDarkTheme(){return r===p.dark},setLightTheme(){s(p.light)},setDarkTheme(){s(p.dark)}})),[r,s])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function g(){const e=(0,o.useContext)(c);if(null==e)throw new i.dV("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},5597:(e,t,n)=>{"use strict";n.d(t,{VQ:()=>g,g1:()=>y});var o=n(6540),r=n(4070),i=n(7065),s=n(6342),a=n(1754),l=n(9532),c=n(679),d=n(4848);const u=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.Wf)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.Wf)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.Wf)(u(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const m=o.createContext(null);function h(){const e=(0,r.Gy)(),t=(0,s.p)().docs.versionPersistence,n=(0,o.useMemo)((()=>Object.keys(e)),[e]),[i,a]=(0,o.useState)((()=>f(n)));(0,o.useEffect)((()=>{a(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:o}=e;function r(e){const t=p.read(e,n);return o[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,r(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[i,(0,o.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),a((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function b(e){let{children:t}=e;const n=h();return(0,d.jsx)(m.Provider,{value:n,children:t})}function g(e){let{children:t}=e;return a.C5?(0,d.jsx)(b,{children:t}):(0,d.jsx)(d.Fragment,{children:t})}function v(){const e=(0,o.useContext)(m);if(!e)throw new l.dV("DocsPreferredVersionContextProvider");return e}function y(e){void 0===e&&(e=i.W);const t=(0,r.ht)(e),[n,s]=v(),{preferredVersionName:a}=n[e];return{preferredVersion:t.versions.find((e=>e.name===a))??null,savePreferredVersionName:(0,o.useCallback)((t=>{s.savePreferredVersion(e,t)}),[s,e])}}},6588:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,t:()=>c});var o=n(6540),r=n(9532),i=n(4848);const s=Symbol("EmptyContext"),a=o.createContext(s);function l(e){let{children:t,name:n,items:r}=e;const s=(0,o.useMemo)((()=>n&&r?{name:n,items:r}:null),[n,r]);return(0,i.jsx)(a.Provider,{value:s,children:t})}function c(){const e=(0,o.useContext)(a);if(e===s)throw new r.dV("DocsSidebarProvider");return e}},2252:(e,t,n)=>{"use strict";n.d(t,{n:()=>a,r:()=>l});var o=n(6540),r=n(9532),i=n(4848);const s=o.createContext(null);function a(e){let{children:t,version:n}=e;return(0,i.jsx)(s.Provider,{value:n,children:t})}function l(){const e=(0,o.useContext)(s);if(null===e)throw new r.dV("DocsVersionProvider");return e}},9876:(e,t,n)=>{"use strict";n.d(t,{e:()=>f,M:()=>m});var o=n(6540),r=n(5600),i=n(4581),s=n(6347),a=n(9532);function l(e){!function(e){const t=(0,s.W6)(),n=(0,a._q)(e);(0,o.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var c=n(6342),d=n(4848);const u=o.createContext(void 0);function p(){const e=function(){const e=(0,r.YL)(),{items:t}=(0,c.p)().navbar;return 0===t.length&&!e.component}(),t=(0,i.l)(),n=!e&&"mobile"===t,[s,a]=(0,o.useState)(!1);l((()=>{if(s)return a(!1),!1}));const d=(0,o.useCallback)((()=>{a((e=>!e))}),[]);return(0,o.useEffect)((()=>{"desktop"===t&&a(!1)}),[t]),(0,o.useMemo)((()=>({disabled:e,shouldRender:n,toggle:d,shown:s})),[e,n,d,s])}function f(e){let{children:t}=e;const n=p();return(0,d.jsx)(u.Provider,{value:n,children:t})}function m(){const e=o.useContext(u);if(void 0===e)throw new a.dV("NavbarMobileSidebarProvider");return e}},5600:(e,t,n)=>{"use strict";n.d(t,{GX:()=>c,YL:()=>l,y_:()=>a});var o=n(6540),r=n(9532),i=n(4848);const s=o.createContext(null);function a(e){let{children:t}=e;const n=(0,o.useState)({component:null,props:null});return(0,i.jsx)(s.Provider,{value:n,children:t})}function l(){const e=(0,o.useContext)(s);if(!e)throw new r.dV("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const i=(0,o.useContext)(s);if(!i)throw new r.dV("NavbarSecondaryMenuContentProvider");const[,a]=i,l=(0,r.Be)(n);return(0,o.useEffect)((()=>{a({component:t,props:l})}),[a,t,l]),(0,o.useEffect)((()=>()=>a({component:null,props:null})),[a]),null}},4090:(e,t,n)=>{"use strict";n.d(t,{w:()=>r,J:()=>i});var o=n(6540);const r="navigation-with-keyboard";function i(){(0,o.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(r),"mousedown"===e.type&&document.body.classList.remove(r)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(r),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},4581:(e,t,n)=>{"use strict";n.d(t,{l:()=>a});var o=n(6540),r=n(8193);const i={desktop:"desktop",mobile:"mobile",ssr:"ssr"},s=996;function a(e){let{desktopBreakpoint:t=s}=void 0===e?{}:e;const[n,a]=(0,o.useState)((()=>"ssr"));return(0,o.useEffect)((()=>{function e(){a(function(e){if(!r.A.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?i.desktop:i.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},7559:(e,t,n)=>{"use strict";n.d(t,{G:()=>o});const o={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},3109:(e,t,n)=>{"use strict";function o(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{O:()=>o})},1754:(e,t,n)=>{"use strict";n.d(t,{Nr:()=>f,w8:()=>b,C5:()=>p,B5:()=>S,Vd:()=>k,QB:()=>_,fW:()=>x,OF:()=>w,Y:()=>v});var o=n(6540),r=n(6347),i=n(2831),s=n(4070),a=n(5597),l=n(2252),c=n(6588);function d(e){return Array.from(new Set(e))}var u=n(9169);const p=!!s.Gy;function f(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=f(t);if(e)return e}}(e):void 0:e.href}const m=(e,t)=>void 0!==e&&(0,u.ys)(e,t),h=(e,t)=>e.some((e=>b(e,t)));function b(e,t){return"link"===e.type?m(e.href,t):"category"===e.type&&(m(e.href,t)||h(e.items,t))}function g(e,t){switch(e.type){case"category":return b(e,t)||e.items.some((e=>g(e,t)));case"link":return!e.unlisted||b(e,t);default:return!0}}function v(e,t){return(0,o.useMemo)((()=>e.filter((e=>g(e,t)))),[e,t])}function y(e){let{sidebarItems:t,pathname:n,onlyCategories:o=!1}=e;const r=[];return function e(t){for(const i of t)if("category"===i.type&&((0,u.ys)(i.href,n)||e(i.items))||"link"===i.type&&(0,u.ys)(i.href,n)){return o&&"category"!==i.type||r.unshift(i),!0}return!1}(t),r}function w(){const e=(0,c.t)(),{pathname:t}=(0,r.zy)(),n=(0,s.vT)()?.pluginData.breadcrumbs;return!1!==n&&e?y({sidebarItems:e.items,pathname:t}):null}function k(e){const{activeVersion:t}=(0,s.zK)(e),{preferredVersion:n}=(0,a.g1)(e),r=(0,s.r7)(e);return(0,o.useMemo)((()=>d([t,n,r].filter(Boolean))),[t,n,r])}function x(e,t){const n=k(t);return(0,o.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),o=t.find((t=>t[0]===e));if(!o)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return o[1]}),[e,n])}function _(e,t){const n=k(t);return(0,o.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),o=t.find((t=>t.id===e));if(!o){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${d(t.map((e=>e.id))).join("\n- ")}`)}return o}),[e,n])}function S(e){let{route:t}=e;const n=(0,r.zy)(),o=(0,l.r)(),s=t.routes,a=s.find((e=>(0,r.B6)(n.pathname,e)));if(!a)return null;const c=a.sidebar,d=c?o.docsSidebars[c]:void 0;return{docElement:(0,i.v)(s),sidebarName:c,sidebarItems:d}}},1003:(e,t,n)=>{"use strict";n.d(t,{e3:()=>f,be:()=>u,Jx:()=>m});var o=n(6540),r=n(4164),i=n(5260),s=n(3102);function a(){const e=o.useContext(s.o);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(6025),c=n(4586);var d=n(4848);function u(e){let{title:t,description:n,keywords:o,image:r,children:s}=e;const a=function(e){const{siteConfig:t}=(0,c.A)(),{title:n,titleDelimiter:o}=t;return e?.trim().length?`${e.trim()} ${o} ${n}`:n}(t),{withBaseUrl:u}=(0,l.hH)(),p=r?u(r,{absolute:!0}):void 0;return(0,d.jsxs)(i.A,{children:[t&&(0,d.jsx)("title",{children:a}),t&&(0,d.jsx)("meta",{property:"og:title",content:a}),n&&(0,d.jsx)("meta",{name:"description",content:n}),n&&(0,d.jsx)("meta",{property:"og:description",content:n}),o&&(0,d.jsx)("meta",{name:"keywords",content:Array.isArray(o)?o.join(","):o}),p&&(0,d.jsx)("meta",{property:"og:image",content:p}),p&&(0,d.jsx)("meta",{name:"twitter:image",content:p}),s]})}const p=o.createContext(void 0);function f(e){let{className:t,children:n}=e;const s=o.useContext(p),a=(0,r.A)(s,t);return(0,d.jsxs)(p.Provider,{value:a,children:[(0,d.jsx)(i.A,{children:(0,d.jsx)("html",{className:a})}),n]})}function m(e){let{children:t}=e;const n=a(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return(0,d.jsx)(f,{className:(0,r.A)(o,i),children:t})}},9532:(e,t,n)=>{"use strict";n.d(t,{Be:()=>c,ZC:()=>a,_q:()=>s,dV:()=>l,fM:()=>d});var o=n(6540),r=n(205),i=n(4848);function s(e){const t=(0,o.useRef)(e);return(0,r.A)((()=>{t.current=e}),[e]),(0,o.useCallback)((function(){return t.current(...arguments)}),[])}function a(e){const t=(0,o.useRef)();return(0,r.A)((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(? \w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,o.useMemo)((()=>e),t.flat())}function d(e){return t=>{let{children:n}=t;return(0,i.jsx)(i.Fragment,{children:e.reduceRight(((e,t)=>(0,i.jsx)(t,{children:e})),n)})}}},9169:(e,t,n)=>{"use strict";n.d(t,{Dt:()=>a,ys:()=>s});var o=n(6540),r=n(8328),i=n(4586);function s(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function a(){const{baseUrl:e}=(0,i.A)().siteConfig;return(0,o.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function o(e){return e.path===t&&!0===e.exact}function r(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(o)||e(t.filter(r).flatMap((e=>e.routes??[])))}(n)}({routes:r.A,baseUrl:e})),[e])}},3104:(e,t,n)=>{"use strict";n.d(t,{Mq:()=>p,Tv:()=>c,gk:()=>f});var o=n(6540),r=n(8193),i=n(2303),s=(n(205),n(9532)),a=n(4848);const l=o.createContext(void 0);function c(e){let{children:t}=e;const n=function(){const e=(0,o.useRef)(!0);return(0,o.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,a.jsx)(l.Provider,{value:n,children:t})}function d(){const e=(0,o.useContext)(l);if(null==e)throw new s.dV("ScrollControllerProvider");return e}const u=()=>r.A.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=d(),r=(0,o.useRef)(u()),i=(0,s._q)(e);(0,o.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();i(e,r.current),r.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[i,n,...t])}function f(){const e=(0,o.useRef)(null),t=(0,i.A)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function o(){const r=document.documentElement.scrollTop;(n&&r>e||!n&&r t&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},2967:(e,t,n)=>{"use strict";n.d(t,{Cy:()=>o,tU:()=>r});n(4586);const o="default";function r(e,t){return`docs-${e}-${t}`}},679:(e,t,n)=>{"use strict";n.d(t,{Wf:()=>c});n(6540);const o=JSON.parse('{"N":"localStorage","M":""}'),r=o.N;function i(e){let{key:t,oldValue:n,newValue:o,storage:r}=e;if(n===o)return;const i=document.createEvent("StorageEvent");i.initStorageEvent("storage",!1,!1,t,n,o,window.location.href,r),window.dispatchEvent(i)}function s(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,a||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),a=!0),null}var t}let a=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(e,t){const n=`${e}${o.M}`;if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(n);const r=s(t?.persistence);return null===r?l:{get:()=>{try{return r.getItem(n)}catch(e){return console.error(`Docusaurus storage error, can't get key=${n}`,e),null}},set:e=>{try{const t=r.getItem(n);r.setItem(n,e),i({key:n,oldValue:t,newValue:e,storage:r})}catch(t){console.error(`Docusaurus storage error, can't set ${n}=${e}`,t)}},del:()=>{try{const e=r.getItem(n);r.removeItem(n),i({key:n,oldValue:e,newValue:null,storage:r})}catch(e){console.error(`Docusaurus storage error, can't delete key=${n}`,e)}},listen:e=>{try{const t=t=>{t.storageArea===r&&t.key===n&&e(t)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)}catch(t){return console.error(`Docusaurus storage error, can't listen for changes of key=${n}`,t),()=>{}}}}}},2131:(e,t,n)=>{"use strict";n.d(t,{o:()=>s});var o=n(4586),r=n(6347),i=n(440);function s(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:s,currentLocale:a}}=(0,o.A)(),{pathname:l}=(0,r.zy)(),c=(0,i.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),d=a===s?e:e.replace(`/${a}/`,"/"),u=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:o}=e;return`${o?t:""}${function(e){return e===s?`${d}`:`${d}${e}/`}(n)}${u}`}}}},5062:(e,t,n)=>{"use strict";n.d(t,{$:()=>s});var o=n(6540),r=n(6347),i=n(9532);function s(e){const t=(0,r.zy)(),n=(0,i.ZC)(t),s=(0,i._q)(e);(0,o.useEffect)((()=>{n&&t!==n&&s({location:t,previousLocation:n})}),[s,t,n])}},6342:(e,t,n)=>{"use strict";n.d(t,{p:()=>r});var o=n(4586);function r(){return(0,o.A)().siteConfig.themeConfig}},2983:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.removeTrailingSlash=t.addLeadingSlash=t.addTrailingSlash=void 0;const o=n(2566);function r(e){return e.endsWith("/")?e:`${e}/`}function i(e){return(0,o.removeSuffix)(e,"/")}t.addTrailingSlash=r,t.default=function(e,t){const{trailingSlash:n,baseUrl:o}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[s]=e.split(/[#?]/),a="/"===s||s===o?s:(l=s,n?r(l):i(l));var l;return e.replace(s,a)},t.addLeadingSlash=function(e){return(0,o.addPrefix)(e,"/")},t.removeTrailingSlash=i},253:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},440:function(e,t,n){"use strict";var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.removePrefix=t.addSuffix=t.removeSuffix=t.addPrefix=t.removeTrailingSlash=t.addLeadingSlash=t.addTrailingSlash=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var r=n(2983);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return o(r).default}}),Object.defineProperty(t,"addTrailingSlash",{enumerable:!0,get:function(){return r.addTrailingSlash}}),Object.defineProperty(t,"addLeadingSlash",{enumerable:!0,get:function(){return r.addLeadingSlash}}),Object.defineProperty(t,"removeTrailingSlash",{enumerable:!0,get:function(){return r.removeTrailingSlash}});var i=n(2566);Object.defineProperty(t,"addPrefix",{enumerable:!0,get:function(){return i.addPrefix}}),Object.defineProperty(t,"removeSuffix",{enumerable:!0,get:function(){return i.removeSuffix}}),Object.defineProperty(t,"addSuffix",{enumerable:!0,get:function(){return i.addSuffix}}),Object.defineProperty(t,"removePrefix",{enumerable:!0,get:function(){return i.removePrefix}});var s=n(253);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return s.getErrorCausalChain}})},2566:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.removePrefix=t.addSuffix=t.removeSuffix=t.addPrefix=void 0,t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){return""===t?e:e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},8287:()=>{!function(e){var t=[{pattern:/"""[\s\S]*?"""[Hhcusa]?/,greedy:!0,inside:{symbol:{pattern:/("""[\s\S]*?""")[Hhcusa]/,lookbehind:!0,greedy:!0}}},{pattern:/"[^\n"]*"[Hhcusa]?/,greedy:!0,inside:{symbol:{pattern:/("[^\n"]*")[Hhcusa]/,lookbehind:!0,greedy:!0}}}],n=/(?:!=|\?|:|%=|%|&=|&|\*=|\*|\+=|\+|->|-=|-|\/%|\/=|\/|<=>|<<=|<<|<=|<|==|=|>>=|>>|>=|>|\^>>=|\^>>|\^=|\^\/=|\^\/|\^%=|\^%|\^|\|=|\||~>>=|~>>|~\/=|~\/|~%|~)(?=\s)/,o=[/`[^`\n]+`/,/[^\.~,;\[\]\(\)\s]+/];e.languages.func={comment:[{pattern:/;;.*/,lookbehind:!0,greedy:!0},{pattern:/\{-[\s\S]*?(?:-\}|$)/,lookbehind:!0,greedy:!0},{pattern:/\b_\b(?![^\.~,;\[\]\(\)\s])/}],pragma:{pattern:/#pragma(.*);/,inside:{keyword:/(?:#pragma|test-version-set|not-version|version|allow-post-modification|compute-asm-ltr)\b/,number:/(?:\d+)(?:.\d+)?(?:.\d+)?/,operator:/=|\^|<=|>=|<|>/,string:t,punctuation:/;/}},include:{pattern:/#include(.*);/,inside:{keyword:/#include\b/,string:t,punctuation:/;/}},builtin:/\b(?:int|cell|slice|builder|cont|tuple|type)\b/,boolean:/\b(?:false|true|nil|Nil)\b/,keyword:/\b(?:forall|extern|global|asm|impure|inline_ref|inline|auto_apply|method_id|operator|infixl|infixr|infix|const|return|var|repeat|do|while|until|try|catch|ifnot|if|then|elseifnot|elseif|else)\b/,number:/-?\b(?:\d+|0x[\da-fA-F]+)\b(?![^\.~,;\[\]\(\)\s])/,string:t,operator:n,punctuation:[/[\.,;\(\)\[\]]/,/[\{\}](?![^\.~,;\[\]\(\)\s])/],function:[{pattern:new RegExp(o[0].source+/(?=\s*\()/.source),greedy:!0},{pattern:/~_/,greedy:!0},{pattern:new RegExp(/\^?_/.source+n.source+/_/.source),greedy:!0},{pattern:new RegExp(/[\.~]?/.source+o[1].source+/(?=\s*\()/.source),greedy:!0},{pattern:/\b(?:divmod|moddiv|muldiv|muldivr|muldivc|muldivmod|null\?|throw|throw_if|throw_unless|throw_arg|throw_arg_if|throw_arg_unless|load_int|load_uint|preload_int|preload_uint|store_int|store_uint|load_bits|preload_bits|int_at|cell_at|slice_at|tuple_at|at|touch|touch2|run_method0|run_method1|run_method2|run_method3|~divmod|~moddiv|~store_int|~store_uint|~touch|~touch2|~dump|~stdump)\b/,greedy:!0}],"class-name":/[A-Z][^\.~,;\[\]\(\)\s]*/,variable:o.map((e=>({pattern:e,greedy:!0})))},e.languages.fc=e.languages.func}(Prism)},9325:()=>{!function(e){e.languages.tact={keyword:[{pattern:/\b(?:abstract|asm|as|catch|const|contract(?!:)|do|else|extend|extends|foreach|fun|get|if|in|import|initOf|inline|let|message(?!:)|mutates|native|override|primitive|public|repeat|return|self|struct(?!:)|trait(?!:)|try|until|virtual|while|with)\b/},{pattern:/\b(?:bounced|external|init|receive)\b(?=\()/}],builtin:[{pattern:/\b(?:Address|Bool|Builder|Cell|Int|Slice|String|StringBuilder)\b/},{pattern:/(\bas\s+)(?:coins|remaining|bytes32|bytes64|int257|u?int(?:2[0-5][0-6]|1[0-9][0-9]|[1-9][0-9]?))\b/,lookbehind:!0,greedy:!0}],constant:[{pattern:/\bnull\b/},{pattern:/\b[A-Z][A-Z0-9_]*\b/}],"class-name":{pattern:/\b[A-Z]\w*\b/},attribute:[{pattern:/@name/,inside:{function:/.+/}},{pattern:/@interface/,inside:{function:/.+/}}],function:{pattern:/\b\w+(?=\()/},boolean:{pattern:/\b(?:false|true)\b/},number:[{pattern:/\b0x[0-9a-f](?:_?[0-9a-f])*\b/i},{pattern:/\b0o[0-7](?:_?[0-7])*\b/i},{pattern:/\b0b[01](?:_?[01])*\b/i},{pattern:/\b0\d*\b/},{pattern:/\b[1-9](?:_?\d)*\b/}],string:void 0,punctuation:{pattern:/[{}[\]();,.:?]/},comment:[{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/\b_\b/}],operator:{pattern:/![!=]?|->|[+\-*/%=]=?|[<>]=|<|>>?|~|\|[\|=]?|&[&=]?|\^=?/},variable:{pattern:/\b[a-zA-Z_]\w*\b/}},e.languages.insertBefore("tact","string",{"string-literal":{pattern:/(?:(")(?:\\.|(?!\1)[^\\\r\n])*\1(?!\1))/,greedy:!0,inside:{regex:[{pattern:/\\[\\"nrtvbf]/},{pattern:/\\x[0-9a-fA-F]{2}/},{pattern:/\\u[0-9a-fA-F]{4}/},{pattern:/\\u\{[0-9a-fA-F]{1,6}\}/}],string:{pattern:/[\s\S]+/}}}}),e.languages.insertBefore("tact","keyword",{generics:{pattern:/(?:\b(?:bounced|map)\b<[^\\\r\n]*>)/,greedy:!0,inside:{builtin:[...e.languages.tact.builtin,{pattern:/\b(?:bounced(?=<)|map(?=<))\b/}],"class-name":e.languages.tact["class-name"],punctuation:{pattern:/[<>(),.?]/},keyword:{pattern:/\bas\b/}}}})}(Prism)},1513:(e,t,n)=>{"use strict";n.d(t,{zR:()=>w,TM:()=>C,yJ:()=>f,sC:()=>D,AO:()=>p});var o=n(8168);function r(e){return"/"===e.charAt(0)}function i(e,t){for(var n=t,o=n+1,r=e.length;o =0;p--){var f=s[p];"."===f?i(s,p):".."===f?(i(s,p),u++):u&&(i(s,p),u--)}if(!c)for(;u--;u)s.unshift("..");!c||""===s[0]||s[0]&&r(s[0])||s.unshift("");var m=s.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var a=n(1561);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function d(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function u(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,o=e.hash,r=t||"/";return n&&"?"!==n&&(r+="?"===n.charAt(0)?n:"?"+n),o&&"#"!==o&&(r+="#"===o.charAt(0)?o:"#"+o),r}function f(e,t,n,r){var i;"string"==typeof e?(i=function(e){var t=e||"/",n="",o="",r=t.indexOf("#");-1!==r&&(o=t.substr(r),t=t.substr(0,r));var i=t.indexOf("?");return-1!==i&&(n=t.substr(i),t=t.substr(0,i)),{pathname:t,search:"?"===n?"":n,hash:"#"===o?"":o}}(e),i.state=t):(void 0===(i=(0,o.A)({},e)).pathname&&(i.pathname=""),i.search?"?"!==i.search.charAt(0)&&(i.search="?"+i.search):i.search="",i.hash?"#"!==i.hash.charAt(0)&&(i.hash="#"+i.hash):i.hash="",void 0!==t&&void 0===i.state&&(i.state=t));try{i.pathname=decodeURI(i.pathname)}catch(a){throw a instanceof URIError?new URIError('Pathname "'+i.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):a}return n&&(i.key=n),r?i.pathname?"/"!==i.pathname.charAt(0)&&(i.pathname=s(i.pathname,r.pathname)):i.pathname=r.pathname:i.pathname||(i.pathname="/"),i}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,o,r){if(null!=e){var i="function"==typeof e?e(t,n):e;"string"==typeof i?"function"==typeof o?o(i,r):r(!0):r(!1!==i)}else r(!0)},appendListener:function(e){var n=!0;function o(){n&&e.apply(void 0,arguments)}return t.push(o),function(){n=!1,t=t.filter((function(e){return e!==o}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),o=0;o t?n.splice(t,n.length-t,r):n.push(r),u({action:o,location:r,index:t,entries:n})}}))},replace:function(e,t){var o="REPLACE",r=f(e,t,h(),w.location);d.confirmTransitionTo(r,o,n,(function(e){e&&(w.entries[w.index]=r,u({action:o,location:r}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t {"use strict";var o=n(4363),r={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},i={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},s={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},a={};function l(e){return o.isMemo(e)?s:a[e.$$typeof]||r}a[o.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},a[o.Memo]=s;var c=Object.defineProperty,d=Object.getOwnPropertyNames,u=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,o){if("string"!=typeof n){if(m){var r=f(n);r&&r!==m&&e(t,r,o)}var s=d(n);u&&(s=s.concat(u(n)));for(var a=l(t),h=l(n),b=0;b {"use strict";e.exports=function(e,t,n,o,r,i,s,a){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,o,r,i,s,a],d=0;(l=new Error(t.replace(/%s/g,(function(){return c[d++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},4634:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},119:(e,t,n)=>{"use strict";n.r(t)},1043:(e,t,n)=>{"use strict";n.r(t)},5947:function(e,t,n){var o,r;o=function(){var e,t,n={version:"0.2.0"},o=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:' '};function r(e,t,n){return en?n:e}function i(e){return 100*(-1+e)}function s(e,t,n){var r;return(r="translate3d"===o.positionUsing?{transform:"translate3d("+i(e)+"%,0,0)"}:"translate"===o.positionUsing?{transform:"translate("+i(e)+"%,0)"}:{"margin-left":i(e)+"%"}).transition="all "+t+"ms "+n,r}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(o[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=r(e,o.minimum,1),n.status=1===e?null:e;var i=n.render(!t),c=i.querySelector(o.barSelector),d=o.speed,u=o.easing;return i.offsetWidth,a((function(t){""===o.positionUsing&&(o.positionUsing=n.getPositioningCSS()),l(c,s(e,d,u)),1===e?(l(i,{transition:"none",opacity:1}),i.offsetWidth,setTimeout((function(){l(i,{transition:"all "+d+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),d)}),d)):setTimeout(t,d)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),o.trickleSpeed)};return o.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*r(Math.random()*t,.1,.95)),t=r(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*o.trickleRate)},e=0,t=0,n.promise=function(o){return o&&"resolved"!==o.state()?(0===t&&n.start(),e++,t++,o.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");d(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=o.template;var r,s=t.querySelector(o.barSelector),a=e?"-100":i(n.status||0),c=document.querySelector(o.parent);return l(s,{transition:"all 0 linear",transform:"translate3d("+a+"%,0,0)"}),o.showSpinner||(r=t.querySelector(o.spinnerSelector))&&f(r),c!=document.body&&d(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){u(document.documentElement,"nprogress-busy"),u(document.querySelector(o.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var a=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function o(t){var n=document.body.style;if(t in n)return t;for(var o,r=e.length,i=t.charAt(0).toUpperCase()+t.slice(1);r--;)if((o=e[r]+i)in n)return o;return t}function r(e){return e=n(e),t[e]||(t[e]=o(e))}function i(e,t,n){t=r(t),e.style[t]=n}return function(e,t){var n,o,r=arguments;if(2==r.length)for(n in t)void 0!==(o=t[n])&&t.hasOwnProperty(n)&&i(e,n,o);else i(e,r[1],r[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function d(e,t){var n=p(e),o=n+t;c(n,t)||(e.className=o.substring(1))}function u(e,t){var n,o=p(e);c(e,t)&&(n=o.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(r="function"==typeof o?o.call(t,n,t,e):o)||(e.exports=r)},6969:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to WebPlatform.org documentation. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes ( .comment
can become.namespace--comment
) or replace them with your defined ones (like.editor__comment
). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements thehighlightAll
andhighlightAllUnder
methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},8722:(e,t,n)=>{const o=n(6969),r=n(8380),i=new Set;function s(e){void 0===e?e=Object.keys(o.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...i,...Object.keys(Prism.languages)];r(o,e,t).load((e=>{if(!(e in o.languages))return void(s.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(3157).resolve(t)],delete Prism.languages[e],n(3157)(t),i.add(e)}))}s.silent=!1,e.exports=s},8692:(e,t,n)=>{var o={"./":8722};function r(e){var t=i(e);return n(t)}function i(e){if(!n.o(o,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return o[e]}r.keys=function(){return Object.keys(o)},r.resolve=i,e.exports=r,r.id=8692},3157:(e,t,n)=>{var o={"./":8722};function r(e){var t=i(e);return n(t)}function i(e){if(!n.o(o,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return o[e]}r.keys=function(){return Object.keys(o)},r.resolve=i,e.exports=r,r.id=3157},8380:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,o=e.length;n"));var a={},l=e[o];if(l){function c(t){if(!(t in e))throw new Error(o+" depends on an unknown component "+t);if(!(t in a))for(var s in r(t,i),a[t]=!0,n[t])a[s]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[o]=a,i.pop()}}return function(e){var t=n[e];return t||(r(e,o),t=n[e]),t}}function r(e){for(var t in e)return!0;return!1}return function(i,s,a){var l=function(e){var t={};for(var n in e){var o=e[n];for(var r in o)if("meta"!=r){var i=o[r];t[r]="string"==typeof i?{title:i}:i}}return t}(i),c=function(e){var n;return function(o){if(o in e)return o;if(!n)for(var r in n={},e){var i=e[r];t(i&&i.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+r+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+r+" because it is a component.");n[t]=r}))}return n[o]||o}}(l);s=s.map(c),a=(a||[]).map(c);var d=n(s),u=n(a);s.forEach((function e(n){var o=l[n];t(o&&o.require,(function(t){t in u||(d[t]=!0,e(t))}))}));for(var p,f=o(l),m=d;r(m);){for(var h in p={},m){var b=l[h];t(b&&b.modify,(function(e){e in u&&(p[e]=!0)}))}for(var g in u)if(!(g in d))for(var v in f(g))if(v in d){p[g]=!0;break}for(var y in m=p)d[y]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,o,r){var i=r?r.series:void 0,s=r?r.parallel:e,a={},l={};function c(e){if(e in a)return a[e];l[e]=!0;var r,d=[];for(var u in t(e))u in n&&d.push(u);if(0===d.length)r=o(e);else{var p=s(d.map((function(e){var t=c(e);return delete l[e],t})));i?r=i(p,(function(){return o(e)})):o(e)}return a[e]=r}for(var d in n)c(d);var u=[];for(var p in l)u.push(a[p]);return s(u)}(f,d,t,n)}};return w}}();e.exports=t},2694:(e,t,n)=>{"use strict";var o=n(6925);function r(){}function i(){}i.resetWarningCache=r,e.exports=function(){function e(e,t,n,r,i,s){if(s!==o){var a=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw a.name="Invariant Violation",a}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:i,resetWarningCache:r};return n.PropTypes=n,n}},5556:(e,t,n)=>{e.exports=n(2694)()},6925:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},2551:(e,t,n)=>{"use strict";var o=n(6540),r=n(9982);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n t}return!1}(t,n,r,o)&&(n=null),o||null===r?function(e){return!!u.call(m,e)||!u.call(f,e)&&(p.test(e)?m[e]=!0:(f[e]=!0,!1))}(t)&&(null===n?e.removeAttribute(t):e.setAttribute(t,""+n)):r.mustUseProperty?e[r.propertyName]=null===n?3!==r.type&&"":n:(t=r.attributeName,o=r.attributeNamespace,null===n?e.removeAttribute(t):(n=3===(r=r.type)||4===r&&!0===n?"":""+n,o?e.setAttributeNS(o,t,n):e.setAttribute(t,n))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var t=e.replace(g,v);b[t]=new h(t,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var t=e.replace(g,v);b[t]=new h(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var t=e.replace(g,v);b[t]=new h(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)})),["tabIndex","crossOrigin"].forEach((function(e){b[e]=new h(e,1,!1,e.toLowerCase(),null,!1,!1)})),b.xlinkHref=new h("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach((function(e){b[e]=new h(e,1,!1,e.toLowerCase(),null,!0,!0)}));var w=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,k=Symbol.for("react.element"),x=Symbol.for("react.portal"),_=Symbol.for("react.fragment"),S=Symbol.for("react.strict_mode"),A=Symbol.for("react.profiler"),C=Symbol.for("react.provider"),E=Symbol.for("react.context"),D=Symbol.for("react.forward_ref"),T=Symbol.for("react.suspense"),R=Symbol.for("react.suspense_list"),L=Symbol.for("react.memo"),O=Symbol.for("react.lazy");Symbol.for("react.scope"),Symbol.for("react.debug_trace_mode");var P=Symbol.for("react.offscreen");Symbol.for("react.legacy_hidden"),Symbol.for("react.cache"),Symbol.for("react.tracing_marker");var N=Symbol.iterator;function I(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=N&&e[N]||e["@@iterator"])?e:null}var j,M=Object.assign;function F(e){if(void 0===j)try{throw Error()}catch(n){var t=n.stack.trim().match(/\n( *(at )?)/);j=t&&t[1]||""}return"\n"+j+e}var U=!1;function B(e,t){if(!e||U)return"";U=!0;var n=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(t)if(t=function(){throw Error()},Object.defineProperty(t.prototype,"props",{set:function(){throw Error()}}),"object"==typeof Reflect&&Reflect.construct){try{Reflect.construct(t,[])}catch(c){var o=c}Reflect.construct(e,[],t)}else{try{t.call()}catch(c){o=c}e.call(t.prototype)}else{try{throw Error()}catch(c){o=c}e()}}catch(c){if(c&&o&&"string"==typeof c.stack){for(var r=c.stack.split("\n"),i=o.stack.split("\n"),s=r.length-1,a=i.length-1;1<=s&&0<=a&&r[s]!==i[a];)a--;for(;1<=s&&0<=a;s--,a--)if(r[s]!==i[a]){if(1!==s||1!==a)do{if(s--,0>--a||r[s]!==i[a]){var l="\n"+r[s].replace(" at new "," at ");return e.displayName&&l.includes(" ")&&(l=l.replace(" ",e.displayName)),l}}while(1<=s&&0<=a);break}}}finally{U=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?F(e):""}function z(e){switch(e.tag){case 5:return F(e.type);case 16:return F("Lazy");case 13:return F("Suspense");case 19:return F("SuspenseList");case 0:case 2:case 15:return e=B(e.type,!1);case 11:return e=B(e.type.render,!1);case 1:return e=B(e.type,!0);default:return""}}function $(e){if(null==e)return null;if("function"==typeof e)return e.displayName||e.name||null;if("string"==typeof e)return e;switch(e){case _:return"Fragment";case x:return"Portal";case A:return"Profiler";case S:return"StrictMode";case T:return"Suspense";case R:return"SuspenseList"}if("object"==typeof e)switch(e.$$typeof){case E:return(e.displayName||"Context")+".Consumer";case C:return(e._context.displayName||"Context")+".Provider";case D:var t=e.render;return(e=e.displayName)||(e=""!==(e=t.displayName||t.name||"")?"ForwardRef("+e+")":"ForwardRef"),e;case L:return null!==(t=e.displayName||null)?t:$(e.type)||"Memo";case O:t=e._payload,e=e._init;try{return $(e(t))}catch(n){}}return null}function V(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=(e=t.render).displayName||e.name||"",t.displayName||(""!==e?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return $(t);case 8:return t===S?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if("function"==typeof t)return t.displayName||t.name||null;if("string"==typeof t)return t}return null}function q(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":case"object":return e;default:return""}}function H(e){var t=e.type;return(e=e.nodeName)&&"input"===e.toLowerCase()&&("checkbox"===t||"radio"===t)}function G(e){e._valueTracker||(e._valueTracker=function(e){var t=H(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),o=""+e[t];if(!e.hasOwnProperty(t)&&void 0!==n&&"function"==typeof n.get&&"function"==typeof n.set){var r=n.get,i=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return r.call(this)},set:function(e){o=""+e,i.call(this,e)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return o},setValue:function(e){o=""+e},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}(e))}function W(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),o="";return e&&(o=H(e)?e.checked?"true":"false":e.value),(e=o)!==n&&(t.setValue(e),!0)}function Z(e){if(void 0===(e=e||("undefined"!=typeof document?document:void 0)))return null;try{return e.activeElement||e.body}catch(t){return e.body}}function Q(e,t){var n=t.checked;return M({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:null!=n?n:e._wrapperState.initialChecked})}function K(e,t){var n=null==t.defaultValue?"":t.defaultValue,o=null!=t.checked?t.checked:t.defaultChecked;n=q(null!=t.value?t.value:n),e._wrapperState={initialChecked:o,initialValue:n,controlled:"checkbox"===t.type||"radio"===t.type?null!=t.checked:null!=t.value}}function Y(e,t){null!=(t=t.checked)&&y(e,"checked",t,!1)}function X(e,t){Y(e,t);var n=q(t.value),o=t.type;if(null!=n)"number"===o?(0===n&&""===e.value||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if("submit"===o||"reset"===o)return void e.removeAttribute("value");t.hasOwnProperty("value")?ee(e,t.type,n):t.hasOwnProperty("defaultValue")&&ee(e,t.type,q(t.defaultValue)),null==t.checked&&null!=t.defaultChecked&&(e.defaultChecked=!!t.defaultChecked)}function J(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var o=t.type;if(!("submit"!==o&&"reset"!==o||void 0!==t.value&&null!==t.value))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}""!==(n=e.name)&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,""!==n&&(e.name=n)}function ee(e,t,n){"number"===t&&Z(e.ownerDocument)===e||(null==n?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var te=Array.isArray;function ne(e,t,n,o){if(e=e.options,t){t={};for(var r=0;r "+t.valueOf().toString()+"",t=ce.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}},"undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction?function(e,t,n,o){MSApp.execUnsafeLocalFunction((function(){return de(e,t)}))}:de);function pe(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&3===n.nodeType)return void(n.nodeValue=t)}e.textContent=t}var fe={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},me=["Webkit","ms","Moz","O"];function he(e,t,n){return null==t||"boolean"==typeof t||""===t?"":n||"number"!=typeof t||0===t||fe.hasOwnProperty(e)&&fe[e]?(""+t).trim():t+"px"}function be(e,t){for(var n in e=e.style,t)if(t.hasOwnProperty(n)){var o=0===n.indexOf("--"),r=he(n,t[n],o);"float"===n&&(n="cssFloat"),o?e.setProperty(n,r):e[n]=r}}Object.keys(fe).forEach((function(e){me.forEach((function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),fe[t]=fe[e]}))}));var ge=M({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function ve(e,t){if(t){if(ge[e]&&(null!=t.children||null!=t.dangerouslySetInnerHTML))throw Error(i(137,e));if(null!=t.dangerouslySetInnerHTML){if(null!=t.children)throw Error(i(60));if("object"!=typeof t.dangerouslySetInnerHTML||!("__html"in t.dangerouslySetInnerHTML))throw Error(i(61))}if(null!=t.style&&"object"!=typeof t.style)throw Error(i(62))}}function ye(e,t){if(-1===e.indexOf("-"))return"string"==typeof t.is;switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var we=null;function ke(e){return(e=e.target||e.srcElement||window).correspondingUseElement&&(e=e.correspondingUseElement),3===e.nodeType?e.parentNode:e}var xe=null,_e=null,Se=null;function Ae(e){if(e=wr(e)){if("function"!=typeof xe)throw Error(i(280));var t=e.stateNode;t&&(t=xr(t),xe(e.stateNode,e.type,t))}}function Ce(e){_e?Se?Se.push(e):Se=[e]:_e=e}function Ee(){if(_e){var e=_e,t=Se;if(Se=_e=null,Ae(e),t)for(e=0;e >>=0,0===e?32:31-(at(e)/lt|0)|0},at=Math.log,lt=Math.LN2;var ct=64,dt=4194304;function ut(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return 4194240&e;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return 130023424&e;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function pt(e,t){var n=e.pendingLanes;if(0===n)return 0;var o=0,r=e.suspendedLanes,i=e.pingedLanes,s=268435455&n;if(0!==s){var a=s&~r;0!==a?o=ut(a):0!==(i&=s)&&(o=ut(i))}else 0!==(s=n&~r)?o=ut(s):0!==i&&(o=ut(i));if(0===o)return 0;if(0!==t&&t!==o&&!(t&r)&&((r=o&-o)>=(i=t&-t)||16===r&&4194240&i))return t;if(4&o&&(o|=16&n),0!==(t=e.entangledLanes))for(e=e.entanglements,t&=o;0 n;n++)t.push(e);return t}function gt(e,t,n){e.pendingLanes|=t,536870912!==t&&(e.suspendedLanes=0,e.pingedLanes=0),(e=e.eventTimes)[t=31-st(t)]=n}function vt(e,t){var n=e.entangledLanes|=t;for(e=e.entanglements;n;){var o=31-st(n),r=1< =In),Fn=String.fromCharCode(32),Un=!1;function Bn(e,t){switch(e){case"keyup":return-1!==Pn.indexOf(t.keyCode);case"keydown":return 229!==t.keyCode;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function zn(e){return"object"==typeof(e=e.detail)&&"data"in e?e.data:null}var $n=!1;var Vn={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};function qn(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return"input"===t?!!Vn[e.type]:"textarea"===t}function Hn(e,t,n,o){Ce(o),0<(t=Wo(t,"onChange")).length&&(n=new dn("onChange","change",null,n,o),e.push({event:n,listeners:t}))}var Gn=null,Wn=null;function Zn(e){Uo(e,0)}function Qn(e){if(W(kr(e)))return e}function Kn(e,t){if("change"===e)return t}var Yn=!1;if(d){var Xn;if(d){var Jn="oninput"in document;if(!Jn){var eo=document.createElement("div");eo.setAttribute("oninput","return;"),Jn="function"==typeof eo.oninput}Xn=Jn}else Xn=!1;Yn=Xn&&(!document.documentMode||9 =t)return{node:o,offset:t-e};e=n}e:{for(;o;){if(o.nextSibling){o=o.nextSibling;break e}o=o.parentNode}o=void 0}o=co(o)}}function po(e,t){return!(!e||!t)&&(e===t||(!e||3!==e.nodeType)&&(t&&3===t.nodeType?po(e,t.parentNode):"contains"in e?e.contains(t):!!e.compareDocumentPosition&&!!(16&e.compareDocumentPosition(t))))}function fo(){for(var e=window,t=Z();t instanceof e.HTMLIFrameElement;){try{var n="string"==typeof t.contentWindow.location.href}catch(o){n=!1}if(!n)break;t=Z((e=t.contentWindow).document)}return t}function mo(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&("input"===t&&("text"===e.type||"search"===e.type||"tel"===e.type||"url"===e.type||"password"===e.type)||"textarea"===t||"true"===e.contentEditable)}function ho(e){var t=fo(),n=e.focusedElem,o=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&po(n.ownerDocument.documentElement,n)){if(null!==o&&mo(n))if(t=o.start,void 0===(e=o.end)&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if((e=(t=n.ownerDocument||document)&&t.defaultView||window).getSelection){e=e.getSelection();var r=n.textContent.length,i=Math.min(o.start,r);o=void 0===o.end?i:Math.min(o.end,r),!e.extend&&i>o&&(r=o,o=i,i=r),r=uo(n,i);var s=uo(n,o);r&&s&&(1!==e.rangeCount||e.anchorNode!==r.node||e.anchorOffset!==r.offset||e.focusNode!==s.node||e.focusOffset!==s.offset)&&((t=t.createRange()).setStart(r.node,r.offset),e.removeAllRanges(),i>o?(e.addRange(t),e.extend(s.node,s.offset)):(t.setEnd(s.node,s.offset),e.addRange(t)))}for(t=[],e=n;e=e.parentNode;)1===e.nodeType&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for("function"==typeof n.focus&&n.focus(),n=0;n =document.documentMode,go=null,vo=null,yo=null,wo=!1;function ko(e,t,n){var o=n.window===n?n.document:9===n.nodeType?n:n.ownerDocument;wo||null==go||go!==Z(o)||("selectionStart"in(o=go)&&mo(o)?o={start:o.selectionStart,end:o.selectionEnd}:o={anchorNode:(o=(o.ownerDocument&&o.ownerDocument.defaultView||window).getSelection()).anchorNode,anchorOffset:o.anchorOffset,focusNode:o.focusNode,focusOffset:o.focusOffset},yo&&lo(yo,o)||(yo=o,0<(o=Wo(vo,"onSelect")).length&&(t=new dn("onSelect","select",null,t,n),e.push({event:t,listeners:o}),t.target=go)))}function xo(e,t){var n={};return n[e.toLowerCase()]=t.toLowerCase(),n["Webkit"+e]="webkit"+t,n["Moz"+e]="moz"+t,n}var _o={animationend:xo("Animation","AnimationEnd"),animationiteration:xo("Animation","AnimationIteration"),animationstart:xo("Animation","AnimationStart"),transitionend:xo("Transition","TransitionEnd")},So={},Ao={};function Co(e){if(So[e])return So[e];if(!_o[e])return e;var t,n=_o[e];for(t in n)if(n.hasOwnProperty(t)&&t in Ao)return So[e]=n[t];return e}d&&(Ao=document.createElement("div").style,"AnimationEvent"in window||(delete _o.animationend.animation,delete _o.animationiteration.animation,delete _o.animationstart.animation),"TransitionEvent"in window||delete _o.transitionend.transition);var Eo=Co("animationend"),Do=Co("animationiteration"),To=Co("animationstart"),Ro=Co("transitionend"),Lo=new Map,Oo="abort auxClick cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" ");function Po(e,t){Lo.set(e,t),l(t,[e])}for(var No=0;No Sr||(e.current=_r[Sr],_r[Sr]=null,Sr--)}function Er(e,t){Sr++,_r[Sr]=e.current,e.current=t}var Dr={},Tr=Ar(Dr),Rr=Ar(!1),Lr=Dr;function Or(e,t){var n=e.type.contextTypes;if(!n)return Dr;var o=e.stateNode;if(o&&o.__reactInternalMemoizedUnmaskedChildContext===t)return o.__reactInternalMemoizedMaskedChildContext;var r,i={};for(r in n)i[r]=t[r];return o&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=i),i}function Pr(e){return null!=(e=e.childContextTypes)}function Nr(){Cr(Rr),Cr(Tr)}function Ir(e,t,n){if(Tr.current!==Dr)throw Error(i(168));Er(Tr,t),Er(Rr,n)}function jr(e,t,n){var o=e.stateNode;if(t=t.childContextTypes,"function"!=typeof o.getChildContext)return n;for(var r in o=o.getChildContext())if(!(r in t))throw Error(i(108,V(e)||"Unknown",r));return M({},n,o)}function Mr(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Dr,Lr=Tr.current,Er(Tr,e),Er(Rr,Rr.current),!0}function Fr(e,t,n){var o=e.stateNode;if(!o)throw Error(i(169));n?(e=jr(e,t,Lr),o.__reactInternalMemoizedMergedChildContext=e,Cr(Rr),Cr(Tr),Er(Tr,e)):Cr(Rr),Er(Rr,n)}var Ur=null,Br=!1,zr=!1;function $r(e){null===Ur?Ur=[e]:Ur.push(e)}function Vr(){if(!zr&&null!==Ur){zr=!0;var e=0,t=yt;try{var n=Ur;for(yt=1;e >=s,r-=s,Yr=1<<32-st(t)+r|n< h?(b=u,u=null):b=u.sibling;var g=f(r,u,a[h],l);if(null===g){null===u&&(u=b);break}e&&u&&null===g.alternate&&t(r,u),i=s(g,i,h),null===d?c=g:d.sibling=g,d=g,u=b}if(h===a.length)return n(r,u),ii&&Jr(r,h),c;if(null===u){for(;h b?(g=h,h=null):g=h.sibling;var y=f(r,h,v.value,c);if(null===y){null===h&&(h=g);break}e&&h&&null===y.alternate&&t(r,h),a=s(y,a,b),null===u?d=y:u.sibling=y,u=y,h=g}if(v.done)return n(r,h),ii&&Jr(r,b),d;if(null===h){for(;!v.done;b++,v=l.next())null!==(v=p(r,v.value,c))&&(a=s(v,a,b),null===u?d=v:u.sibling=v,u=v);return ii&&Jr(r,b),d}for(h=o(r,h);!v.done;b++,v=l.next())null!==(v=m(h,r,b,v.value,c))&&(e&&null!==v.alternate&&h.delete(null===v.key?b:v.key),a=s(v,a,b),null===u?d=v:u.sibling=v,u=v);return e&&h.forEach((function(e){return t(r,e)})),ii&&Jr(r,b),d}return function e(o,i,s,l){if("object"==typeof s&&null!==s&&s.type===_&&null===s.key&&(s=s.props.children),"object"==typeof s&&null!==s){switch(s.$$typeof){case k:e:{for(var c=s.key,d=i;null!==d;){if(d.key===c){if((c=s.type)===_){if(7===d.tag){n(o,d.sibling),(i=r(d,s.props.children)).return=o,o=i;break e}}else if(d.elementType===c||"object"==typeof c&&null!==c&&c.$$typeof===O&&yi(c)===d.type){n(o,d.sibling),(i=r(d,s.props)).ref=gi(o,d,s),i.return=o,o=i;break e}n(o,d);break}t(o,d),d=d.sibling}s.type===_?((i=Ic(s.props.children,o.mode,l,s.key)).return=o,o=i):((l=Nc(s.type,s.key,s.props,null,o.mode,l)).ref=gi(o,i,s),l.return=o,o=l)}return a(o);case x:e:{for(d=s.key;null!==i;){if(i.key===d){if(4===i.tag&&i.stateNode.containerInfo===s.containerInfo&&i.stateNode.implementation===s.implementation){n(o,i.sibling),(i=r(i,s.children||[])).return=o,o=i;break e}n(o,i);break}t(o,i),i=i.sibling}(i=Fc(s,o.mode,l)).return=o,o=i}return a(o);case O:return e(o,i,(d=s._init)(s._payload),l)}if(te(s))return h(o,i,s,l);if(I(s))return b(o,i,s,l);vi(o,s)}return"string"==typeof s&&""!==s||"number"==typeof s?(s=""+s,null!==i&&6===i.tag?(n(o,i.sibling),(i=r(i,s)).return=o,o=i):(n(o,i),(i=Mc(s,o.mode,l)).return=o,o=i),a(o)):n(o,i)}}var ki=wi(!0),xi=wi(!1),_i=Ar(null),Si=null,Ai=null,Ci=null;function Ei(){Ci=Ai=Si=null}function Di(e){var t=_i.current;Cr(_i),e._currentValue=t}function Ti(e,t,n){for(;null!==e;){var o=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,null!==o&&(o.childLanes|=t)):null!==o&&(o.childLanes&t)!==t&&(o.childLanes|=t),e===n)break;e=e.return}}function Ri(e,t){Si=e,Ci=Ai=null,null!==(e=e.dependencies)&&null!==e.firstContext&&(!!(e.lanes&t)&&(ya=!0),e.firstContext=null)}function Li(e){var t=e._currentValue;if(Ci!==e)if(e={context:e,memoizedValue:t,next:null},null===Ai){if(null===Si)throw Error(i(308));Ai=e,Si.dependencies={lanes:0,firstContext:e}}else Ai=Ai.next=e;return t}var Oi=null;function Pi(e){null===Oi?Oi=[e]:Oi.push(e)}function Ni(e,t,n,o){var r=t.interleaved;return null===r?(n.next=n,Pi(t)):(n.next=r.next,r.next=n),t.interleaved=n,Ii(e,o)}function Ii(e,t){e.lanes|=t;var n=e.alternate;for(null!==n&&(n.lanes|=t),n=e,e=e.return;null!==e;)e.childLanes|=t,null!==(n=e.alternate)&&(n.childLanes|=t),n=e,e=e.return;return 3===n.tag?n.stateNode:null}var ji=!1;function Mi(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Fi(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Ui(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Bi(e,t,n){var o=e.updateQueue;if(null===o)return null;if(o=o.shared,2&Dl){var r=o.pending;return null===r?t.next=t:(t.next=r.next,r.next=t),o.pending=t,Ii(e,n)}return null===(r=o.interleaved)?(t.next=t,Pi(o)):(t.next=r.next,r.next=t),o.interleaved=t,Ii(e,n)}function zi(e,t,n){if(null!==(t=t.updateQueue)&&(t=t.shared,4194240&n)){var o=t.lanes;n|=o&=e.pendingLanes,t.lanes=n,vt(e,n)}}function $i(e,t){var n=e.updateQueue,o=e.alternate;if(null!==o&&n===(o=o.updateQueue)){var r=null,i=null;if(null!==(n=n.firstBaseUpdate)){do{var s={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};null===i?r=i=s:i=i.next=s,n=n.next}while(null!==n);null===i?r=i=t:i=i.next=t}else r=i=t;return n={baseState:o.baseState,firstBaseUpdate:r,lastBaseUpdate:i,shared:o.shared,effects:o.effects},void(e.updateQueue=n)}null===(e=n.lastBaseUpdate)?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function Vi(e,t,n,o){var r=e.updateQueue;ji=!1;var i=r.firstBaseUpdate,s=r.lastBaseUpdate,a=r.shared.pending;if(null!==a){r.shared.pending=null;var l=a,c=l.next;l.next=null,null===s?i=c:s.next=c,s=l;var d=e.alternate;null!==d&&((a=(d=d.updateQueue).lastBaseUpdate)!==s&&(null===a?d.firstBaseUpdate=c:a.next=c,d.lastBaseUpdate=l))}if(null!==i){var u=r.baseState;for(s=0,d=c=l=null,a=i;;){var p=a.lane,f=a.eventTime;if((o&p)===p){null!==d&&(d=d.next={eventTime:f,lane:0,tag:a.tag,payload:a.payload,callback:a.callback,next:null});e:{var m=e,h=a;switch(p=t,f=n,h.tag){case 1:if("function"==typeof(m=h.payload)){u=m.call(f,u,p);break e}u=m;break e;case 3:m.flags=-65537&m.flags|128;case 0:if(null==(p="function"==typeof(m=h.payload)?m.call(f,u,p):m))break e;u=M({},u,p);break e;case 2:ji=!0}}null!==a.callback&&0!==a.lane&&(e.flags|=64,null===(p=r.effects)?r.effects=[a]:p.push(a))}else f={eventTime:f,lane:p,tag:a.tag,payload:a.payload,callback:a.callback,next:null},null===d?(c=d=f,l=u):d=d.next=f,s|=p;if(null===(a=a.next)){if(null===(a=r.shared.pending))break;a=(p=a).next,p.next=null,r.lastBaseUpdate=p,r.shared.pending=null}}if(null===d&&(l=u),r.baseState=l,r.firstBaseUpdate=c,r.lastBaseUpdate=d,null!==(t=r.shared.interleaved)){r=t;do{s|=r.lane,r=r.next}while(r!==t)}else null===i&&(r.shared.lanes=0);jl|=s,e.lanes=s,e.memoizedState=u}}function qi(e,t,n){if(e=t.effects,t.effects=null,null!==e)for(t=0;t n?n:4,e(!0);var o=is.transition;is.transition={};try{e(!1),t()}finally{yt=n,is.transition=o}}function Gs(){return ys().memoizedState}function Ws(e,t,n){var o=tc(e);if(n={lane:o,action:n,hasEagerState:!1,eagerState:null,next:null},Qs(e))Ks(t,n);else if(null!==(n=Ni(e,t,n,o))){nc(n,e,o,ec()),Ys(n,t,o)}}function Zs(e,t,n){var o=tc(e),r={lane:o,action:n,hasEagerState:!1,eagerState:null,next:null};if(Qs(e))Ks(t,r);else{var i=e.alternate;if(0===e.lanes&&(null===i||0===i.lanes)&&null!==(i=t.lastRenderedReducer))try{var s=t.lastRenderedState,a=i(s,n);if(r.hasEagerState=!0,r.eagerState=a,ao(a,s)){var l=t.interleaved;return null===l?(r.next=r,Pi(t)):(r.next=l.next,l.next=r),void(t.interleaved=r)}}catch(c){}null!==(n=Ni(e,t,r,o))&&(nc(n,e,o,r=ec()),Ys(n,t,o))}}function Qs(e){var t=e.alternate;return e===as||null!==t&&t===as}function Ks(e,t){us=ds=!0;var n=e.pending;null===n?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Ys(e,t,n){if(4194240&n){var o=t.lanes;n|=o&=e.pendingLanes,t.lanes=n,vt(e,n)}}var Xs={readContext:Li,useCallback:ms,useContext:ms,useEffect:ms,useImperativeHandle:ms,useInsertionEffect:ms,useLayoutEffect:ms,useMemo:ms,useReducer:ms,useRef:ms,useState:ms,useDebugValue:ms,useDeferredValue:ms,useTransition:ms,useMutableSource:ms,useSyncExternalStore:ms,useId:ms,unstable_isNewReconciler:!1},Js={readContext:Li,useCallback:function(e,t){return vs().memoizedState=[e,void 0===t?null:t],e},useContext:Li,useEffect:Is,useImperativeHandle:function(e,t,n){return n=null!=n?n.concat([e]):null,Ps(4194308,4,Us.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Ps(4194308,4,e,t)},useInsertionEffect:function(e,t){return Ps(4,2,e,t)},useMemo:function(e,t){var n=vs();return t=void 0===t?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var o=vs();return t=void 0!==n?n(t):t,o.memoizedState=o.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},o.queue=e,e=e.dispatch=Ws.bind(null,as,e),[o.memoizedState,e]},useRef:function(e){return e={current:e},vs().memoizedState=e},useState:Rs,useDebugValue:zs,useDeferredValue:function(e){return vs().memoizedState=e},useTransition:function(){var e=Rs(!1),t=e[0];return e=Hs.bind(null,e[1]),vs().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var o=as,r=vs();if(ii){if(void 0===n)throw Error(i(407));n=n()}else{if(n=t(),null===Tl)throw Error(i(349));30&ss||As(o,t,n)}r.memoizedState=n;var s={value:n,getSnapshot:t};return r.queue=s,Is(Es.bind(null,o,s,e),[e]),o.flags|=2048,Ls(9,Cs.bind(null,o,s,n,t),void 0,null),n},useId:function(){var e=vs(),t=Tl.identifierPrefix;if(ii){var n=Xr;t=":"+t+"R"+(n=(Yr&~(1<<32-st(Yr)-1)).toString(32)+n),0<(n=ps++)&&(t+="H"+n.toString(32)),t+=":"}else t=":"+t+"r"+(n=fs++).toString(32)+":";return e.memoizedState=t},unstable_isNewReconciler:!1},ea={readContext:Li,useCallback:$s,useContext:Li,useEffect:js,useImperativeHandle:Bs,useInsertionEffect:Ms,useLayoutEffect:Fs,useMemo:Vs,useReducer:ks,useRef:Os,useState:function(){return ks(ws)},useDebugValue:zs,useDeferredValue:function(e){return qs(ys(),ls.memoizedState,e)},useTransition:function(){return[ks(ws)[0],ys().memoizedState]},useMutableSource:_s,useSyncExternalStore:Ss,useId:Gs,unstable_isNewReconciler:!1},ta={readContext:Li,useCallback:$s,useContext:Li,useEffect:js,useImperativeHandle:Bs,useInsertionEffect:Ms,useLayoutEffect:Fs,useMemo:Vs,useReducer:xs,useRef:Os,useState:function(){return xs(ws)},useDebugValue:zs,useDeferredValue:function(e){var t=ys();return null===ls?t.memoizedState=e:qs(t,ls.memoizedState,e)},useTransition:function(){return[xs(ws)[0],ys().memoizedState]},useMutableSource:_s,useSyncExternalStore:Ss,useId:Gs,unstable_isNewReconciler:!1};function na(e,t){if(e&&e.defaultProps){for(var n in t=M({},t),e=e.defaultProps)void 0===t[n]&&(t[n]=e[n]);return t}return t}function oa(e,t,n,o){n=null==(n=n(o,t=e.memoizedState))?t:M({},t,n),e.memoizedState=n,0===e.lanes&&(e.updateQueue.baseState=n)}var ra={isMounted:function(e){return!!(e=e._reactInternals)&&$e(e)===e},enqueueSetState:function(e,t,n){e=e._reactInternals;var o=ec(),r=tc(e),i=Ui(o,r);i.payload=t,null!=n&&(i.callback=n),null!==(t=Bi(e,i,r))&&(nc(t,e,r,o),zi(t,e,r))},enqueueReplaceState:function(e,t,n){e=e._reactInternals;var o=ec(),r=tc(e),i=Ui(o,r);i.tag=1,i.payload=t,null!=n&&(i.callback=n),null!==(t=Bi(e,i,r))&&(nc(t,e,r,o),zi(t,e,r))},enqueueForceUpdate:function(e,t){e=e._reactInternals;var n=ec(),o=tc(e),r=Ui(n,o);r.tag=2,null!=t&&(r.callback=t),null!==(t=Bi(e,r,o))&&(nc(t,e,o,n),zi(t,e,o))}};function ia(e,t,n,o,r,i,s){return"function"==typeof(e=e.stateNode).shouldComponentUpdate?e.shouldComponentUpdate(o,i,s):!t.prototype||!t.prototype.isPureReactComponent||(!lo(n,o)||!lo(r,i))}function sa(e,t,n){var o=!1,r=Dr,i=t.contextType;return"object"==typeof i&&null!==i?i=Li(i):(r=Pr(t)?Lr:Tr.current,i=(o=null!=(o=t.contextTypes))?Or(e,r):Dr),t=new t(n,i),e.memoizedState=null!==t.state&&void 0!==t.state?t.state:null,t.updater=ra,e.stateNode=t,t._reactInternals=e,o&&((e=e.stateNode).__reactInternalMemoizedUnmaskedChildContext=r,e.__reactInternalMemoizedMaskedChildContext=i),t}function aa(e,t,n,o){e=t.state,"function"==typeof t.componentWillReceiveProps&&t.componentWillReceiveProps(n,o),"function"==typeof t.UNSAFE_componentWillReceiveProps&&t.UNSAFE_componentWillReceiveProps(n,o),t.state!==e&&ra.enqueueReplaceState(t,t.state,null)}function la(e,t,n,o){var r=e.stateNode;r.props=n,r.state=e.memoizedState,r.refs={},Mi(e);var i=t.contextType;"object"==typeof i&&null!==i?r.context=Li(i):(i=Pr(t)?Lr:Tr.current,r.context=Or(e,i)),r.state=e.memoizedState,"function"==typeof(i=t.getDerivedStateFromProps)&&(oa(e,t,i,n),r.state=e.memoizedState),"function"==typeof t.getDerivedStateFromProps||"function"==typeof r.getSnapshotBeforeUpdate||"function"!=typeof r.UNSAFE_componentWillMount&&"function"!=typeof r.componentWillMount||(t=r.state,"function"==typeof r.componentWillMount&&r.componentWillMount(),"function"==typeof r.UNSAFE_componentWillMount&&r.UNSAFE_componentWillMount(),t!==r.state&&ra.enqueueReplaceState(r,r.state,null),Vi(e,n,r,o),r.state=e.memoizedState),"function"==typeof r.componentDidMount&&(e.flags|=4194308)}function ca(e,t){try{var n="",o=t;do{n+=z(o),o=o.return}while(o);var r=n}catch(i){r="\nError generating stack: "+i.message+"\n"+i.stack}return{value:e,source:t,stack:r,digest:null}}function da(e,t,n){return{value:e,source:null,stack:null!=n?n:null,digest:null!=t?t:null}}function ua(e,t){try{console.error(t.value)}catch(n){setTimeout((function(){throw n}))}}var pa="function"==typeof WeakMap?WeakMap:Map;function fa(e,t,n){(n=Ui(-1,n)).tag=3,n.payload={element:null};var o=t.value;return n.callback=function(){ql||(ql=!0,Hl=o),ua(0,t)},n}function ma(e,t,n){(n=Ui(-1,n)).tag=3;var o=e.type.getDerivedStateFromError;if("function"==typeof o){var r=t.value;n.payload=function(){return o(r)},n.callback=function(){ua(0,t)}}var i=e.stateNode;return null!==i&&"function"==typeof i.componentDidCatch&&(n.callback=function(){ua(0,t),"function"!=typeof o&&(null===Gl?Gl=new Set([this]):Gl.add(this));var e=t.stack;this.componentDidCatch(t.value,{componentStack:null!==e?e:""})}),n}function ha(e,t,n){var o=e.pingCache;if(null===o){o=e.pingCache=new pa;var r=new Set;o.set(t,r)}else void 0===(r=o.get(t))&&(r=new Set,o.set(t,r));r.has(n)||(r.add(n),e=Ac.bind(null,e,t,n),t.then(e,e))}function ba(e){do{var t;if((t=13===e.tag)&&(t=null===(t=e.memoizedState)||null!==t.dehydrated),t)return e;e=e.return}while(null!==e);return null}function ga(e,t,n,o,r){return 1&e.mode?(e.flags|=65536,e.lanes=r,e):(e===t?e.flags|=65536:(e.flags|=128,n.flags|=131072,n.flags&=-52805,1===n.tag&&(null===n.alternate?n.tag=17:((t=Ui(-1,1)).tag=2,Bi(n,t,1))),n.lanes|=1),e)}var va=w.ReactCurrentOwner,ya=!1;function wa(e,t,n,o){t.child=null===e?xi(t,null,n,o):ki(t,e.child,n,o)}function ka(e,t,n,o,r){n=n.render;var i=t.ref;return Ri(t,r),o=bs(e,t,n,o,i,r),n=gs(),null===e||ya?(ii&&n&&ti(t),t.flags|=1,wa(e,t,o,r),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~r,qa(e,t,r))}function xa(e,t,n,o,r){if(null===e){var i=n.type;return"function"!=typeof i||Oc(i)||void 0!==i.defaultProps||null!==n.compare||void 0!==n.defaultProps?((e=Nc(n.type,null,o,t,t.mode,r)).ref=t.ref,e.return=t,t.child=e):(t.tag=15,t.type=i,_a(e,t,i,o,r))}if(i=e.child,!(e.lanes&r)){var s=i.memoizedProps;if((n=null!==(n=n.compare)?n:lo)(s,o)&&e.ref===t.ref)return qa(e,t,r)}return t.flags|=1,(e=Pc(i,o)).ref=t.ref,e.return=t,t.child=e}function _a(e,t,n,o,r){if(null!==e){var i=e.memoizedProps;if(lo(i,o)&&e.ref===t.ref){if(ya=!1,t.pendingProps=o=i,!(e.lanes&r))return t.lanes=e.lanes,qa(e,t,r);131072&e.flags&&(ya=!0)}}return Ca(e,t,n,o,r)}function Sa(e,t,n){var o=t.pendingProps,r=o.children,i=null!==e?e.memoizedState:null;if("hidden"===o.mode)if(1&t.mode){if(!(1073741824&n))return e=null!==i?i.baseLanes|n:n,t.lanes=t.childLanes=1073741824,t.memoizedState={baseLanes:e,cachePool:null,transitions:null},t.updateQueue=null,Er(Pl,Ol),Ol|=e,null;t.memoizedState={baseLanes:0,cachePool:null,transitions:null},o=null!==i?i.baseLanes:n,Er(Pl,Ol),Ol|=o}else t.memoizedState={baseLanes:0,cachePool:null,transitions:null},Er(Pl,Ol),Ol|=n;else null!==i?(o=i.baseLanes|n,t.memoizedState=null):o=n,Er(Pl,Ol),Ol|=o;return wa(e,t,r,n),t.child}function Aa(e,t){var n=t.ref;(null===e&&null!==n||null!==e&&e.ref!==n)&&(t.flags|=512,t.flags|=2097152)}function Ca(e,t,n,o,r){var i=Pr(n)?Lr:Tr.current;return i=Or(t,i),Ri(t,r),n=bs(e,t,n,o,i,r),o=gs(),null===e||ya?(ii&&o&&ti(t),t.flags|=1,wa(e,t,n,r),t.child):(t.updateQueue=e.updateQueue,t.flags&=-2053,e.lanes&=~r,qa(e,t,r))}function Ea(e,t,n,o,r){if(Pr(n)){var i=!0;Mr(t)}else i=!1;if(Ri(t,r),null===t.stateNode)Va(e,t),sa(t,n,o),la(t,n,o,r),o=!0;else if(null===e){var s=t.stateNode,a=t.memoizedProps;s.props=a;var l=s.context,c=n.contextType;"object"==typeof c&&null!==c?c=Li(c):c=Or(t,c=Pr(n)?Lr:Tr.current);var d=n.getDerivedStateFromProps,u="function"==typeof d||"function"==typeof s.getSnapshotBeforeUpdate;u||"function"!=typeof s.UNSAFE_componentWillReceiveProps&&"function"!=typeof s.componentWillReceiveProps||(a!==o||l!==c)&&aa(t,s,o,c),ji=!1;var p=t.memoizedState;s.state=p,Vi(t,o,s,r),l=t.memoizedState,a!==o||p!==l||Rr.current||ji?("function"==typeof d&&(oa(t,n,d,o),l=t.memoizedState),(a=ji||ia(t,n,a,o,p,l,c))?(u||"function"!=typeof s.UNSAFE_componentWillMount&&"function"!=typeof s.componentWillMount||("function"==typeof s.componentWillMount&&s.componentWillMount(),"function"==typeof s.UNSAFE_componentWillMount&&s.UNSAFE_componentWillMount()),"function"==typeof s.componentDidMount&&(t.flags|=4194308)):("function"==typeof s.componentDidMount&&(t.flags|=4194308),t.memoizedProps=o,t.memoizedState=l),s.props=o,s.state=l,s.context=c,o=a):("function"==typeof s.componentDidMount&&(t.flags|=4194308),o=!1)}else{s=t.stateNode,Fi(e,t),a=t.memoizedProps,c=t.type===t.elementType?a:na(t.type,a),s.props=c,u=t.pendingProps,p=s.context,"object"==typeof(l=n.contextType)&&null!==l?l=Li(l):l=Or(t,l=Pr(n)?Lr:Tr.current);var f=n.getDerivedStateFromProps;(d="function"==typeof f||"function"==typeof s.getSnapshotBeforeUpdate)||"function"!=typeof s.UNSAFE_componentWillReceiveProps&&"function"!=typeof s.componentWillReceiveProps||(a!==u||p!==l)&&aa(t,s,o,l),ji=!1,p=t.memoizedState,s.state=p,Vi(t,o,s,r);var m=t.memoizedState;a!==u||p!==m||Rr.current||ji?("function"==typeof f&&(oa(t,n,f,o),m=t.memoizedState),(c=ji||ia(t,n,c,o,p,m,l)||!1)?(d||"function"!=typeof s.UNSAFE_componentWillUpdate&&"function"!=typeof s.componentWillUpdate||("function"==typeof s.componentWillUpdate&&s.componentWillUpdate(o,m,l),"function"==typeof s.UNSAFE_componentWillUpdate&&s.UNSAFE_componentWillUpdate(o,m,l)),"function"==typeof s.componentDidUpdate&&(t.flags|=4),"function"==typeof s.getSnapshotBeforeUpdate&&(t.flags|=1024)):("function"!=typeof s.componentDidUpdate||a===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof s.getSnapshotBeforeUpdate||a===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),t.memoizedProps=o,t.memoizedState=m),s.props=o,s.state=m,s.context=l,o=c):("function"!=typeof s.componentDidUpdate||a===e.memoizedProps&&p===e.memoizedState||(t.flags|=4),"function"!=typeof s.getSnapshotBeforeUpdate||a===e.memoizedProps&&p===e.memoizedState||(t.flags|=1024),o=!1)}return Da(e,t,n,o,i,r)}function Da(e,t,n,o,r,i){Aa(e,t);var s=!!(128&t.flags);if(!o&&!s)return r&&Fr(t,n,!1),qa(e,t,i);o=t.stateNode,va.current=t;var a=s&&"function"!=typeof n.getDerivedStateFromError?null:o.render();return t.flags|=1,null!==e&&s?(t.child=ki(t,e.child,null,i),t.child=ki(t,null,a,i)):wa(e,t,a,i),t.memoizedState=o.state,r&&Fr(t,n,!0),t.child}function Ta(e){var t=e.stateNode;t.pendingContext?Ir(0,t.pendingContext,t.pendingContext!==t.context):t.context&&Ir(0,t.context,!1),Ki(e,t.containerInfo)}function Ra(e,t,n,o,r){return mi(),hi(r),t.flags|=256,wa(e,t,n,o),t.child}var La,Oa,Pa,Na,Ia={dehydrated:null,treeContext:null,retryLane:0};function ja(e){return{baseLanes:e,cachePool:null,transitions:null}}function Ma(e,t,n){var o,r=t.pendingProps,s=es.current,a=!1,l=!!(128&t.flags);if((o=l)||(o=(null===e||null!==e.memoizedState)&&!!(2&s)),o?(a=!0,t.flags&=-129):null!==e&&null===e.memoizedState||(s|=1),Er(es,1&s),null===e)return di(t),null!==(e=t.memoizedState)&&null!==(e=e.dehydrated)?(1&t.mode?"$!"===e.data?t.lanes=8:t.lanes=1073741824:t.lanes=1,null):(l=r.children,e=r.fallback,a?(r=t.mode,a=t.child,l={mode:"hidden",children:l},1&r||null===a?a=jc(l,r,0,null):(a.childLanes=0,a.pendingProps=l),e=Ic(e,r,n,null),a.return=t,e.return=t,a.sibling=e,t.child=a,t.child.memoizedState=ja(n),t.memoizedState=Ia,e):Fa(t,l));if(null!==(s=e.memoizedState)&&null!==(o=s.dehydrated))return function(e,t,n,o,r,s,a){if(n)return 256&t.flags?(t.flags&=-257,Ua(e,t,a,o=da(Error(i(422))))):null!==t.memoizedState?(t.child=e.child,t.flags|=128,null):(s=o.fallback,r=t.mode,o=jc({mode:"visible",children:o.children},r,0,null),(s=Ic(s,r,a,null)).flags|=2,o.return=t,s.return=t,o.sibling=s,t.child=o,1&t.mode&&ki(t,e.child,null,a),t.child.memoizedState=ja(a),t.memoizedState=Ia,s);if(!(1&t.mode))return Ua(e,t,a,null);if("$!"===r.data){if(o=r.nextSibling&&r.nextSibling.dataset)var l=o.dgst;return o=l,Ua(e,t,a,o=da(s=Error(i(419)),o,void 0))}if(l=!!(a&e.childLanes),ya||l){if(null!==(o=Tl)){switch(a&-a){case 4:r=2;break;case 16:r=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:r=32;break;case 536870912:r=268435456;break;default:r=0}0!==(r=r&(o.suspendedLanes|a)?0:r)&&r!==s.retryLane&&(s.retryLane=r,Ii(e,r),nc(o,e,r,-1))}return hc(),Ua(e,t,a,o=da(Error(i(421))))}return"$?"===r.data?(t.flags|=128,t.child=e.child,t=Ec.bind(null,e),r._reactRetry=t,null):(e=s.treeContext,ri=dr(r.nextSibling),oi=t,ii=!0,si=null,null!==e&&(Zr[Qr++]=Yr,Zr[Qr++]=Xr,Zr[Qr++]=Kr,Yr=e.id,Xr=e.overflow,Kr=t),t=Fa(t,o.children),t.flags|=4096,t)}(e,t,l,r,o,s,n);if(a){a=r.fallback,l=t.mode,o=(s=e.child).sibling;var c={mode:"hidden",children:r.children};return 1&l||t.child===s?(r=Pc(s,c)).subtreeFlags=14680064&s.subtreeFlags:((r=t.child).childLanes=0,r.pendingProps=c,t.deletions=null),null!==o?a=Pc(o,a):(a=Ic(a,l,n,null)).flags|=2,a.return=t,r.return=t,r.sibling=a,t.child=r,r=a,a=t.child,l=null===(l=e.child.memoizedState)?ja(n):{baseLanes:l.baseLanes|n,cachePool:null,transitions:l.transitions},a.memoizedState=l,a.childLanes=e.childLanes&~n,t.memoizedState=Ia,r}return e=(a=e.child).sibling,r=Pc(a,{mode:"visible",children:r.children}),!(1&t.mode)&&(r.lanes=n),r.return=t,r.sibling=null,null!==e&&(null===(n=t.deletions)?(t.deletions=[e],t.flags|=16):n.push(e)),t.child=r,t.memoizedState=null,r}function Fa(e,t){return(t=jc({mode:"visible",children:t},e.mode,0,null)).return=e,e.child=t}function Ua(e,t,n,o){return null!==o&&hi(o),ki(t,e.child,null,n),(e=Fa(t,t.pendingProps.children)).flags|=2,t.memoizedState=null,e}function Ba(e,t,n){e.lanes|=t;var o=e.alternate;null!==o&&(o.lanes|=t),Ti(e.return,t,n)}function za(e,t,n,o,r){var i=e.memoizedState;null===i?e.memoizedState={isBackwards:t,rendering:null,renderingStartTime:0,last:o,tail:n,tailMode:r}:(i.isBackwards=t,i.rendering=null,i.renderingStartTime=0,i.last=o,i.tail=n,i.tailMode=r)}function $a(e,t,n){var o=t.pendingProps,r=o.revealOrder,i=o.tail;if(wa(e,t,o.children,n),2&(o=es.current))o=1&o|2,t.flags|=128;else{if(null!==e&&128&e.flags)e:for(e=t.child;null!==e;){if(13===e.tag)null!==e.memoizedState&&Ba(e,n,t);else if(19===e.tag)Ba(e,n,t);else if(null!==e.child){e.child.return=e,e=e.child;continue}if(e===t)break e;for(;null===e.sibling;){if(null===e.return||e.return===t)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}o&=1}if(Er(es,o),1&t.mode)switch(r){case"forwards":for(n=t.child,r=null;null!==n;)null!==(e=n.alternate)&&null===ts(e)&&(r=n),n=n.sibling;null===(n=r)?(r=t.child,t.child=null):(r=n.sibling,n.sibling=null),za(t,!1,r,n,i);break;case"backwards":for(n=null,r=t.child,t.child=null;null!==r;){if(null!==(e=r.alternate)&&null===ts(e)){t.child=r;break}e=r.sibling,r.sibling=n,n=r,r=e}za(t,!0,n,null,i);break;case"together":za(t,!1,null,null,void 0);break;default:t.memoizedState=null}else t.memoizedState=null;return t.child}function Va(e,t){!(1&t.mode)&&null!==e&&(e.alternate=null,t.alternate=null,t.flags|=2)}function qa(e,t,n){if(null!==e&&(t.dependencies=e.dependencies),jl|=t.lanes,!(n&t.childLanes))return null;if(null!==e&&t.child!==e.child)throw Error(i(153));if(null!==t.child){for(n=Pc(e=t.child,e.pendingProps),t.child=n,n.return=t;null!==e.sibling;)e=e.sibling,(n=n.sibling=Pc(e,e.pendingProps)).return=t;n.sibling=null}return t.child}function Ha(e,t){if(!ii)switch(e.tailMode){case"hidden":t=e.tail;for(var n=null;null!==t;)null!==t.alternate&&(n=t),t=t.sibling;null===n?e.tail=null:n.sibling=null;break;case"collapsed":n=e.tail;for(var o=null;null!==n;)null!==n.alternate&&(o=n),n=n.sibling;null===o?t||null===e.tail?e.tail=null:e.tail.sibling=null:o.sibling=null}}function Ga(e){var t=null!==e.alternate&&e.alternate.child===e.child,n=0,o=0;if(t)for(var r=e.child;null!==r;)n|=r.lanes|r.childLanes,o|=14680064&r.subtreeFlags,o|=14680064&r.flags,r.return=e,r=r.sibling;else for(r=e.child;null!==r;)n|=r.lanes|r.childLanes,o|=r.subtreeFlags,o|=r.flags,r.return=e,r=r.sibling;return e.subtreeFlags|=o,e.childLanes=n,t}function Wa(e,t,n){var o=t.pendingProps;switch(ni(t),t.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return Ga(t),null;case 1:case 17:return Pr(t.type)&&Nr(),Ga(t),null;case 3:return o=t.stateNode,Yi(),Cr(Rr),Cr(Tr),os(),o.pendingContext&&(o.context=o.pendingContext,o.pendingContext=null),null!==e&&null!==e.child||(pi(t)?t.flags|=4:null===e||e.memoizedState.isDehydrated&&!(256&t.flags)||(t.flags|=1024,null!==si&&(sc(si),si=null))),Oa(e,t),Ga(t),null;case 5:Ji(t);var r=Qi(Zi.current);if(n=t.type,null!==e&&null!=t.stateNode)Pa(e,t,n,o,r),e.ref!==t.ref&&(t.flags|=512,t.flags|=2097152);else{if(!o){if(null===t.stateNode)throw Error(i(166));return Ga(t),null}if(e=Qi(Gi.current),pi(t)){o=t.stateNode,n=t.type;var s=t.memoizedProps;switch(o[fr]=t,o[mr]=s,e=!!(1&t.mode),n){case"dialog":Bo("cancel",o),Bo("close",o);break;case"iframe":case"object":case"embed":Bo("load",o);break;case"video":case"audio":for(r=0;r <\/script>",e=e.removeChild(e.firstChild)):"string"==typeof o.is?e=l.createElement(n,{is:o.is}):(e=l.createElement(n),"select"===n&&(l=e,o.multiple?l.multiple=!0:o.size&&(l.size=o.size))):e=l.createElementNS(e,n),e[fr]=t,e[mr]=o,La(e,t,!1,!1),t.stateNode=e;e:{switch(l=ye(n,o),n){case"dialog":Bo("cancel",e),Bo("close",e),r=o;break;case"iframe":case"object":case"embed":Bo("load",e),r=o;break;case"video":case"audio":for(r=0;r $l&&(t.flags|=128,o=!0,Ha(s,!1),t.lanes=4194304)}else{if(!o)if(null!==(e=ts(l))){if(t.flags|=128,o=!0,null!==(n=e.updateQueue)&&(t.updateQueue=n,t.flags|=4),Ha(s,!0),null===s.tail&&"hidden"===s.tailMode&&!l.alternate&&!ii)return Ga(t),null}else 2*Ye()-s.renderingStartTime>$l&&1073741824!==n&&(t.flags|=128,o=!0,Ha(s,!1),t.lanes=4194304);s.isBackwards?(l.sibling=t.child,t.child=l):(null!==(n=s.last)?n.sibling=l:t.child=l,s.last=l)}return null!==s.tail?(t=s.tail,s.rendering=t,s.tail=t.sibling,s.renderingStartTime=Ye(),t.sibling=null,n=es.current,Er(es,o?1&n|2:1&n),t):(Ga(t),null);case 22:case 23:return uc(),o=null!==t.memoizedState,null!==e&&null!==e.memoizedState!==o&&(t.flags|=8192),o&&1&t.mode?!!(1073741824&Ol)&&(Ga(t),6&t.subtreeFlags&&(t.flags|=8192)):Ga(t),null;case 24:case 25:return null}throw Error(i(156,t.tag))}function Za(e,t){switch(ni(t),t.tag){case 1:return Pr(t.type)&&Nr(),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return Yi(),Cr(Rr),Cr(Tr),os(),65536&(e=t.flags)&&!(128&e)?(t.flags=-65537&e|128,t):null;case 5:return Ji(t),null;case 13:if(Cr(es),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(i(340));mi()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return Cr(es),null;case 4:return Yi(),null;case 10:return Di(t.type._context),null;case 22:case 23:return uc(),null;default:return null}}La=function(e,t){for(var n=t.child;null!==n;){if(5===n.tag||6===n.tag)e.appendChild(n.stateNode);else if(4!==n.tag&&null!==n.child){n.child.return=n,n=n.child;continue}if(n===t)break;for(;null===n.sibling;){if(null===n.return||n.return===t)return;n=n.return}n.sibling.return=n.return,n=n.sibling}},Oa=function(){},Pa=function(e,t,n,o){var r=e.memoizedProps;if(r!==o){e=t.stateNode,Qi(Gi.current);var i,s=null;switch(n){case"input":r=Q(e,r),o=Q(e,o),s=[];break;case"select":r=M({},r,{value:void 0}),o=M({},o,{value:void 0}),s=[];break;case"textarea":r=oe(e,r),o=oe(e,o),s=[];break;default:"function"!=typeof r.onClick&&"function"==typeof o.onClick&&(e.onclick=er)}for(d in ve(n,o),n=null,r)if(!o.hasOwnProperty(d)&&r.hasOwnProperty(d)&&null!=r[d])if("style"===d){var l=r[d];for(i in l)l.hasOwnProperty(i)&&(n||(n={}),n[i]="")}else"dangerouslySetInnerHTML"!==d&&"children"!==d&&"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&"autoFocus"!==d&&(a.hasOwnProperty(d)?s||(s=[]):(s=s||[]).push(d,null));for(d in o){var c=o[d];if(l=null!=r?r[d]:void 0,o.hasOwnProperty(d)&&c!==l&&(null!=c||null!=l))if("style"===d)if(l){for(i in l)!l.hasOwnProperty(i)||c&&c.hasOwnProperty(i)||(n||(n={}),n[i]="");for(i in c)c.hasOwnProperty(i)&&l[i]!==c[i]&&(n||(n={}),n[i]=c[i])}else n||(s||(s=[]),s.push(d,n)),n=c;else"dangerouslySetInnerHTML"===d?(c=c?c.__html:void 0,l=l?l.__html:void 0,null!=c&&l!==c&&(s=s||[]).push(d,c)):"children"===d?"string"!=typeof c&&"number"!=typeof c||(s=s||[]).push(d,""+c):"suppressContentEditableWarning"!==d&&"suppressHydrationWarning"!==d&&(a.hasOwnProperty(d)?(null!=c&&"onScroll"===d&&Bo("scroll",e),s||l===c||(s=[])):(s=s||[]).push(d,c))}n&&(s=s||[]).push("style",n);var d=s;(t.updateQueue=d)&&(t.flags|=4)}},Na=function(e,t,n,o){n!==o&&(t.flags|=4)};var Qa=!1,Ka=!1,Ya="function"==typeof WeakSet?WeakSet:Set,Xa=null;function Ja(e,t){var n=e.ref;if(null!==n)if("function"==typeof n)try{n(null)}catch(o){Sc(e,t,o)}else n.current=null}function el(e,t,n){try{n()}catch(o){Sc(e,t,o)}}var tl=!1;function nl(e,t,n){var o=t.updateQueue;if(null!==(o=null!==o?o.lastEffect:null)){var r=o=o.next;do{if((r.tag&e)===e){var i=r.destroy;r.destroy=void 0,void 0!==i&&el(t,n,i)}r=r.next}while(r!==o)}}function ol(e,t){if(null!==(t=null!==(t=t.updateQueue)?t.lastEffect:null)){var n=t=t.next;do{if((n.tag&e)===e){var o=n.create;n.destroy=o()}n=n.next}while(n!==t)}}function rl(e){var t=e.ref;if(null!==t){var n=e.stateNode;e.tag,e=n,"function"==typeof t?t(e):t.current=e}}function il(e){var t=e.alternate;null!==t&&(e.alternate=null,il(t)),e.child=null,e.deletions=null,e.sibling=null,5===e.tag&&(null!==(t=e.stateNode)&&(delete t[fr],delete t[mr],delete t[br],delete t[gr],delete t[vr])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function sl(e){return 5===e.tag||3===e.tag||4===e.tag}function al(e){e:for(;;){for(;null===e.sibling;){if(null===e.return||sl(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;5!==e.tag&&6!==e.tag&&18!==e.tag;){if(2&e.flags)continue e;if(null===e.child||4===e.tag)continue e;e.child.return=e,e=e.child}if(!(2&e.flags))return e.stateNode}}function ll(e,t,n){var o=e.tag;if(5===o||6===o)e=e.stateNode,t?8===n.nodeType?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(8===n.nodeType?(t=n.parentNode).insertBefore(e,n):(t=n).appendChild(e),null!=(n=n._reactRootContainer)||null!==t.onclick||(t.onclick=er));else if(4!==o&&null!==(e=e.child))for(ll(e,t,n),e=e.sibling;null!==e;)ll(e,t,n),e=e.sibling}function cl(e,t,n){var o=e.tag;if(5===o||6===o)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(4!==o&&null!==(e=e.child))for(cl(e,t,n),e=e.sibling;null!==e;)cl(e,t,n),e=e.sibling}var dl=null,ul=!1;function pl(e,t,n){for(n=n.child;null!==n;)fl(e,t,n),n=n.sibling}function fl(e,t,n){if(it&&"function"==typeof it.onCommitFiberUnmount)try{it.onCommitFiberUnmount(rt,n)}catch(a){}switch(n.tag){case 5:Ka||Ja(n,t);case 6:var o=dl,r=ul;dl=null,pl(e,t,n),ul=r,null!==(dl=o)&&(ul?(e=dl,n=n.stateNode,8===e.nodeType?e.parentNode.removeChild(n):e.removeChild(n)):dl.removeChild(n.stateNode));break;case 18:null!==dl&&(ul?(e=dl,n=n.stateNode,8===e.nodeType?cr(e.parentNode,n):1===e.nodeType&&cr(e,n),$t(e)):cr(dl,n.stateNode));break;case 4:o=dl,r=ul,dl=n.stateNode.containerInfo,ul=!0,pl(e,t,n),dl=o,ul=r;break;case 0:case 11:case 14:case 15:if(!Ka&&(null!==(o=n.updateQueue)&&null!==(o=o.lastEffect))){r=o=o.next;do{var i=r,s=i.destroy;i=i.tag,void 0!==s&&(2&i||4&i)&&el(n,t,s),r=r.next}while(r!==o)}pl(e,t,n);break;case 1:if(!Ka&&(Ja(n,t),"function"==typeof(o=n.stateNode).componentWillUnmount))try{o.props=n.memoizedProps,o.state=n.memoizedState,o.componentWillUnmount()}catch(a){Sc(n,t,a)}pl(e,t,n);break;case 21:pl(e,t,n);break;case 22:1&n.mode?(Ka=(o=Ka)||null!==n.memoizedState,pl(e,t,n),Ka=o):pl(e,t,n);break;default:pl(e,t,n)}}function ml(e){var t=e.updateQueue;if(null!==t){e.updateQueue=null;var n=e.stateNode;null===n&&(n=e.stateNode=new Ya),t.forEach((function(t){var o=Dc.bind(null,e,t);n.has(t)||(n.add(t),t.then(o,o))}))}}function hl(e,t){var n=t.deletions;if(null!==n)for(var o=0;o r&&(r=a),o&=~s}if(o=r,10<(o=(120>(o=Ye()-o)?120:480>o?480:1080>o?1080:1920>o?1920:3e3>o?3e3:4320>o?4320:1960*Sl(o/1960))-o)){e.timeoutHandle=rr(kc.bind(null,e,Bl,Vl),o);break}kc(e,Bl,Vl);break;default:throw Error(i(329))}}}return oc(e,Ye()),e.callbackNode===n?rc.bind(null,e):null}function ic(e,t){var n=Ul;return e.current.memoizedState.isDehydrated&&(pc(e,t).flags|=256),2!==(e=bc(e,t))&&(t=Bl,Bl=n,null!==t&&sc(t)),e}function sc(e){null===Bl?Bl=e:Bl.push.apply(Bl,e)}function ac(e,t){for(t&=~Fl,t&=~Ml,e.suspendedLanes|=t,e.pingedLanes&=~t,e=e.expirationTimes;0 e?16:e,null===Zl)var o=!1;else{if(e=Zl,Zl=null,Ql=0,6&Dl)throw Error(i(331));var r=Dl;for(Dl|=4,Xa=e.current;null!==Xa;){var s=Xa,a=s.child;if(16&Xa.flags){var l=s.deletions;if(null!==l){for(var c=0;c Ye()-zl?pc(e,0):Fl|=n),oc(e,t)}function Cc(e,t){0===t&&(1&e.mode?(t=dt,!(130023424&(dt<<=1))&&(dt=4194304)):t=1);var n=ec();null!==(e=Ii(e,t))&&(gt(e,t,n),oc(e,n))}function Ec(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),Cc(e,n)}function Dc(e,t){var n=0;switch(e.tag){case 13:var o=e.stateNode,r=e.memoizedState;null!==r&&(n=r.retryLane);break;case 19:o=e.stateNode;break;default:throw Error(i(314))}null!==o&&o.delete(t),Cc(e,n)}function Tc(e,t){return We(e,t)}function Rc(e,t,n,o){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=o,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Lc(e,t,n,o){return new Rc(e,t,n,o)}function Oc(e){return!(!(e=e.prototype)||!e.isReactComponent)}function Pc(e,t){var n=e.alternate;return null===n?((n=Lc(e.tag,t,e.key,e.mode)).elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=14680064&e.flags,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=null===t?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Nc(e,t,n,o,r,s){var a=2;if(o=e,"function"==typeof e)Oc(e)&&(a=1);else if("string"==typeof e)a=5;else e:switch(e){case _:return Ic(n.children,r,s,t);case S:a=8,r|=8;break;case A:return(e=Lc(12,n,t,2|r)).elementType=A,e.lanes=s,e;case T:return(e=Lc(13,n,t,r)).elementType=T,e.lanes=s,e;case R:return(e=Lc(19,n,t,r)).elementType=R,e.lanes=s,e;case P:return jc(n,r,s,t);default:if("object"==typeof e&&null!==e)switch(e.$$typeof){case C:a=10;break e;case E:a=9;break e;case D:a=11;break e;case L:a=14;break e;case O:a=16,o=null;break e}throw Error(i(130,null==e?e:typeof e,""))}return(t=Lc(a,n,t,r)).elementType=e,t.type=o,t.lanes=s,t}function Ic(e,t,n,o){return(e=Lc(7,e,o,t)).lanes=n,e}function jc(e,t,n,o){return(e=Lc(22,e,o,t)).elementType=P,e.lanes=n,e.stateNode={isHidden:!1},e}function Mc(e,t,n){return(e=Lc(6,e,null,t)).lanes=n,e}function Fc(e,t,n){return(t=Lc(4,null!==e.children?e.children:[],e.key,t)).lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function Uc(e,t,n,o,r){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=bt(0),this.expirationTimes=bt(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=bt(0),this.identifierPrefix=o,this.onRecoverableError=r,this.mutableSourceEagerHydrationData=null}function Bc(e,t,n,o,r,i,s,a,l){return e=new Uc(e,t,n,a,l),1===t?(t=1,!0===i&&(t|=8)):t=0,i=Lc(3,null,null,t),e.current=i,i.stateNode=e,i.memoizedState={element:o,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Mi(i),e}function zc(e){if(!e)return Dr;e:{if($e(e=e._reactInternals)!==e||1!==e.tag)throw Error(i(170));var t=e;do{switch(t.tag){case 3:t=t.stateNode.context;break e;case 1:if(Pr(t.type)){t=t.stateNode.__reactInternalMemoizedMergedChildContext;break e}}t=t.return}while(null!==t);throw Error(i(171))}if(1===e.tag){var n=e.type;if(Pr(n))return jr(e,n,t)}return t}function $c(e,t,n,o,r,i,s,a,l){return(e=Bc(n,o,!0,e,0,i,0,a,l)).context=zc(null),n=e.current,(i=Ui(o=ec(),r=tc(n))).callback=null!=t?t:null,Bi(n,i,r),e.current.lanes=r,gt(e,r,o),oc(e,o),e}function Vc(e,t,n,o){var r=t.current,i=ec(),s=tc(r);return n=zc(n),null===t.context?t.context=n:t.pendingContext=n,(t=Ui(i,s)).payload={element:e},null!==(o=void 0===o?null:o)&&(t.callback=o),null!==(e=Bi(r,t,s))&&(nc(e,r,s,i),zi(e,r,s)),s}function qc(e){return(e=e.current).child?(e.child.tag,e.child.stateNode):null}function Hc(e,t){if(null!==(e=e.memoizedState)&&null!==e.dehydrated){var n=e.retryLane;e.retryLane=0!==n&&n {"use strict";var o=n(961);t.createRoot=o.createRoot,t.hydrateRoot=o.hydrateRoot},961:(e,t,n)=>{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}(),e.exports=n(2551)},115:e=>{var t="undefined"!=typeof Element,n="function"==typeof Map,o="function"==typeof Set,r="function"==typeof ArrayBuffer&&!!ArrayBuffer.isView;function i(e,s){if(e===s)return!0;if(e&&s&&"object"==typeof e&&"object"==typeof s){if(e.constructor!==s.constructor)return!1;var a,l,c,d;if(Array.isArray(e)){if((a=e.length)!=s.length)return!1;for(l=a;0!=l--;)if(!i(e[l],s[l]))return!1;return!0}if(n&&e instanceof Map&&s instanceof Map){if(e.size!==s.size)return!1;for(d=e.entries();!(l=d.next()).done;)if(!s.has(l.value[0]))return!1;for(d=e.entries();!(l=d.next()).done;)if(!i(l.value[1],s.get(l.value[0])))return!1;return!0}if(o&&e instanceof Set&&s instanceof Set){if(e.size!==s.size)return!1;for(d=e.entries();!(l=d.next()).done;)if(!s.has(l.value[0]))return!1;return!0}if(r&&ArrayBuffer.isView(e)&&ArrayBuffer.isView(s)){if((a=e.length)!=s.length)return!1;for(l=a;0!=l--;)if(e[l]!==s[l])return!1;return!0}if(e.constructor===RegExp)return e.source===s.source&&e.flags===s.flags;if(e.valueOf!==Object.prototype.valueOf&&"function"==typeof e.valueOf&&"function"==typeof s.valueOf)return e.valueOf()===s.valueOf();if(e.toString!==Object.prototype.toString&&"function"==typeof e.toString&&"function"==typeof s.toString)return e.toString()===s.toString();if((a=(c=Object.keys(e)).length)!==Object.keys(s).length)return!1;for(l=a;0!=l--;)if(!Object.prototype.hasOwnProperty.call(s,c[l]))return!1;if(t&&e instanceof Element)return!1;for(l=a;0!=l--;)if(("_owner"!==c[l]&&"__v"!==c[l]&&"__o"!==c[l]||!e.$$typeof)&&!i(e[c[l]],s[c[l]]))return!1;return!0}return e!=e&&s!=s}e.exports=function(e,t){try{return i(e,t)}catch(n){if((n.message||"").match(/stack|recursion/i))return console.warn("react-fast-compare cannot handle circular refs"),!1;throw n}}},545:(e,t,n)=>{"use strict";n.d(t,{mg:()=>J,vd:()=>H});var o=n(6540),r=n(5556),i=n.n(r),s=n(115),a=n.n(s),l=n(311),c=n.n(l),d=n(2833),u=n.n(d);function p(){return p=Object.assign||function(e){for(var t=1;t =0||(r[n]=e[n]);return r}var b={BASE:"base",BODY:"body",HEAD:"head",HTML:"html",LINK:"link",META:"meta",NOSCRIPT:"noscript",SCRIPT:"script",STYLE:"style",TITLE:"title",FRAGMENT:"Symbol(react.fragment)"},g={rel:["amphtml","canonical","alternate"]},v={type:["application/ld+json"]},y={charset:"",name:["robots","description"],property:["og:type","og:title","og:url","og:image","og:image:alt","og:description","twitter:url","twitter:title","twitter:description","twitter:image","twitter:image:alt","twitter:card","twitter:site"]},w=Object.keys(b).map((function(e){return b[e]})),k={accesskey:"accessKey",charset:"charSet",class:"className",contenteditable:"contentEditable",contextmenu:"contextMenu","http-equiv":"httpEquiv",itemprop:"itemProp",tabindex:"tabIndex"},x=Object.keys(k).reduce((function(e,t){return e[k[t]]=t,e}),{}),_=function(e,t){for(var n=e.length-1;n>=0;n-=1){var o=e[n];if(Object.prototype.hasOwnProperty.call(o,t))return o[t]}return null},S=function(e){var t=_(e,b.TITLE),n=_(e,"titleTemplate");if(Array.isArray(t)&&(t=t.join("")),n&&t)return n.replace(/%s/g,(function(){return t}));var o=_(e,"defaultTitle");return t||o||void 0},A=function(e){return _(e,"onChangeClientState")||function(){}},C=function(e,t){return t.filter((function(t){return void 0!==t[e]})).map((function(t){return t[e]})).reduce((function(e,t){return p({},e,t)}),{})},E=function(e,t){return t.filter((function(e){return void 0!==e[b.BASE]})).map((function(e){return e[b.BASE]})).reverse().reduce((function(t,n){if(!t.length)for(var o=Object.keys(n),r=0;r /g,">").replace(/"/g,""").replace(/'/g,"'")},I=function(e){return Object.keys(e).reduce((function(t,n){var o=void 0!==e[n]?n+'="'+e[n]+'"':""+n;return t?t+" "+o:o}),"")},j=function(e,t){return void 0===t&&(t={}),Object.keys(e).reduce((function(t,n){return t[k[n]||n]=e[n],t}),t)},M=function(e,t){return t.map((function(t,n){var r,i=((r={key:n})["data-rh"]=!0,r);return Object.keys(t).forEach((function(e){var n=k[e]||e;"innerHTML"===n||"cssText"===n?i.dangerouslySetInnerHTML={__html:t.innerHTML||t.cssText}:i[n]=t[e]})),o.createElement(e,i)}))},F=function(e,t,n){switch(e){case b.TITLE:return{toComponent:function(){return n=t.titleAttributes,(r={key:e=t.title})["data-rh"]=!0,i=j(n,r),[o.createElement(b.TITLE,i,e)];var e,n,r,i},toString:function(){return function(e,t,n,o){var r=I(n),i=R(t);return r?"<"+e+' data-rh="true" '+r+">"+N(i,o)+""+e+">":"<"+e+' data-rh="true">'+N(i,o)+""+e+">"}(e,t.title,t.titleAttributes,n)}};case"bodyAttributes":case"htmlAttributes":return{toComponent:function(){return j(t)},toString:function(){return I(t)}};default:return{toComponent:function(){return M(e,t)},toString:function(){return function(e,t,n){return t.reduce((function(t,o){var r=Object.keys(o).filter((function(e){return!("innerHTML"===e||"cssText"===e)})).reduce((function(e,t){var r=void 0===o[t]?t:t+'="'+N(o[t],n)+'"';return e?e+" "+r:r}),""),i=o.innerHTML||o.cssText||"",s=-1===P.indexOf(e);return t+"<"+e+' data-rh="true" '+r+(s?"/>":">"+i+""+e+">")}),"")}(e,t,n)}}}},U=function(e){var t=e.baseTag,n=e.bodyAttributes,o=e.encode,r=e.htmlAttributes,i=e.noscriptTags,s=e.styleTags,a=e.title,l=void 0===a?"":a,c=e.titleAttributes,d=e.linkTags,u=e.metaTags,p=e.scriptTags,f={toComponent:function(){},toString:function(){return""}};if(e.prioritizeSeoTags){var m=function(e){var t=e.linkTags,n=e.scriptTags,o=e.encode,r=L(e.metaTags,y),i=L(t,g),s=L(n,v);return{priorityMethods:{toComponent:function(){return[].concat(M(b.META,r.priority),M(b.LINK,i.priority),M(b.SCRIPT,s.priority))},toString:function(){return F(b.META,r.priority,o)+" "+F(b.LINK,i.priority,o)+" "+F(b.SCRIPT,s.priority,o)}},metaTags:r.default,linkTags:i.default,scriptTags:s.default}}(e);f=m.priorityMethods,d=m.linkTags,u=m.metaTags,p=m.scriptTags}return{priority:f,base:F(b.BASE,t,o),bodyAttributes:F("bodyAttributes",n,o),htmlAttributes:F("htmlAttributes",r,o),link:F(b.LINK,d,o),meta:F(b.META,u,o),noscript:F(b.NOSCRIPT,i,o),script:F(b.SCRIPT,p,o),style:F(b.STYLE,s,o),title:F(b.TITLE,{title:l,titleAttributes:c},o)}},B=[],z=function(e,t){var n=this;void 0===t&&(t="undefined"!=typeof document),this.instances=[],this.value={setHelmet:function(e){n.context.helmet=e},helmetInstances:{get:function(){return n.canUseDOM?B:n.instances},add:function(e){(n.canUseDOM?B:n.instances).push(e)},remove:function(e){var t=(n.canUseDOM?B:n.instances).indexOf(e);(n.canUseDOM?B:n.instances).splice(t,1)}}},this.context=e,this.canUseDOM=t,t||(e.helmet=U({baseTag:[],bodyAttributes:{},encodeSpecialCharacters:!0,htmlAttributes:{},linkTags:[],metaTags:[],noscriptTags:[],scriptTags:[],styleTags:[],title:"",titleAttributes:{}}))},$=o.createContext({}),V=i().shape({setHelmet:i().func,helmetInstances:i().shape({get:i().func,add:i().func,remove:i().func})}),q="undefined"!=typeof document,H=function(e){function t(n){var o;return(o=e.call(this,n)||this).helmetData=new z(o.props.context,t.canUseDOM),o}return f(t,e),t.prototype.render=function(){return o.createElement($.Provider,{value:this.helmetData.value},this.props.children)},t}(o.Component);H.canUseDOM=q,H.propTypes={context:i().shape({helmet:i().shape()}),children:i().node.isRequired},H.defaultProps={context:{}},H.displayName="HelmetProvider";var G=function(e,t){var n,o=document.head||document.querySelector(b.HEAD),r=o.querySelectorAll(e+"[data-rh]"),i=[].slice.call(r),s=[];return t&&t.length&&t.forEach((function(t){var o=document.createElement(e);for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&("innerHTML"===r?o.innerHTML=t.innerHTML:"cssText"===r?o.styleSheet?o.styleSheet.cssText=t.cssText:o.appendChild(document.createTextNode(t.cssText)):o.setAttribute(r,void 0===t[r]?"":t[r]));o.setAttribute("data-rh","true"),i.some((function(e,t){return n=t,o.isEqualNode(e)}))?i.splice(n,1):s.push(o)})),i.forEach((function(e){return e.parentNode.removeChild(e)})),s.forEach((function(e){return o.appendChild(e)})),{oldTags:i,newTags:s}},W=function(e,t){var n=document.getElementsByTagName(e)[0];if(n){for(var o=n.getAttribute("data-rh"),r=o?o.split(","):[],i=[].concat(r),s=Object.keys(t),a=0;a =0;u-=1)n.removeAttribute(i[u]);r.length===i.length?n.removeAttribute("data-rh"):n.getAttribute("data-rh")!==s.join(",")&&n.setAttribute("data-rh",s.join(","))}},Z=function(e,t){var n=e.baseTag,o=e.htmlAttributes,r=e.linkTags,i=e.metaTags,s=e.noscriptTags,a=e.onChangeClientState,l=e.scriptTags,c=e.styleTags,d=e.title,u=e.titleAttributes;W(b.BODY,e.bodyAttributes),W(b.HTML,o),function(e,t){void 0!==e&&document.title!==e&&(document.title=R(e)),W(b.TITLE,t)}(d,u);var p={baseTag:G(b.BASE,n),linkTags:G(b.LINK,r),metaTags:G(b.META,i),noscriptTags:G(b.NOSCRIPT,s),scriptTags:G(b.SCRIPT,l),styleTags:G(b.STYLE,c)},f={},m={};Object.keys(p).forEach((function(e){var t=p[e],n=t.newTags,o=t.oldTags;n.length&&(f[e]=n),o.length&&(m[e]=p[e].oldTags)})),t&&t(),a(e,f,m)},Q=null,K=function(e){function t(){for(var t,n=arguments.length,o=new Array(n),r=0;r elements are self-closing and can not contain children. Refer to our API for more information.")}},n.flattenArrayTypeChildren=function(e){var t,n=e.child,o=e.arrayTypeChildren;return p({},o,((t={})[n.type]=[].concat(o[n.type]||[],[p({},e.newChildProps,this.mapNestedChildrenToProps(n,e.nestedChildren))]),t))},n.mapObjectTypeChildren=function(e){var t,n,o=e.child,r=e.newProps,i=e.newChildProps,s=e.nestedChildren;switch(o.type){case b.TITLE:return p({},r,((t={})[o.type]=s,t.titleAttributes=p({},i),t));case b.BODY:return p({},r,{bodyAttributes:p({},i)});case b.HTML:return p({},r,{htmlAttributes:p({},i)});default:return p({},r,((n={})[o.type]=p({},i),n))}},n.mapArrayTypeChildrenToProps=function(e,t){var n=p({},t);return Object.keys(e).forEach((function(t){var o;n=p({},n,((o={})[t]=e[t],o))})),n},n.warnOnInvalidChildren=function(e,t){return c()(w.some((function(t){return e.type===t})),"function"==typeof e.type?"You may be attempting to nest components within each other, which is not allowed. Refer to our API for more information.":"Only elements types "+w.join(", ")+" are allowed. Helmet does not support rendering <"+e.type+"> elements. Refer to our API for more information."),c()(!t||"string"==typeof t||Array.isArray(t)&&!t.some((function(e){return"string"!=typeof e})),"Helmet expects a string as a child of <"+e.type+">. Did you forget to wrap your children in braces? ( <"+e.type+">{``}"+e.type+"> ) Refer to our API for more information."),!0},n.mapChildrenToProps=function(e,t){var n=this,r={};return o.Children.forEach(e,(function(e){if(e&&e.props){var o=e.props,i=o.children,s=h(o,Y),a=Object.keys(s).reduce((function(e,t){return e[x[t]||t]=s[t],e}),{}),l=e.type;switch("symbol"==typeof l?l=l.toString():n.warnOnInvalidChildren(e,i),l){case b.FRAGMENT:t=n.mapChildrenToProps(i,t);break;case b.LINK:case b.META:case b.NOSCRIPT:case b.SCRIPT:case b.STYLE:r=n.flattenArrayTypeChildren({child:e,arrayTypeChildren:r,newChildProps:a,nestedChildren:i});break;default:t=n.mapObjectTypeChildren({child:e,newProps:t,newChildProps:a,nestedChildren:i})}}})),this.mapArrayTypeChildrenToProps(r,t)},n.render=function(){var e=this.props,t=e.children,n=h(e,X),r=p({},n),i=n.helmetData;return t&&(r=this.mapChildrenToProps(t,r)),!i||i instanceof z||(i=new z(i.context,i.instances)),i?o.createElement(K,p({},r,{context:i.value,helmetData:void 0})):o.createElement($.Consumer,null,(function(e){return o.createElement(K,p({},r,{context:e}))}))},t}(o.Component);J.propTypes={base:i().object,bodyAttributes:i().object,children:i().oneOfType([i().arrayOf(i().node),i().node]),defaultTitle:i().string,defer:i().bool,encodeSpecialCharacters:i().bool,htmlAttributes:i().object,link:i().arrayOf(i().object),meta:i().arrayOf(i().object),noscript:i().arrayOf(i().object),onChangeClientState:i().func,script:i().arrayOf(i().object),style:i().arrayOf(i().object),title:i().string,titleAttributes:i().object,titleTemplate:i().string,prioritizeSeoTags:i().bool,helmetData:i().object},J.defaultProps={defer:!0,encodeSpecialCharacters:!0,prioritizeSeoTags:!1},J.displayName="Helmet"},2799:(e,t)=>{"use strict";var n="function"==typeof Symbol&&Symbol.for,o=n?Symbol.for("react.element"):60103,r=n?Symbol.for("react.portal"):60106,i=n?Symbol.for("react.fragment"):60107,s=n?Symbol.for("react.strict_mode"):60108,a=n?Symbol.for("react.profiler"):60114,l=n?Symbol.for("react.provider"):60109,c=n?Symbol.for("react.context"):60110,d=n?Symbol.for("react.async_mode"):60111,u=n?Symbol.for("react.concurrent_mode"):60111,p=n?Symbol.for("react.forward_ref"):60112,f=n?Symbol.for("react.suspense"):60113,m=n?Symbol.for("react.suspense_list"):60120,h=n?Symbol.for("react.memo"):60115,b=n?Symbol.for("react.lazy"):60116,g=n?Symbol.for("react.block"):60121,v=n?Symbol.for("react.fundamental"):60117,y=n?Symbol.for("react.responder"):60118,w=n?Symbol.for("react.scope"):60119;function k(e){if("object"==typeof e&&null!==e){var t=e.$$typeof;switch(t){case o:switch(e=e.type){case d:case u:case i:case a:case s:case f:return e;default:switch(e=e&&e.$$typeof){case c:case p:case b:case h:case l:return e;default:return t}}case r:return t}}}function x(e){return k(e)===u}t.AsyncMode=d,t.ConcurrentMode=u,t.ContextConsumer=c,t.ContextProvider=l,t.Element=o,t.ForwardRef=p,t.Fragment=i,t.Lazy=b,t.Memo=h,t.Portal=r,t.Profiler=a,t.StrictMode=s,t.Suspense=f,t.isAsyncMode=function(e){return x(e)||k(e)===d},t.isConcurrentMode=x,t.isContextConsumer=function(e){return k(e)===c},t.isContextProvider=function(e){return k(e)===l},t.isElement=function(e){return"object"==typeof e&&null!==e&&e.$$typeof===o},t.isForwardRef=function(e){return k(e)===p},t.isFragment=function(e){return k(e)===i},t.isLazy=function(e){return k(e)===b},t.isMemo=function(e){return k(e)===h},t.isPortal=function(e){return k(e)===r},t.isProfiler=function(e){return k(e)===a},t.isStrictMode=function(e){return k(e)===s},t.isSuspense=function(e){return k(e)===f},t.isValidElementType=function(e){return"string"==typeof e||"function"==typeof e||e===i||e===u||e===a||e===s||e===f||e===m||"object"==typeof e&&null!==e&&(e.$$typeof===b||e.$$typeof===h||e.$$typeof===l||e.$$typeof===c||e.$$typeof===p||e.$$typeof===v||e.$$typeof===y||e.$$typeof===w||e.$$typeof===g)},t.typeOf=k},4363:(e,t,n)=>{"use strict";e.exports=n(2799)},3259:(e,t,n)=>{"use strict";function o(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function r(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function s(){return s=Object.assign||function(e){for(var t=1;t {"use strict";n.d(t,{u:()=>s,v:()=>a});var o=n(6347),r=n(8168),i=n(6540);function s(e,t,n){return void 0===n&&(n=[]),e.some((function(e){var r=e.path?(0,o.B6)(t,e):n.length?n[n.length-1].match:o.Ix.computeRootMatch(t);return r&&(n.push({route:e,match:r}),e.routes&&s(e.routes,t,n)),r})),n}function a(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),e?i.createElement(o.dO,n,e.map((function(e,n){return i.createElement(o.qh,{key:e.key||n,path:e.path,exact:e.exact,strict:e.strict,render:function(n){return e.render?e.render((0,r.A)({},n,{},t,{route:e})):i.createElement(e.component,(0,r.A)({},n,t,{route:e}))}})}))):null}},4625:(e,t,n)=>{"use strict";n.d(t,{I9:()=>u,Kd:()=>d,N_:()=>g,k2:()=>w});var o=n(6347),r=n(2892),i=n(6540),s=n(1513),a=n(8168),l=n(8587),c=n(1561),d=function(e){function t(){for(var t,n=arguments.length,o=new Array(n),r=0;r {"use strict";n.d(t,{B6:()=>_,Ix:()=>y,W6:()=>O,XZ:()=>v,dO:()=>R,qh:()=>S,zy:()=>P});var o=n(2892),r=n(6540),i=n(5556),s=n.n(i),a=n(1513),l=n(1561),c=n(8168),d=n(8505),u=n.n(d),p=(n(4363),n(8587)),f=(n(4146),1073741823),m="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:void 0!==n.g?n.g:{};var h=r.createContext||function(e,t){var n,i,a="__create-react-context-"+function(){var e="__global_unique_id__";return m[e]=(m[e]||0)+1}()+"__",l=function(e){function n(){for(var t,n,o,r=arguments.length,i=new Array(r),s=0;s {var o=n(4634);e.exports=f,e.exports.parse=i,e.exports.compile=function(e,t){return a(i(e,t),t)},e.exports.tokensToFunction=a,e.exports.tokensToRegExp=p;var r=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function i(e,t){for(var n,o=[],i=0,s=0,a="",d=t&&t.delimiter||"/";null!=(n=r.exec(e));){var u=n[0],p=n[1],f=n.index;if(a+=e.slice(s,f),s=f+u.length,p)a+=p[1];else{var m=e[s],h=n[2],b=n[3],g=n[4],v=n[5],y=n[6],w=n[7];a&&(o.push(a),a="");var k=null!=h&&null!=m&&m!==h,x="+"===y||"*"===y,_="?"===y||"*"===y,S=n[2]||d,A=g||v;o.push({name:b||i++,prefix:h||"",delimiter:S,optional:_,repeat:x,partial:k,asterisk:!!w,pattern:A?c(A):w?".*":"[^"+l(S)+"]+?"})}}return s {"use strict";var o=n(6540),r=Symbol.for("react.element"),i=Symbol.for("react.fragment"),s=Object.prototype.hasOwnProperty,a=o.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,l={key:!0,ref:!0,__self:!0,__source:!0};function c(e,t,n){var o,i={},c=null,d=null;for(o in void 0!==n&&(c=""+n),void 0!==t.key&&(c=""+t.key),void 0!==t.ref&&(d=t.ref),t)s.call(t,o)&&!l.hasOwnProperty(o)&&(i[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps)void 0===i[o]&&(i[o]=t[o]);return{$$typeof:r,type:e,key:c,ref:d,props:i,_owner:a.current}}t.Fragment=i,t.jsx=c,t.jsxs=c},5287:(e,t)=>{"use strict";var n=Symbol.for("react.element"),o=Symbol.for("react.portal"),r=Symbol.for("react.fragment"),i=Symbol.for("react.strict_mode"),s=Symbol.for("react.profiler"),a=Symbol.for("react.provider"),l=Symbol.for("react.context"),c=Symbol.for("react.forward_ref"),d=Symbol.for("react.suspense"),u=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),f=Symbol.iterator;var m={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},h=Object.assign,b={};function g(e,t,n){this.props=e,this.context=t,this.refs=b,this.updater=n||m}function v(){}function y(e,t,n){this.props=e,this.context=t,this.refs=b,this.updater=n||m}g.prototype.isReactComponent={},g.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},g.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},v.prototype=g.prototype;var w=y.prototype=new v;w.constructor=y,h(w,g.prototype),w.isPureReactComponent=!0;var k=Array.isArray,x=Object.prototype.hasOwnProperty,_={current:null},S={key:!0,ref:!0,__self:!0,__source:!0};function A(e,t,o){var r,i={},s=null,a=null;if(null!=t)for(r in void 0!==t.ref&&(a=t.ref),void 0!==t.key&&(s=""+t.key),t)x.call(t,r)&&!S.hasOwnProperty(r)&&(i[r]=t[r]);var l=arguments.length-2;if(1===l)i.children=o;else if(1 {"use strict";e.exports=n(5287)},4848:(e,t,n)=>{"use strict";e.exports=n(1020)},7463:(e,t)=>{"use strict";function n(e,t){var n=e.length;e.push(t);e:for(;0 >>1,r=e[o];if(!(0>>1;o i(l,n))ci(d,l)?(e[o]=d,e[c]=n,o=c):(e[o]=l,e[a]=n,o=a);else{if(!(c i(d,n)))break e;e[o]=d,e[c]=n,o=c}}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}if("object"==typeof performance&&"function"==typeof performance.now){var s=performance;t.unstable_now=function(){return s.now()}}else{var a=Date,l=a.now();t.unstable_now=function(){return a.now()-l}}var c=[],d=[],u=1,p=null,f=3,m=!1,h=!1,b=!1,g="function"==typeof setTimeout?setTimeout:null,v="function"==typeof clearTimeout?clearTimeout:null,y="undefined"!=typeof setImmediate?setImmediate:null;function w(e){for(var t=o(d);null!==t;){if(null===t.callback)r(d);else{if(!(t.startTime<=e))break;r(d),t.sortIndex=t.expirationTime,n(c,t)}t=o(d)}}function k(e){if(b=!1,w(e),!h)if(null!==o(c))h=!0,P(x);else{var t=o(d);null!==t&&N(k,t.startTime-e)}}function x(e,n){h=!1,b&&(b=!1,v(C),C=-1),m=!0;var i=f;try{for(w(n),p=o(c);null!==p&&(!(p.expirationTime>n)||e&&!T());){var s=p.callback;if("function"==typeof s){p.callback=null,f=p.priorityLevel;var a=s(p.expirationTime<=n);n=t.unstable_now(),"function"==typeof a?p.callback=a:p===o(c)&&r(c),w(n)}else r(c);p=o(c)}if(null!==p)var l=!0;else{var u=o(d);null!==u&&N(k,u.startTime-n),l=!1}return l}finally{p=null,f=i,m=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var _,S=!1,A=null,C=-1,E=5,D=-1;function T(){return!(t.unstable_now()-D e||125 s?(e.sortIndex=i,n(d,e),null===o(c)&&e===o(d)&&(b?(v(C),C=-1):b=!0,N(k,i-s))):(e.sortIndex=a,n(c,e),h||m||(h=!0,P(x))),e},t.unstable_shouldYield=T,t.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}},9982:(e,t,n)=>{"use strict";e.exports=n(7463)},2833:e=>{e.exports=function(e,t,n,o){var r=n?n.call(o,e,t):void 0;if(void 0!==r)return!!r;if(e===t)return!0;if("object"!=typeof e||!e||"object"!=typeof t||!t)return!1;var i=Object.keys(e),s=Object.keys(t);if(i.length!==s.length)return!1;for(var a=Object.prototype.hasOwnProperty.bind(t),l=0;l {"use strict";n.r(t),n.d(t,{default:()=>o});const o={title:"Misti",tagline:"TON Static Analyzer",favicon:"img/misti.svg",url:"https://nowarp.io",baseUrl:"/",organizationName:"nowarp",projectName:"misti",onBrokenLinks:"warn",onBrokenMarkdownLinks:"throw",i18n:{defaultLocale:"en",locales:["en"],path:"i18n",localeConfigs:{}},presets:[["classic",{docs:{sidebarPath:"./sidebars.ts",routeBasePath:"tools/misti/docs",editUrl:"https://github.com/nowarp/nowarp.github.io/tree/master/"},theme:{customCss:"./src/css/custom.css"}}]],plugins:[["@docusaurus/plugin-google-gtag",{trackingID:"G-8VLF6VGHH5",anonymizeIP:!0}]],themeConfig:{navbar:{title:"Misti",logo:{alt:"Misti Logo",src:"img/misti.svg"},items:[{type:"docsVersionDropdown",position:"right",dropdownItemsBefore:[],dropdownItemsAfter:[]},{label:"API Reference",position:"right",items:[{label:"Misti",to:"/tools/misti/api",target:"_blank",rel:"noopener noreferrer"},{label:"Souffle.js",to:"/lib/souffle-js/api",target:"_blank",rel:"noopener noreferrer"}]}],hideOnScroll:!1},footer:{style:"dark",links:[{title:"Community",items:[{label:"Telegram",href:"https://t.me/misti_dev"},{label:"GitHub",href:"https://github.com/nowarp/misti"}]},{title:"Developers",items:[{label:"API Reference",href:"https://nowarp.io/tools/misti/api/"},{label:"Changelog",href:"https://github.com/nowarp/misti/blob/master/CHANGELOG.md"},{label:"Roadmap",href:"https://github.com/nowarp/misti/milestones"}]}],copyright:'\n \n Supported by TF\n \n\n '},prism:{theme:{plain:{color:"#393A34",backgroundColor:"#f6f8fa"},styles:[{types:["comment","prolog","doctype","cdata"],style:{color:"#999988",fontStyle:"italic"}},{types:["namespace"],style:{opacity:.7}},{types:["string","attr-value"],style:{color:"#e3116c"}},{types:["punctuation","operator"],style:{color:"#393A34"}},{types:["entity","url","symbol","number","boolean","variable","constant","property","regex","inserted"],style:{color:"#36acaa"}},{types:["atrule","keyword","attr-name","selector"],style:{color:"#00a4db"}},{types:["function","deleted","tag"],style:{color:"#d73a49"}},{types:["function-variable"],style:{color:"#6f42c1"}},{types:["tag","selector","keyword"],style:{color:"#00009f"}}]},darkTheme:{plain:{backgroundColor:"hsl(220, 13%, 18%)",color:"hsl(220, 14%, 71%)",textShadow:"0 1px rgba(0, 0, 0, 0.3)"},styles:[{types:["comment","prolog","cdata"],style:{color:"hsl(220, 10%, 40%)"}},{types:["doctype","punctuation","entity"],style:{color:"hsl(220, 14%, 71%)"}},{types:["attr-name","class-name","maybe-class-name","boolean","constant","number","atrule"],style:{color:"hsl(29, 54%, 61%)"}},{types:["keyword"],style:{color:"hsl(286, 60%, 67%)"}},{types:["property","tag","symbol","deleted","important"],style:{color:"hsl(355, 65%, 65%)"}},{types:["selector","string","char","builtin","inserted","regex","attr-value"],style:{color:"hsl(95, 38%, 62%)"}},{types:["variable","operator","function"],style:{color:"hsl(207, 82%, 66%)"}},{types:["url"],style:{color:"hsl(187, 47%, 55%)"}},{types:["deleted"],style:{textDecorationLine:"line-through"}},{types:["inserted"],style:{textDecorationLine:"underline"}},{types:["italic"],style:{fontStyle:"italic"}},{types:["important","bold"],style:{fontWeight:"bold"}},{types:["important"],style:{color:"hsl(220, 14%, 71%)"}}]},additionalLanguages:[],magicComments:[{className:"theme-code-block-highlighted-line",line:"highlight-next-line",block:{start:"highlight-start",end:"highlight-end"}}]},colorMode:{defaultMode:"light",disableSwitch:!1,respectPrefersColorScheme:!1},docs:{versionPersistence:"localStorage",sidebar:{hideable:!1,autoCollapseCategories:!1}},metadata:[],tableOfContents:{minHeadingLevel:2,maxHeadingLevel:3}},baseUrlIssueBanner:!0,future:{experimental_storage:{type:"localStorage",namespace:!1},experimental_router:"browser"},onBrokenAnchors:"warn",onDuplicateRoutes:"warn",staticDirectories:["static"],customFields:{},themes:[],scripts:[],headTags:[],stylesheets:[],clientModules:[],titleDelimiter:"|",noIndex:!1,markdown:{format:"mdx",mermaid:!1,mdx1Compat:{comments:!0,admonitions:!0,headingIds:!0},anchors:{maintainCase:!1}}}},8168:(e,t,n)=>{"use strict";function o(){return o=Object.assign?Object.assign.bind():function(e){for(var t=1;to})},2892:(e,t,n)=>{"use strict";function o(e,t){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},o(e,t)}function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,o(e,t)}n.d(t,{A:()=>r})},8587:(e,t,n)=>{"use strict";function o(e,t){if(null==e)return{};var n={};for(var o in e)if({}.hasOwnProperty.call(e,o)){if(t.includes(o))continue;n[o]=e[o]}return n}n.d(t,{A:()=>o})},4164:(e,t,n)=>{"use strict";function o(e){var t,n,r="";if("string"==typeof e||"number"==typeof e)r+=e;else if("object"==typeof e)if(Array.isArray(e)){var i=e.length;for(t=0;tr});const r=function(){for(var e,t,n=0,r="",i=arguments.length;n{"use strict";n.d(t,{My:()=>E,f4:()=>ee});var o,r,i,s,a,l,c,d=n(6540),u=n(4164),p=Object.create,f=Object.defineProperty,m=Object.defineProperties,h=Object.getOwnPropertyDescriptor,b=Object.getOwnPropertyDescriptors,g=Object.getOwnPropertyNames,v=Object.getOwnPropertySymbols,y=Object.getPrototypeOf,w=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable,x=(e,t,n)=>t in e?f(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,_=(e,t)=>{for(var n in t||(t={}))w.call(t,n)&&x(e,n,t[n]);if(v)for(var n of v(t))k.call(t,n)&&x(e,n,t[n]);return e},S=(e,t)=>m(e,b(t)),A=(e,t)=>{var n={};for(var o in e)w.call(e,o)&&t.indexOf(o)<0&&(n[o]=e[o]);if(null!=e&&v)for(var o of v(e))t.indexOf(o)<0&&k.call(e,o)&&(n[o]=e[o]);return n},C=(o={"../../node_modules/.pnpm/prismjs@1.29.0_patch_hash=vrxx3pzkik6jpmgpayxfjunetu/node_modules/prismjs/prism.js"(e,t){var n=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},o={util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=u.reach);_+=x.value.length,x=x.next){var S=x.value;if(t.length>e.length)return;if(!(S instanceof r)){var A,C=1;if(v){if(!(A=i(k,_,e,g))||A.index>=e.length)break;var E=A.index,D=A.index+A[0].length,T=_;for(T+=x.value.length;E>=T;)T+=(x=x.next).value.length;if(_=T-=x.value.length,x.value instanceof r)continue;for(var R=x;R!==t.tail&&(T u.reach&&(u.reach=N);var I=x.prev;if(O&&(I=l(t,I,O),_+=O.length),c(t,I,C),x=l(t,I,new r(p,b?o.tokenize(L,b):L,y,L)),P&&l(t,x,P),C>1){var j={cause:p+","+m,reach:N};s(e,t,n,x.prev,_,j),u&&j.reach>u.reach&&(u.reach=j.reach)}}}}}}function a(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var o=t.next,r={value:n,prev:t,next:o};return t.next=r,o.prev=r,e.length++,r}function c(e,t,n){for(var o=t.next,r=0;r "+i.content+""+i.tag+">"},o}();t.exports=n,n.default=n}},function(){return r||(0,o[g(o)[0]])((r={exports:{}}).exports,r),r.exports}),E=((e,t,n)=>(n=null!=e?p(y(e)):{},((e,t,n,o)=>{if(t&&"object"==typeof t||"function"==typeof t)for(let r of g(t))w.call(e,r)||r===n||f(e,r,{get:()=>t[r],enumerable:!(o=h(t,r))||o.enumerable});return e})(!t&&e&&e.__esModule?n:f(n,"default",{value:e,enumerable:!0}),e)))(C());E.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},{pattern:/^(\s*)["']|["']$/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/?[\da-f]{1,8};/i]},E.languages.markup.tag.inside["attr-value"].inside.entity=E.languages.markup.entity,E.languages.markup.doctype.inside["internal-subset"].inside=E.languages.markup,E.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(E.languages.markup.tag,"addInlined",{value:function(e,t){var n;(t=((n=((n={})["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:E.languages[t]},n.cdata=/^$/i,{"included-cdata":{pattern://i,inside:n}}))["language-"+t]={pattern:/[\s\S]+/,inside:E.languages[t]},{}))[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:n},E.languages.insertBefore("markup","cdata",t)}}),Object.defineProperty(E.languages.markup.tag,"addAttribute",{value:function(e,t){E.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:E.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),E.languages.html=E.languages.markup,E.languages.mathml=E.languages.markup,E.languages.svg=E.languages.markup,E.languages.xml=E.languages.extend("markup",{}),E.languages.ssml=E.languages.xml,E.languages.atom=E.languages.xml,E.languages.rss=E.languages.xml,i=E,s={pattern:/\\[\\(){}[\]^$+*?|.]/,alias:"escape"},l="(?:[^\\\\-]|"+(a=/\\(?:x[\da-fA-F]{2}|u[\da-fA-F]{4}|u\{[\da-fA-F]+\}|0[0-7]{0,2}|[123][0-7]{2}|c[a-zA-Z]|.)/).source+")",l=RegExp(l+"-"+l),c={pattern:/(<|')[^<>']+(?=[>']$)/,lookbehind:!0,alias:"variable"},i.languages.regex={"char-class":{pattern:/((?:^|[^\\])(?:\\\\)*)\[(?:[^\\\]]|\\[\s\S])*\]/,lookbehind:!0,inside:{"char-class-negation":{pattern:/(^\[)\^/,lookbehind:!0,alias:"operator"},"char-class-punctuation":{pattern:/^\[|\]$/,alias:"punctuation"},range:{pattern:l,inside:{escape:a,"range-punctuation":{pattern:/-/,alias:"operator"}}},"special-escape":s,"char-set":{pattern:/\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},escape:a}},"special-escape":s,"char-set":{pattern:/\.|\\[wsd]|\\p\{[^{}]+\}/i,alias:"class-name"},backreference:[{pattern:/\\(?![123][0-7]{2})[1-9]/,alias:"keyword"},{pattern:/\\k<[^<>']+>/,alias:"keyword",inside:{"group-name":c}}],anchor:{pattern:/[$^]|\\[ABbGZz]/,alias:"function"},escape:a,group:[{pattern:/\((?:\?(?:<[^<>']+>|'[^<>']+'|[>:]|[=!]|[idmnsuxU]+(?:-[idmnsuxU]+)?:?))?/,alias:"punctuation",inside:{"group-name":c}},{pattern:/\)/,alias:"punctuation"}],quantifier:{pattern:/(?:[+*?]|\{\d+(?:,\d*)?\})[?+]?/,alias:"number"},alternation:{pattern:/\|/,alias:"keyword"}},E.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},E.languages.javascript=E.languages.extend("clike",{"class-name":[E.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),E.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,E.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:E.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:E.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:E.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:E.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:E.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),E.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:E.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),E.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),E.languages.markup&&(E.languages.markup.tag.addInlined("script","javascript"),E.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),E.languages.js=E.languages.javascript,E.languages.actionscript=E.languages.extend("javascript",{keyword:/\b(?:as|break|case|catch|class|const|default|delete|do|dynamic|each|else|extends|final|finally|for|function|get|if|implements|import|in|include|instanceof|interface|internal|is|namespace|native|new|null|override|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|use|var|void|while|with)\b/,operator:/\+\+|--|(?:[+\-*\/%^]|&&?|\|\|?|<|>>?>?|[!=]=?)=?|[~?@]/}),E.languages.actionscript["class-name"].alias="function",delete E.languages.actionscript.parameter,delete E.languages.actionscript["literal-property"],E.languages.markup&&E.languages.insertBefore("actionscript","string",{xml:{pattern:/(^|[^.])<\/?\w+(?:\s+[^\s>\/=]+=("|')(?:\\[\s\S]|(?!\2)[^\\])*\2)*\s*\/?>/,lookbehind:!0,inside:E.languages.markup}}),function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(E),function(e){var t=e.languages.javadoclike={parameter:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*@(?:arg|arguments|param)\s+)\w+/m,lookbehind:!0},keyword:{pattern:/(^[\t ]*(?:\/{3}|\*|\/\*\*)\s*|\{)@[a-z][a-zA-Z-]+\b/m,lookbehind:!0},punctuation:/[{}]/};Object.defineProperty(t,"addSupport",{value:function(t,n){(t="string"==typeof t?[t]:t).forEach((function(t){var o=function(e){e.inside||(e.inside={}),e.inside.rest=n},r="doc-comment";if(i=e.languages[t]){var i,s=i[r];if((s=s||(i=e.languages.insertBefore(t,"comment",{"doc-comment":{pattern:/(^|[^\\])\/\*\*[^/][\s\S]*?(?:\*\/|$)/,lookbehind:!0,alias:"comment"}}))[r])instanceof RegExp&&(s=i[r]={pattern:s}),Array.isArray(s))for(var a=0,l=s.length;a |\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}}),{pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0}),{pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0});e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|RebeccaPurple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,number:n})}(E),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,o="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",r=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-] )(?:[ \t]*(?:(?![#:]) |: ))*/.source.replace(/ /g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),i=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function s(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s< >[ \t]+)?)(?:< >)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/< >/g,(function(){return o})).replace(/< >/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s< >[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/< >/g,(function(){return o}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:< >[ \t]+)?)< >(?=\s*:\s)/.source.replace(/< >/g,(function(){return o})).replace(/< >/g,(function(){return"(?:"+r+"|"+i+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:s(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:s(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:s(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:s(i),lookbehind:!0,greedy:!0},number:{pattern:s(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(E),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(/ /g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var o=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,r=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return o})),i=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source,s=(e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+r+i+"(?:"+r+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+r+i+")(?:"+r+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(o),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+r+")"+i+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+r+"$"),inside:{"table-header":{pattern:RegExp(o),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_) |_(?:(?!_) )+_)+__\b|\*\*(?:(?!\*) |\*(?:(?!\*) )+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_) |__(?:(?!_) )+__)+_\b|\*(?:(?!\*) |\*\*(?:(?!\*) )+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~) )+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\]) )+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]) )+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,o=t.length;n ",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(E),E.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:E.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},E.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n ?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,o=t.inside.interpolation,r=o.inside["interpolation-punctuation"],i=o.pattern.source;function s(t,o){if(e.languages[t])return{pattern:RegExp("((?:"+o+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function a(t,n,o){return t={code:t,grammar:n,language:o},e.hooks.run("before-tokenize",t),t.tokens=e.tokenize(t.code,t.grammar),e.hooks.run("after-tokenize",t),t.tokens}function l(t,n,s){var l=e.tokenize(t,{interpolation:{pattern:RegExp(i),lookbehind:!0}}),c=0,d={},u=(l=a(l.map((function(e){if("string"==typeof e)return e;var n,o;for(e=e.content;-1!==t.indexOf((o=c++,n="___"+s.toUpperCase()+"_"+o+"___")););return d[n]=e,n})).join(""),n,s),Object.keys(d));return c=0,function t(n){for(var i=0;i =u.length)return;var s,l,p,f,m,h,b,g=n[i];"string"==typeof g||"string"==typeof g.content?(s=u[c],-1!==(b=(h="string"==typeof g?g:g.content).indexOf(s))&&(++c,l=h.substring(0,b),m=d[s],p=void 0,(f={})["interpolation-punctuation"]=r,3===(f=e.tokenize(m,f)).length&&((p=[1,1]).push.apply(p,a(f[1],e.languages.javascript,"javascript")),f.splice.apply(f,p)),p=new e.Token("interpolation",f,o.alias,m),f=h.substring(b+s.length),m=[],l&&m.push(l),m.push(p),f&&(t(h=[f]),m.push.apply(m,h)),"string"==typeof g?(n.splice.apply(n,[i,1].concat(m)),i+=m.length-1):g.content=m)):(b=g.content,Array.isArray(b)?t(b):t([b]))}}(l),new e.Token(s,l,"language-"+s,t)}e.languages.javascript["template-string"]=[s("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),s("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),s("svg",/\bsvg/.source),s("markdown",/\b(?:markdown|md)/.source),s("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),s("sql",/\bsql/.source),t].filter(Boolean);var c={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function d(e){return"string"==typeof e?e:Array.isArray(e)?e.map(d).join(""):d(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in c&&function t(n){for(var o=0,r=n.length;o