Truth Markets V2 Smart Contract Audit

<style>
@import url(https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap);@import url('https://fonts.googleapis.com/css2?family=Source Code Pro:wght@400;500;600;700&display=swap');ul{opacity:1;}table{border:none !important;}a,code,pre,tt{overflow-wrap:break-word;word-wrap:break-word}.chroma .lntable,.chroma .lntd{margin:0;border:0;padding:0}pre,table{width:100%}.findings-count td,.findings-count th,.rating-critical,.rating-high,.rating-informational,.rating-low,.rating-medium,.status-closed,.status-open,.status-resolved{text-align:center}.rating-critical,.rating-high,.rating-informational,.rating-low,.rating-medium,.status-closed,.status-open,.status-resolved,a,h1,h2,h3{font-weight:500}:root{--color-link:#f66263;--color-heading:#f66263;--color-codeblock:#f5f2f0;--color-codeblock-border:#f5f2f0;--color-critical:#cc7ab9;--color-high:#ff6263;--color-medium:#f68463;--color-low:#f6b263;--color-informational:#6ba2f6;--color-open:#f6d263;--color-closed:#b6b6b6;--color-resolved:#9fbf9f;--size-200:0.694rem;--size-300:0.833rem;--size-400:1rem;--size-500:1.2rem;--size-600:1.44rem;--size-700:1.728rem;--size-800:2.074rem;--size-900:2.488rem}.report-container{color:#222;font-family:Montserrat,sans-serif;line-height:1.6;margin:1rem;font-size:var(--size-400)}a{color:var(--color-link)}@media screen and (min-width:1600px){.report-main{display:grid;grid-gap:1em}.toc{grid-column:1;max-width:30em}.frontpage-logo,.frontpage-subtitle,.frontpage-title,.report{grid-column:2}}@media screen and (max-width:1599px){ .report-main{ margin: 0 auto;max-width:70em} }h1,h2,h3,h4,h5,h6{margin-bottom:0}.toc>ul>li>a,dt,h4,h5,h6,table th{font-weight:600}h1,h2{color:var(--color-heading)}h3,h4,h5,h6{color:#444 !important}h1{font-size:var(--size-800)}h2{font-size:var(--size-700)}h3{font-size:var(--size-600) } .audit-text-formatting .report-main h3{font-size:var(--size-600) }h4{font-size:var(--size-500)}h1 strong,h2 strong,h3 strong,h4 strong{font-weight:400;font-size:.7em;font-family:"Source Code Pro",monospace}h2 strong::after{content:"\a";white-space:pre}code,pre,tt{font-family:"Source Code Pro",monospace,sans-serif;background-color:var(--color-codeblock);white-space:pre-wrap}code,tt{padding:1px 3px;border-radius:2px}pre{box-sizing:border-box;padding:10px;overflow:auto;word-break:break-all}pre code,tt{font-size:inherit;background:0 0;border:none;padding:0}.findings code,h2 code{background-color:inherit;border-width:0}@media screen and (min-width:600px){dl{display:grid;grid-gap:0.5em}dt{grid-column:1}dd{grid-column:2}}@media screen and (max-width:599px){dl{display:block}}table{background-color:inherit;max-width:100%;min-width:100%;border:none;font-size:.9em}table thead th{border-bottom:2px solid #222}table td,table th{text-align:left;border:none}table,td,th{border-collapse:collapse}.findings-count thead tr th:first-of-type{border-style:none}.findings-count tbody td:first-child{text-align:right;width:6em;padding-right:.75em;border-right:2px solid #222;font-weight:600}.findings-count td:nth-child(2),.rating-critical{background-color:var(--color-critical)}.findings-count td:nth-child(3),.rating-high{background-color:var(--color-high)}.findings-count td:nth-child(4),.rating-medium{background-color:var(--color-medium)}.findings-count td:nth-child(5),.rating-low{background-color:var(--color-low)}.findings-count td:nth-child(6),.rating-informational{background-color:var(--color-informational)}.status-open{background-color:var(--color-open)}.status-closed{background-color:var(--color-closed)}.status-resolved{background-color:var(--color-resolved)}.findings td:first-of-type{white-space:nowrap;word-break:keep-all;font-family:"Source Code Pro",monospace;vertical-align:top}.findings td:nth-of-type(2){vertical-align:bottom}@media screen{.audit-header,.report{max-width:65rem}h1{margin-top:3em}h2{margin-top:2em}table th{padding:6px}table td{padding:8px 6px}.findings td:nth-of-type(2){min-width:2em}}.metadata td:last-of-type{background-color:#eee}.metadata td:first-of-type,.metadata td:nth-of-type(2){width:8em}.toc ul{list-style:none;margin-left:0;padding-left:0}.toc li ul{margin-left:3em}.toc{counter-reset:tocSectionCounter}.toc>ul>li::before{content:counter(tocSectionCounter) ". ";font-weight:600;padding-right:4px}.toc>ul>li{counter-increment:tocSectionCounter}.report{counter-reset:sectionCounter}.report h1::before{content:counter(sectionCounter) ". ";font-weight:400;padding-right:6px}.report h1{counter-increment:sectionCounter}hr{display:none}@media print{.landing-header{display:none}.toc li a,h1,h2{color:#222}dd,dt{margin:.2em 0;break-inside:avoid}dl,pre{page-break-inside:auto;break-inside:auto}dd,dt,pre{padding:0}.toc li a,.toc li a::after,pre{background-color:#fff}td{min-width:2em}pre,td{word-break:break-word}h1,h2{margin-top:0}#document-control,.break-before,h1,hr{page-break-before:always}h1{font-size:18pt}h2{font-size:16pt}h3{font-size:14pt}.frontpage-subtitle,h4{font-size:12pt}.toc,p,ul,ol,dl{font-size:11pt}summary{list-style:none;font-size:1.1em;margin-bottom:1em}.toc{background:0 0;max-width:100%;counter-reset:page;line-height:1.6}.toc li a::after{content:target-counter(attr(href),page);float:right;position:absolute;right:0;padding-left:3px}.toc li ul{margin-left:1.5em}.toc li{overflow-x:hidden;max-width:98.5%;text-align:left}.toc li ul li::after{content:".............................................." ".............................................." ".............................................." "........";float:left;width:0;letter-spacing:6px}footer,header{display:none}dd,li,p,p *{text-align:justify}dl{width:100%;display:flex;flex-wrap:wrap}dt{flex:1;min-width:30%}dd{flex:1;min-width:65%}.frontpage-logo{margin-top:75mm;width:65mm;padding-bottom:1cm}.report-container{height:auto}pre{display:inline;font-size:.9em}pre:first-child,pre:last-child{padding:0;margin:0;background-color:#fff}pre *{white-space:pre-wrap;background-color:var(--color-codeblock);padding:1px;word-wrap:normal}.findings td{max-width:20em;overflow-wrap:break-word;text-wrap:balance}.frontpage-title{font-size:20pt;font-weight:700}.frontpage-subtitle{page-break-after:always;}.metadata td{padding:.3em}td{padding:4px}}.page-header{margin-top:-1cm;opacity:.8;position:running(pageHeaderRunning)}.page-header svg{width:34mm}@media screen{.page-header,.frontpage-subtitle,.frontpage-title,.frontpage-logo{display:none}.frontpage-subtitle,.frontpage-title{text-align:center}.frontpage-logo{width:10em;padding-bottom:.5em;margin-left:auto;margin-right:auto}.frontpage-title{font-size:var(--size-900);font-weight:700}.frontpage-subtitle{font-size:var(--size-500)}}@page{size:A4;margin:2cm 1.6cm;bleed:6mm}@page{@bottom-center{content:"𝗣𝗨𝗕𝗟𝗜𝗖 \A hello@iosiro.com";white-space:pre;color:#b7b7b7;font-size:9pt;font-family:Montserrat,sans-serif}@bottom-right-corner{content:counter(page);font-size:9pt}@top-center{content:element(pageHeaderRunning)}}@page:first{text-align:center;@top-center{content:none}@bottom-right-corner{content:none}}.chroma .lnlinks,a{text-decoration:none}.chroma .lntd,.codequality td{vertical-align:top;font-size:.9em}.chroma .ge,.chroma .sd{font-style:italic}.chroma .gh,.chroma .gp,.chroma .gs,.chroma .gu,.chroma .nc,.chroma .nd,.chroma .ni,.chroma .nl,.chroma .nn,.chroma .nt,.chroma .se,summary{font-weight:700}.bg,.chroma{background-color:var(--color-codeblock)}.chroma .lnlinks{outline:0;color:inherit}.chroma .lntable{border-spacing:0}.chroma .hl{background-color:#d8d8d8}.chroma .ln,.chroma .lnt{white-space:pre;-webkit-user-select:none;user-select:none;margin-right:.4em;padding:0 .4em;color:#7f7f7f}.chroma .line{display:flex}.chroma .k,.chroma .kc,.chroma .kd,.chroma .kn,.chroma .kr,.chroma .ow{color:#007020;font-weight:700}.chroma .cp,.chroma .cpf,.chroma .kp,.chroma .nb,.chroma .ne{color:#007020}.chroma .kt{color:#902000}.chroma .dl,.chroma .na,.chroma .s,.chroma .s1,.chroma .s2,.chroma .sa,.chroma .sb,.chroma .sc,.chroma .sd,.chroma .se,.chroma .sh{color:#4070a0}.chroma .nc,.chroma .nn{color:#0e84b5}.chroma .no{color:#60add5}.chroma .nd{color:#555}.chroma .ni{color:#d55537}.chroma .nf{color:#06287e}.chroma .nl{color:#002070}.chroma .nt{color:#062873}.chroma .nv{color:#bb60d5}.chroma .si{color:#70a0d0}.chroma .gp,.chroma .sx{color:#c65d09}.chroma .sr{color:#235388}.chroma .ss{color:#517918}.chroma .il,.chroma .m,.chroma .mb,.chroma .mf,.chroma .mh,.chroma .mi,.chroma .mo{color:#40a070}.chroma .o{color:#666}.chroma .c,.chroma .c1,.chroma .ch,.chroma .cm{color:#60a0b0;font-style:italic}.chroma .cs{color:#60a0b0;background-color:#fff0f0}.chroma .gd{color:#a00000}.chroma .gr{color:red}.chroma .gh{color:navy}.chroma .gi{color:#00a000}.chroma .go{color:#888}.chroma .gu{color:purple}.chroma .gt{color:#04d}.chroma .gl{text-decoration:underline}.chroma .w{color:#bbb}.container{max-width:100%}
</style>
<div class="report-container">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg" style="display:none;">
<defs>
<symbol id="iosiro-logo" viewBox="0 0 1233 312" preserveAspectRatio="xMidYMid meet">
<g fill="#061f45">
<path d="M171.5 300.6 c-3.9 -1.7 -9.5 -4.6 -12.5 -6.5 -5.1 -3.2 -21 -15 -21 -15.6 0 -0.2 6.1 -3.5 13.5 -7.4 7.4 -3.8 17.2 -9.6 21.8 -12.7 11.1 -7.7 24.4 -21.3 29 -29.5 8.2 -14.7 9.4 -21.4 11.2 -62 1.5 -36.7 3 -46.9 8.5 -62.1 10.1 -27.6 28.2 -43.3 68 -58.8 20.3 -8 31.8 -14.8 42.4 -25.2 l8.9 -8.8 -0.7 5.7 c-1.1 9.2 -4.7 15.7 -13.4 24.2 -9.3 9.1 -20.2 16 -49.9 31.5 -22.9 12 -27 14.8 -33.3 22.7 -8.4 10.6 -10.6 21.1 -12.5 59.2 -1.6 32.3 -2.4 39.8 -5.6 52.7 -7.4 29.9 -24.7 52.9 -51.2 68.2 l-7.7 4.4 6.4 3.6 6.4 3.5 7.9 -4.1 c4.3 -2.2 11.7 -6.7 16.5 -9.9 9.8 -6.6 30.5 -26 40.1 -37.5 8.9 -10.6 21.7 -30.5 28 -43.3 l5.2 -10.7 9.5 -4.5 c5.2 -2.5 9.6 -4.4 9.9 -4.2 1.6 1.7 -13.3 32.8 -22.4 46.7 -22.3 34 -54.5 62.6 -91.3 81.2 l-4.7 2.4 -7 -3.2z"></path>
<path d="M582.1 272 c-19.3 -4.1 -31.7 -11.4 -45.4 -26.8 -14.2 -16 -19.7 -31.4 -19.7 -55.5 0.1 -22.2 4.9 -36.2 17.4 -50.9 9.3 -10.9 16.1 -16.5 25.8 -21.4 14.5 -7.3 21.7 -8.9 39.8 -8.9 18.3 0 23.5 1.2 38.5 8.5 20.6 10 36.7 29.7 43.1 53 2.6 9.2 2.5 31.8 0 41.4 -7.3 27.2 -27.1 48.7 -53 57.3 -10.6 3.4 -11.8 3.6 -26.6 3.9 -8.5 0.2 -17.5 -0.1 -19.9 -0.6z m31 -31.4 c13.1 -2.8 21.4 -9.3 27.7 -21.3 5.1 -10 6.6 -16.5 6.5 -28.8 0 -22.7 -9.7 -39.6 -26.9 -46.9 -5.9 -2.5 -8.5 -3 -17.7 -3.4 -6.4 -0.3 -12.7 0.1 -15.5 0.8 -25.7 6.4 -40 33.3 -33.7 63.5 2.9 13.8 10.9 25.6 21.7 31.9 8.6 5 25.2 6.9 37.9 4.2z"></path>
<path d="M754 271.9 c-11.5 -3.2 -17.4 -6.4 -24.9 -13.9 -6.6 -6.6 -12.6 -14.9 -14.6 -20.1 -0.5 -1.4 2.3 -3.1 14.1 -8.8 8.1 -3.9 14.9 -7 15 -6.8 0.2 0.2 2.1 3 4.3 6.4 4.7 7.3 9 10.7 15.4 12.4 5.8 1.4 14.3 0.7 18.7 -1.6 6.2 -3.2 8.8 -14 5.1 -21.4 -3.4 -6.6 -9.5 -10.9 -28.6 -20.2 -21.5 -10.4 -27.5 -15.1 -32.7 -25.7 -3.1 -6.3 -3.3 -7.2 -3.3 -17.7 0.1 -9.1 0.5 -12 2.4 -16.8 5.3 -13.4 16.5 -23.3 31.5 -27.9 5.6 -1.7 8.6 -2 16.7 -1.6 8.9 0.4 10.7 0.9 17.4 4.2 8.9 4.4 17.2 12.1 20.9 19.4 1.4 2.8 2.6 5.6 2.6 6.1 0 0.9 -27.9 15.6 -28.4 14.9 -0.2 -0.2 -1.4 -2 -2.8 -4.1 -5.3 -7.9 -13.3 -11.2 -20.2 -8.3 -4 1.7 -7.6 6.8 -7.6 10.9 0 6.9 5.4 11.8 20.3 18.4 18 7.9 32.9 16.8 39.6 23.4 1.8 1.9 4.7 6.3 6.4 9.9 2.7 5.6 3.2 7.9 3.5 16.2 0.5 11.8 -1.7 20.3 -7.6 29.3 -7.6 11.7 -18.3 19.3 -32.2 23 -6.2 1.7 -25.4 1.9 -31 0.4z"></path>
<path d="M1118 271 c-17.1 -4.3 -27.7 -10.6 -40.6 -24.3 -5.2 -5.4 -8.2 -9.8 -12.2 -17.7 -6.9 -13.9 -8.4 -19.7 -8.9 -36 -0.6 -16.4 0.9 -24.3 6.6 -36.6 5.5 -11.7 11.7 -20 20.5 -27.7 9.2 -8.1 17.3 -12.6 29.6 -16.8 8 -2.7 11.4 -3.3 21.9 -3.7 17.7 -0.7 28.4 1.5 43.8 9 9.7 4.7 14.7 8.7 24 19.1 14.8 16.5 19.6 29.6 19.7 54.2 0 12.8 -0.3 16.2 -2.3 23.5 -3.4 12.4 -9.3 23 -18 32.2 -12.8 13.7 -23.3 19.9 -41 24.4 -12.1 3.1 -31.5 3.3 -43.1 0.4z m32.9 -30.1 c8.9 -1.6 14.3 -4.2 21.1 -10.5 10.4 -9.7 15.3 -22.3 15.3 -39.4 0 -22.3 -9.5 -39.2 -26.6 -47.1 -6.5 -3 -8.3 -3.3 -18.3 -3.7 -17 -0.7 -27.7 3.1 -37.1 13.1 -8.5 8.9 -13.3 22.2 -13.3 36.8 -0.1 36.5 23.6 56.8 58.9 50.8z"></path>
<path d="M116.7 259.8 c-21.5 -21.4 -40.1 -47.4 -49.3 -69 -1.9 -4.5 -3.3 -8.2 -3.2 -8.3 0.2 -0.2 6.4 1.9 13.8 4.6 39.7 14.5 52.8 20.7 56.3 26.6 2.3 4 2.4 9.6 0.2 14.8 l-1.8 4 -1.2 -4.8 c-1.6 -6.3 -7.9 -12.8 -16.1 -16.7 -5.8 -2.8 -22.3 -7.4 -23.2 -6.5 -0.8 0.7 20.8 30.1 29.1 39.6 l4.9 5.6 7.6 -4.1 c16.5 -8.9 28.7 -25.3 31.8 -42.6 3.5 -20.6 -2.9 -41.1 -18.1 -56.9 -12.9 -13.5 -24.5 -20.2 -49.7 -28.9 -17.7 -6.1 -23.4 -8.5 -31.3 -13.1 -20.4 -11.6 -34.4 -28.2 -39 -46.2 -2 -7.5 -2 -20.9 -0.2 -28.9 l1.3 -5.5 0.8 6.5 c2.4 21.7 11.4 39 26.7 51.6 9.4 7.7 18.7 12.1 44.4 20.9 58.6 20.2 75.6 34.1 85.1 69.2 3.7 13.8 4 33.3 0.6 44.1 -6.8 21.5 -25.1 39.9 -49.2 49.4 -11.5 4.6 -9.9 5 -20.3 -5.4z"></path>
<path d="M441 190.5 l0 -78.5 17.5 0 17.5 0 0 78.5 0 78.5 -17.5 0 -17.5 0 0 -78.5z"></path>
<path d="M858 190.5 l0 -78.5 18 0 18 0 0 78.5 0 78.5 -18 0 -18 0 0 -78.5z"></path>
<path d="M942 190.5 l0 -78.5 18 0 18 0 0 7.1 0 7.2 4.5 -4.2 c6.7 -6.2 15.9 -11.7 21.6 -13.1 8.5 -2.1 21 -0.8 29.9 2.9 4.1 1.7 8.1 3.5 8.8 4 1.1 0.6 -0.4 4.3 -6.3 16.2 -4.3 8.5 -7.9 15.6 -8.1 15.8 -0.2 0.2 -3.2 -0.9 -6.6 -2.5 -5.3 -2.4 -7.6 -2.9 -14.3 -2.9 -7 0 -8.7 0.4 -13.4 3 -6.6 3.7 -10.4 8.2 -13.3 16 -2.3 5.9 -2.3 6.9 -2.6 56.8 l-0.3 50.7 -17.9 0 -18 0 0 -78.5z"></path>
<path d="M145 191.5 c-7.1 -7.2 -17 -14 -29.8 -20.4 -10.1 -5.1 -33.5 -13.6 -44.2 -16.1 -13.5 -3.2 -32.8 -13.7 -42 -23 -6.9 -6.8 -13.5 -17.3 -16.6 -26.6 -2.3 -6.6 -2.7 -9.7 -2.8 -18.9 -0.1 -11.4 1.1 -23.2 2.2 -22 0.4 0.3 1.4 4.6 2.3 9.4 3.6 18.6 10.6 32 23.8 45.2 11.8 11.7 18.1 15.2 39.9 21.9 25.8 8 39.3 14.5 53.6 26.1 10 8 20.9 24.4 19.4 28.9 -0.2 0.6 -2.8 -1.5 -5.8 -4.5z"></path>
<path d="M240 182.6 c0 -2.9 4.2 -12.6 7.5 -17.1 7.7 -10.9 17.3 -18.4 40 -31.2 18.3 -10.3 23.6 -14.3 37.8 -28.2 l11.7 -11.6 0 3.5 c0 10 -5.7 21.6 -15.1 31.1 -7.3 7.4 -13.7 11.2 -32.1 19.3 -21.6 9.6 -32.7 16.6 -43 27.4 -3.8 3.8 -6.8 6.9 -6.8 6.8z"></path>
<path d="M244 145.8 c0 -3.2 4.3 -15.5 7.8 -22.2 4.1 -7.9 14.2 -18.7 22.2 -23.8 3 -2 11.6 -6.7 19 -10.7 16.7 -8.8 31.3 -19.6 44.9 -33.2 l10.4 -10.3 -0.6 4.2 c-3.3 20.1 -19.8 37.3 -50.7 52.7 -6.3 3.2 -14 7.5 -17.2 9.6 -5.9 4 -25.8 23.1 -32.2 30.8 -2.1 2.6 -3.6 3.8 -3.6 2.9z"></path>
<path d="M182.1 139.6 c-6.5 -8.4 -21.1 -21.9 -26.3 -24.3 -4.1 -2 -5 -3 -8.2 -9.6 -5 -10.4 -15.6 -21.6 -24.4 -25.9 -6.4 -3.1 -7.3 -3.3 -18.3 -3.3 -13.8 0 -15.9 1 -15.9 7.8 0 3.6 -0.2 3.8 -1.7 2.6 -3 -2.5 -7.3 -10.2 -7.3 -13.2 0 -9.4 12.7 -18.9 29.4 -21.8 5.5 -1 8.2 -2.1 12.1 -5.1 7.3 -5.6 13.7 -7.2 26.5 -6.6 13.4 0.7 20.2 3 46.3 15.4 22.9 11 24.1 11.5 28.5 12.3 l3.2 0.6 -3.6 5 c-9.8 13.7 -18.1 38.4 -19.6 58.5 -0.5 5.9 -2.8 -13.8 -2.8 -23.7 0 -9.8 1.9 -21.5 4.4 -27.5 0.9 -2.1 1.6 -4 1.6 -4.3 0 -0.2 -4.2 -2.4 -9.2 -4.8 -5.1 -2.4 -13.3 -7 -18.3 -10.1 -15.3 -9.7 -33.9 -13.8 -42 -9.4 l-3 1.6 5 0.7 c6.9 0.9 18.2 4.3 19.1 5.7 0.5 0.8 0.1 0.9 -1.1 0.4 -1.1 -0.4 -10.7 -1 -21.4 -1.3 -21 -0.6 -29.5 0.3 -32.5 3.6 -1.6 1.7 -1.3 1.8 5.3 2.5 13.2 1.2 28 7.2 39.8 16 11.7 8.9 21.8 21.8 30.1 38.7 4.1 8.5 9.7 23.8 8.9 24.5 -0.2 0.3 -2.3 -2 -4.6 -5z"></path>
<path d="M57.1 65.6 l-6.4 -6.4 2.9 -12.2 2.9 -12.3 11 -3.9 c56.8 -20.4 121.7 -24.1 184 -10.6 12 2.6 32.2 8.6 36.2 10.7 0.7 0.4 -3.1 2.5 -8.8 5 l-10 4.4 -7.4 -2.2 c-10.1 -2.9 -23.7 -5.6 -38.6 -7.7 -16.6 -2.4 -59.3 -2.4 -79.4 0 -26.3 3 -71.7 12.6 -73.4 15.5 -0.4 0.6 -1.8 6.8 -3.1 13.6 -1.3 6.9 -2.6 12.5 -3 12.5 -0.3 0 -3.4 -2.9 -6.9 -6.4z"></path>
<path d="M449.3 66.9 c-12.3 -6.1 -17 -20.9 -10.4 -32.4 5.2 -9 12.9 -12.5 24.6 -11 6.5 0.8 11.1 4.1 14.9 10.9 11 19 -9.7 42.1 -29.1 32.5z"></path>
<path d="M867.5 67.2 c-5 -2.3 -10.3 -7.6 -12.1 -11.9 -1.8 -4.3 -1.8 -15.2 0.1 -19.6 2.2 -5.4 9.8 -11.5 15.2 -12.3 6.4 -0.9 13.9 0.2 17.9 2.7 7.6 4.7 12.7 16.5 10.5 24.5 -1.5 5.4 -6.1 11.7 -11.2 15.1 -5.4 3.6 -14.5 4.3 -20.4 1.5z"></path>
</g>
</symbol>
</defs>
<use href="#iosiro-logo"></use>
</svg>
<div class="page-header" id="page-header">
<svg version="1.0">
<use href="#iosiro-logo"></use>
</svg>
</div>
<main class="report-main">
<svg version="1.0" class="frontpage-logo">
<use href="#iosiro-logo"></use>
</svg>
<div class="frontpage-title">True Markets V2 Smart Contract Audit</div>
<div class="frontpage-subtitle">True Markets, 07 March 2025</div>
<nav class="toc">
<h1>Contents</h1>
<ul>
<li>
<a href="#introduction">Introduction</a></li>
<li>
<a href="#disclaimer">Disclaimer</a></li>
<li>
<a href="#methodology">Methodology</a></li>
<li>
<a href="#audit-findings">Audit findings</a><ul>
<li>
<a href="#io-trm-v2a-001-reset-markets-slashed-the-new-resolver-bond-with-the-previous-bond">IO-TRM-V2A-001 Reset markets slashed the new resolver bond with the previous bond</a></li>
<li>
<a href="#io-trm-v2a-002-disputers-could-not-claim-bonds-from-unused-disputes-in-reset-markets">IO-TRM-V2A-002 Disputers could not claim bonds from unused disputes in reset markets</a></li>
<li>
<a href="#io-trm-v2a-003-compromised-owner-could-instantly-finalize-markets-for-profit">IO-TRM-V2A-003 Compromised owner could instantly finalize markets for profit</a></li>
<li>
<a href="#io-trm-v2a-004-oracle-council-member-could-pause-oraclecouncilv2-and-escalation-contracts-to-prevent-disputes">IO-TRM-V2A-004 Oracle Council Member could pause OracleCouncilV2 and Escalation Contracts to Prevent Disputes</a></li>
<li>
<a href="#io-trm-v2a-005-compromised-owner-could-affect-bonds-before-the-market-was-finalised">IO-TRM-V2A-005 Compromised owner could affect bonds before the market was finalised</a></li>
<li>
<a href="#io-trm-v2a-006-council-member-could-change-market-deadline">IO-TRM-V2A-006 Council member could change market deadline</a></li>
<li>
<a href="#io-trm-v2a-007-resolver-could-still-be-slashed-by-the-council-when-the-final-result-matched-their-original-submission">IO-TRM-V2A-007 Resolver could still be slashed by the council when the final result matched their original submission</a></li>
<li>
<a href="#io-trm-v2a-008-all-oraclecouncil-members-could-be-removed">IO-TRM-V2A-008 All OracleCouncil members could be removed</a></li>
<li>
<a href="#io-trm-v2a-009-incorrect-comment">IO-TRM-V2A-009 Incorrect comment</a></li>
<li>
<a href="#io-trm-v2a-010-empty-strings-could-be-detected-more-efficiently">IO-TRM-V2A-010 Empty strings could be detected more efficiently</a></li>
<li>
<a href="#io-trm-v2a-011-function-rename">IO-TRM-V2A-011 Function rename</a></li>
<li>
<a href="#io-trm-v2a-012-endoftrading-should-be-capped-to-a-maximum-limit">IO-TRM-V2A-012 EndOfTrading should be capped to a maximum limit</a></li>
<li>
<a href="#io-trm-v2a-013-challenge-periods-could-be-set-to-zero">IO-TRM-V2A-013 Challenge periods could be set to zero</a></li>
</ul>
</li>
<li>
<a href="#specification">Specification</a><ul>
<li>
<a href="#uniswap-v3-as-an-orderbook">Uniswap V3 as an orderbook</a></li>
<li>
<a href="#oracle-council">Oracle Council</a></li>
<li>
<a href="#rewards-distributor">Rewards Distributor</a></li>
<li>
<a href="#contract-ownership">Contract Ownership</a></li>
</ul>
</li>
<li>
<a href="#test-coverage-report">Test coverage report</a></li>
</ul>

</nav>
<article class="report">
<h1 id="introduction">Introduction</h1>
<p>iosiro was commissioned by True Markets to perform a smart contract audit of their True Markets V2 contracts. One auditor conducted the audit between 10 January 2025 and 28 February 2025, using 12 audit days.</p>
<h4 id="overview">Overview</h4>
<p>The audit identified two high-risk and four medium-risk issues, all resolved through code changes or accepted as risks.</p>
<p>The two high-risk issues, both resolved through code fixes, involved functional vulnerabilities: improper slashing of new resolver bonds in reset markets and disputers' inability to claim bonds.</p>
<p>The medium-risk findings related to privileged role permissions, including market finalization, dispute mechanism control, bond manipulation, and market deadline changes. Two were mitigated through code changes, while two were accepted with the safeguard of transferring contract ownership to a multi-sig wallet.</p>
<p>All issues were appropriately addressed, further strengthening the protocol's security and resilience.</p>
<table class="findings-count">
<thead>
<tr>
<th> </th>
<th>Critical</th>
<th>High</th>
<th>Medium</th>
<th>Low</th>
<th>Informational</th>
</tr>
</thead>
<tbody>
<tr>
<td>Open</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
</tr>
<tr>
<td>Resolved</td>
<td>0</td>
<td>2</td>
<td>2</td>
<td>0</td>
<td>3</td>
</tr>
<tr>
<td>Closed</td>
<td>0</td>
<td>0</td>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
</tbody>
</table>
<hr/>
<h4 id="scope">Scope</h4>
<p>The assessment focused on the source files listed below, with all other files considered out of scope. Any out-of-scope code interacting with the assessed code was presumed to operate correctly without introducing functional or security vulnerabilities.</p>
<ul>
<li><strong>Project name:</strong> truth-contracts</li>
<li><strong>Initial audit commit:</strong> <a href="https://github.com/truth-market/truth-contracts/commit/5c7d2eaafe1d120151be589ea0e42707df70cdd6">5c7d2ea</a></li>
<li><strong>Final review commit:</strong> <a href="https://github.com/truth-market/truth-contracts/commit/98829f9e936e2387ee7a6dd20eb23708e320c6f8">98829f9</a></li>
<li><strong>Files:</strong> BondConstants.sol, Escalation.sol, EscalationEnums.sol, EscalationStructs.sol, MarketEnums.sol, OracleBonds.sol, OracleCouncilV2.sol, OraclePausable.sol, OrderExecutor.sol, RewardsDistributionRecipient.sol, StakingRewards.sol, TrueToken.sol, TruthMarket.sol, TruthMarketManagerV2.sol, YesNoToken.sol</li>
</ul>
<p>A specification is available in the <a href="#specification">Specification section</a> of this report.</p>
<h1 id="disclaimer">Disclaimer</h1>
<p>This report aims to provide an overview of the assessed smart contracts' risk exposure and a guide to improving their security posture by addressing identified issues. The audit, limited to specific source code at the time of review, sought to:</p>
<ul>
<li>Identify potential security flaws.</li>
<li>Verify that the smart contracts' functionality aligns with their documentation.</li>
</ul>
<p>Off-chain components, such as backend web application code, keeper functionality, and deployment scripts were explicitly not in-scope of this audit.</p>
<p>Given the unregulated nature and ease of cryptocurrency transfers, operations involving these assets face a high risk from cyber attacks. Maintaining the highest security level is crucial, necessitating a proactive and adaptive approach that accounts for the experimental and rapidly evolving nature of blockchain technology. To encourage secure code development, developers should:</p>
<ul>
<li>Integrate security throughout the development lifecycle.</li>
<li>Employ defensive programming to mitigate the risks posed by unexpected events.</li>
<li>Adhere to current best practices wherever possible.</li>
</ul>
<h1 id="methodology">Methodology</h1>
<p>The audit was conducted using the techniques described below.</p>
<dl>
<dt>Code review</dt>
<dd>The source code was manually inspected to identify potential security flaws. Code review is a useful approach for detecting security flaws, discrepancies between the specification and implementation, design improvements, and high-risk areas of the system.</dd>
<dt>Dynamic analysis</dt>
<dd>The contracts were compiled, deployed, and tested in a test environment, both manually and through the test suite provided. Dynamic analysis was used to identify additional edge cases, confirm that the code was functional, and validate the reported issues.</dd>
<dt>Automated analysis</dt>
<dd>Automated tooling was used to detect the presence of various types of security vulnerabilities. Static analysis results were reviewed manually and any false positives were removed. Any true positive results are included in this report.</dd>
</dl>
<h1 id="audit-findings">Audit findings</h1>
<p>The table below provides an overview of the audit's findings. Detailed write-ups are provided below.</p>
<table class="findings">
<thead>
<tr>
<th>ID</th>
<th>Issue</th>
<th>Risk</th>
<th>Status</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#IO-TRM-V2A-001">IO-TRM-V2A-001</a></td>
<td>Reset markets slashed the new resolver bond with the previous bond</td>
<td class="rating-high">High</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-002">IO-TRM-V2A-002</a></td>
<td>Disputers could not claim bonds from unused disputes in reset markets</td>
<td class="rating-high">High</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-003">IO-TRM-V2A-003</a></td>
<td>Compromised owner could instantly finalize markets for profit</td>
<td class="rating-medium">Medium</td>
<td class="status-closed">Closed</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-004">IO-TRM-V2A-004</a></td>
<td>Oracle Council Member could pause OracleCouncilV2 and Escalation Contracts to Prevent Disputes</td>
<td class="rating-medium">Medium</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-005">IO-TRM-V2A-005</a></td>
<td>Compromised owner could affect bonds before the market was finalised</td>
<td class="rating-medium">Medium</td>
<td class="status-closed">Closed</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-006">IO-TRM-V2A-006</a></td>
<td>Council member could change market deadline</td>
<td class="rating-medium">Medium</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-007">IO-TRM-V2A-007</a></td>
<td>Resolver could still be slashed by the council when the final result matched their original submission</td>
<td class="rating-low">Low</td>
<td class="status-closed">Closed</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-008">IO-TRM-V2A-008</a></td>
<td>All OracleCouncil members could be removed</td>
<td class="rating-low">Low</td>
<td class="status-closed">Closed</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-009">IO-TRM-V2A-009</a></td>
<td>Incorrect comment</td>
<td class="rating-informational">Informational</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-010">IO-TRM-V2A-010</a></td>
<td>Empty strings could be detected more efficiently</td>
<td class="rating-informational">Informational</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-011">IO-TRM-V2A-011</a></td>
<td>Function rename</td>
<td class="rating-informational">Informational</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-012">IO-TRM-V2A-012</a></td>
<td>EndOfTrading should be capped to a maximum limit</td>
<td class="rating-informational">Informational</td>
<td class="status-closed">Closed</td>
</tr>
<tr>
<td><a href="#IO-TRM-V2A-013">IO-TRM-V2A-013</a></td>
<td>Challenge periods could be set to zero</td>
<td class="rating-informational">Informational</td>
<td class="status-closed">Closed</td>
</tr>
</tbody>
</table>
<p>Each issue identified during the audit has been assigned a risk rating. The rating is determined based on the criteria outlined below.</p>
<dl>
<dt>Critical risk</dt>
<dd>The issue could result in the theft of funds from the contract or its users.</dd>
<dt>High risk</dt>
<dd>The issue could result in the loss of funds for the contract owner or its users.</dd>
<dt>Medium risk</dt>
<dd>The issue resulted in the code being dysfunctional or the specification being implemented incorrectly.</dd>
<dt>Low risk</dt>
<dd>A design or best practice issue that could affect the ordinary functioning of the contract.</dd>
<dt>Informational</dt>
<dd>An improvement related to best practice or a suboptimal design pattern.</dd>
</dl>
<p>In addition to a risk rating, each issue is assigned a status:</p>
<dl>
<dt>Open</dt>
<dd>The issue remained present in the code as of the final commit reviewed and may still pose a risk.</dd>
<dt>Resolved</dt>
<dd>The issue was identified during the audit and has since been satisfactorily addressed, removing the risk it posed.</dd>
<dt>Closed</dt>
<dd>The issue was identified during the audit and acknowledged by the developers as an acceptable risk without actioning any change.</dd>
</dl>
<a name="IO-TRM-V2A-001"></a><h2 id="io-trm-v2a-001-reset-markets-slashed-the-new-resolver-bond-with-the-previous-bond" class="break-before"><strong>IO-TRM-V2A-001</strong> Reset markets slashed the new resolver bond with the previous bond</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-high">High</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L204">TruthMarket.sol#L204</a></td>
</tr>
</tbody>
</table>
<p>When a market was reset by the Oracle Council or escalation contracts, opting to punish the resolver, the market was put into a <code>ResetByCouncil</code> state. When the <code>secondChallengePeriod</code> subsided, a new resolution could be proposed for the market by calling <code>TruthMarket.proposeResolution()</code>. This pulled a new resolution bond from the caller and bundled it with the bond from the previous resolver on the <code>OracleBonds</code> contract. As the previous resolver was being slashed, both bonds were sent to the safe box, inadvertently punishing the new resolver.</p>
<h3 id="recommendation">Recommendation</h3>
<p><code>TruthMarket.proposeResolution()</code> should be called before the new bond is taken in <code>TruthMarketManager.proposeResolution()</code>.</p>
<h3 id="client-response">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/20a77f77f3074b44bcc7d95daf67d8bfbcfcbc90">20a77f7</a>.</p>
<a name="IO-TRM-V2A-002"></a><h2 id="io-trm-v2a-002-disputers-could-not-claim-bonds-from-unused-disputes-in-reset-markets" class="break-before"><strong>IO-TRM-V2A-002</strong> Disputers could not claim bonds from unused disputes in reset markets</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-high">High</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/OracleCouncilV2.sol#L421">OracleCouncilV2.sol#L421</a></td>
</tr>
</tbody>
</table>
<p>Markets allowed multiple submissions of disputes, each requiring a bond. During the dispute-handling process, only one dispute is used by the Oracle Council. The bond for the dispute used may be slashed, but all other disputers should be able to reclaim their bond.</p>
<p>However, when a market had multiple disputes submitted and the oracle council accepted one that got reset by escalation, the bonds for the unused disputes could not be claimed.</p>
<p>The issue appeared to be due to the following condition in <code>OracleCouncil.canDisputor<wbr/>Claimback<wbr/>BondFrom<wbr/>UnclosedDispute()</code> resolving to false:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="p">(</span><span class="n">marketClosedForDisputes</span><span class="p">[</span><span class="n">_market</span><span class="p">]</span> <span class="o">||</span> <span class="n">_disputeIndex</span> <span class="o"><=</span> <span class="n">allOpenDisputesCancelledToIndexForMarket</span><span class="p">[</span><span class="n">_market</span><span class="p">])</span>
</span></span></code></pre><h3 id="recommendation-1">Recommendation</h3>
<p>During market finalization, the market should set <code>marketClosedForDisputes[_market]</code> to <code>true</code> on <code>OracleCouncil</code> to ensure that the bonds can be claimed.</p>
<h3 id="client-response-1">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/ff62622994f46f2e4d68370c5fd29ebe8032671c">ff62622</a>.</p>
<a name="IO-TRM-V2A-003"></a><h2 id="io-trm-v2a-003-compromised-owner-could-instantly-finalize-markets-for-profit" class="break-before"><strong>IO-TRM-V2A-003</strong> Compromised owner could instantly finalize markets for profit</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-medium">Medium</td>
<td class="status-closed">Closed</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarketManagerV2.sol#L351">TruthMarketManagerV2.sol#L351</a>, <a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarketManagerV2.sol#L355">TruthMarketManagerV2.sol#L355</a>, <a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarketManagerV2.sol#L359">TruthMarketManagerV2.sol#L359</a></td>
</tr>
</tbody>
</table>
<p>The owner of the <code>TruthMarketManagerV2</code> contract could affect the market deadline, first challenge period, and second challenge period. This capability could be exploited to resolve any market to a chosen outcome, allowing the owner to obtain the winning position token for a cheap price and redeem it immediately from the market for profit.</p>
<h3 id="recommendation-2">Recommendation</h3>
<p>This permission should be removed from the owner and any decisions to extend the market deadline or challenge periods should be part of the dispute-resolution process.</p>
<h3 id="client-response-2">Client response</h3>
<p>Issue closed as after deployment, ownership of the contracts will be transfered to multi-sig. The team do not plan to make this function part of resolve-dispute process.</p>
<a name="IO-TRM-V2A-004"></a><h2 id="io-trm-v2a-004-oracle-council-member-could-pause-oraclecouncilv2-and-escalation-contracts-to-prevent-disputes" class="break-before"><strong>IO-TRM-V2A-004</strong> Oracle Council Member could pause OracleCouncilV2 and Escalation Contracts to Prevent Disputes</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-medium">Medium</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/OracleCouncilV2.sol#L309">OracleCouncilV2.sol#L309</a>, <a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/Escalation.sol#L195">Escalation.sol#L195</a></td>
</tr>
</tbody>
</table>
<p>In the <code>OracleCouncilV2</code> and <code>Escalation</code> contracts, any individual council member could execute the <code>pause()</code> function. This action could be exploited to prevent users from disputing the result of a market or escalating disputes, thereby forcibly resolving the market to a particular outcome. This vulnerability allowed a council member to manipulate the market resolution process to their advantage and potentially profit from it.</p>
<p>The impact of this issue was limited since other council members could unpause the functionality, however, in the instance of collusion the contracts could be paused indefinitely.</p>
<h3 id="recommendation-3">Recommendation</h3>
<p>A secure alternative to allowing the Oracle Council this permission could be to create a separate <code>Pauser</code> role whose only function is to pause the contracts. This pauser does not need to be a multi-sig, so timely responses will be possible when required.</p>
<h3 id="client-response-3">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/98829f9e936e2387ee7a6dd20eb23708e320c6f8">98829f9</a>.</p>
<a name="IO-TRM-V2A-005"></a><h2 id="io-trm-v2a-005-compromised-owner-could-affect-bonds-before-the-market-was-finalised" class="break-before"><strong>IO-TRM-V2A-005</strong> Compromised owner could affect bonds before the market was finalised</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-medium">Medium</td>
<td class="status-closed">Closed</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/OracleBonds.sol#L83">OracleBonds.sol#L83</a></td>
</tr>
</tbody>
</table>
<p>The <code>OracleBonds</code> contract used the <code>onlyOracleCouncilManagerAndOwner</code> and <code>onlyAuthorized</code> modifiers to control access to its functionality. Both modifiers permitted the owner address.</p>
<p>If the owner keys were compromised, the owner could repay bonds to accounts that were intended to be slashed by calling the following functions:</p>
<ul>
<li><code>issueBondsBackToEscalatedDisputor()</code></li>
<li><code>issueBondsBackToResolver()</code></li>
<li><code>issueBondsBackToDisputor()</code></li>
<li><code>sendOpenDisputeBondFromMarketToDisputor()</code>
Similarly, a compromised owner address could inadvertently slash addresses by calling <code>sendBond<wbr/>FromMarket<wbr/>ToSafeBox()</code>.</li>
</ul>
<h3 id="recommendation-4">Recommendation</h3>
<p>To minimize the risk of a compromised owner key, the owner should not be permitted to access protocol functionality directly, and should only be responsible for handling contract upgrades or deployment tasks. This restriction should be further reinforced by transferring contract ownership to a multisig after deployment.</p>
<h3 id="client-response-4">Client response</h3>
<p>Issue closed as the owner keys will transferred to a multi-sig after deployment.</p>
<a name="IO-TRM-V2A-006"></a><h2 id="io-trm-v2a-006-council-member-could-change-market-deadline" class="break-before"><strong>IO-TRM-V2A-006</strong> Council member could change market deadline</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-medium">Medium</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/OracleCouncilV2.sol#L305">OracleCouncilV2.sol#L305</a></td>
</tr>
</tbody>
</table>
<p>An Oracle Council member could manipulate the market by arbitrarily changing the deadline to a much earlier or later time, potentially catching participants off guard and forcing the market to resolve before they could react. This could lead to unfair market outcomes and financial losses for participants who were not aware of the sudden change.</p>
<h3 id="recommendation-5">Recommendation</h3>
<p>This ability should be removed from individual council members and incorporated into the dispute-resolution process to ensure fairness for all market participants.</p>
<h3 id="client-response-5">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/b57a465232c07d18caa26ff5bd204dae9476092b">b57a465</a>.</p>
<a name="IO-TRM-V2A-007"></a><h2 id="io-trm-v2a-007-resolver-could-still-be-slashed-by-the-council-when-the-final-result-matched-their-original-submission" class="break-before"><strong>IO-TRM-V2A-007</strong> Resolver could still be slashed by the council when the final result matched their original submission</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-closed">Closed</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L526">TruthMarket.sol#L526</a></td>
</tr>
</tbody>
</table>
<p>The resolution reward was allocated to a resolver during the dispute process if the final answer in the market matched the original resolver's submission. If the final answer was different, the reward was sent to the disputer, and if the market was canceled, it was sent to the safe box.</p>
<p>However, because the council or escalation voters could decide to punish the resolver, their bond could be slashed in this case. This created an inconsistency where after a dispute, if the final result matched the resolver's submission but it was decided to punish the resolver, they would lose their bond but still receive the resolution reward.</p>
<h3 id="recommendation-6">Recommendation</h3>
<p>To prevent inconsistencies, the rewards should not be paid if the bond is slashed or the bond should not be slashable if the original answer is finalized.</p>
<h3 id="client-response-6">Client response</h3>
<p>The issue was closed as the team did not see it as a risk and opted to leave the functionality as is.</p>
<a name="IO-TRM-V2A-008"></a><h2 id="io-trm-v2a-008-all-oraclecouncil-members-could-be-removed" class="break-before"><strong>IO-TRM-V2A-008</strong> All OracleCouncil members could be removed</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-closed">Closed</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/OracleCouncilV2.sol#L136">OracleCouncilV2.sol#L136</a></td>
</tr>
</tbody>
</table>
<p>The <code>OracleCouncil.removeOracleCouncilMember()</code> function did not prevent the removal of the final Oracle council member. This could allow the system to enter a state where there are no council members to resolve new disputes. Such a scenario could arise should the owner key be compromised.</p>
<h3 id="recommendation-7">Recommendation</h3>
<p>To minimize the risk of a compromised owner key, the owner should not be permitted to access protocol functionality directly, but should only be responsible for handling contract upgrades. This restriction should be further reinforced by transferring contract ownership to a multisig after deployment.</p>
<h3 id="client-response-7">Client response</h3>
<p>Issue closed as the owner keys will transferred to a multi-sig after deployment.</p>
<a name="IO-TRM-V2A-009"></a><h2 id="io-trm-v2a-009-incorrect-comment" class="break-before"><strong>IO-TRM-V2A-009</strong> Incorrect comment</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-informational">Informational</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L415">TruthMarket.sol#L415</a></td>
</tr>
</tbody>
</table>
<p>The comment at <a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L415">TruthMarket.sol#L415</a> is incorrect because if the market is canceled the holder can claim 1 USDC for every pair of YES and NO tokens provided.</p>
<h3 id="recommendation-8">Recommendation</h3>
<p>The comment should be updated to reflect the correct functionality.</p>
<h3 id="client-response-8">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/1596b08c604fffb631117b9c08fab8fcb1e1ae57">1596b08</a>.</p>
<a name="IO-TRM-V2A-010"></a><h2 id="io-trm-v2a-010-empty-strings-could-be-detected-more-efficiently" class="break-before"><strong>IO-TRM-V2A-010</strong> Empty strings could be detected more efficiently</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-informational">Informational</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarketManagerV2.sol#L190">TruthMarketManagerV2.sol#L190</a>, <a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarketManagerV2.sol#L193">TruthMarketManagerV2.sol#L193</a></td>
</tr>
</tbody>
</table>
<p>During market creation, the <code>_marketQuestion</code> and <code>_marketSource</code> are validated as empty using this expression:</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="nb">keccak256</span><span class="p">(</span><span class="nb">abi</span><span class="p">.</span><span class="nb">encode</span><span class="p">(</span><span class="n">_marketQuestion</span><span class="p">))</span> <span class="o">==</span> <span class="nb">keccak256</span><span class="p">(</span><span class="nb">abi</span><span class="p">.</span><span class="nb">encode</span><span class="p">(</span><span class="s">""</span><span class="p">))</span>
</span></span></code></pre><h3 id="recommendation-9">Recommendation</h3>
<p>A more efficient approach would be to cast the string to bytes and check the length, eg. <code>bytes(_marketQuestion).length == 0</code>.</p>
<h3 id="client-response-9">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/04a660ccbbfebdff14f7ffb758d703066e263f78">04a660c</a>.</p>
<a name="IO-TRM-V2A-011"></a><h2 id="io-trm-v2a-011-function-rename" class="break-before"><strong>IO-TRM-V2A-011</strong> Function rename</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-informational">Informational</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L502">TruthMarket.sol#L502</a></td>
</tr>
</tbody>
</table>
<p>The <code>TruthMarket._transferRewardToResolver()</code> function should be renamed to <code>TruthMarket._transferReward()</code> as it sends rewards to more than just the resolver.</p>
<h3 id="client-response-10">Client response</h3>
<p>Fixed in <a href="https://github.com/truth-market/truth-contracts/commit/35bda487024bed3b217b3d6455830996bc4f489e">35bda48</a>.</p>
<a name="IO-TRM-V2A-012"></a><h2 id="io-trm-v2a-012-endoftrading-should-be-capped-to-a-maximum-limit" class="break-before"><strong>IO-TRM-V2A-012</strong> EndOfTrading should be capped to a maximum limit</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-informational">Informational</td>
<td class="status-closed">Closed</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L284">TruthMarket.sol#L284</a></td>
</tr>
</tbody>
</table>
<p>The <code>TruthMarket.setEndOfTrading()</code> function allows the end of trading for a market to be set to any arbitrary value. This poses a risk, as it could be exploited in attacks to prematurely force market resolution or to disrupt the market entirely by setting an unreachable end-of-trading value.</p>
<h3 id="recommendation-10">Recommendation</h3>
<p>The function should enforce some controls to ensure that the value being set is not less than the current time plus some buffer and it is also not being incremented by an unrealistically large amount.</p>
<h3 id="client-response-11">Client response</h3>
<p>The issue was closed as the ownership of the contract will be transferred to a multisig and the team expected not to update these functions unless there is a need for it.</p>
<a name="IO-TRM-V2A-013"></a><h2 id="io-trm-v2a-013-challenge-periods-could-be-set-to-zero" class="break-before"><strong>IO-TRM-V2A-013</strong> Challenge periods could be set to zero</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-informational">Informational</td>
<td class="status-closed">Closed</td>
<td><a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L293">TruthMarket.sol#L293</a>, <a href="https://github.com/truth-market/truth-contracts/blob/5c7d2eaafe1d120151be589ea0e42707df70cdd6/src/TruthMarket.sol#L298">TruthMarket.sol#L298</a></td>
</tr>
</tbody>
</table>
<p>The <code>TruthMarket.setFirst<wbr/>ChallengePeriod()</code> and <code>TruthMarket.setSecond<wbr/>ChallengePeriod()</code> functions could be called to set the periods to any value. This could compound the possible impact of an issue by preventing disputes or escalations.</p>
<h3 id="recommendation-11">Recommendation</h3>
<p>These periods should be validated as greater than <code>endOfTrading</code> plus some buffer but lesser than an unrealistic period length that could prevent the period from completing.</p>
<h3 id="client-response-12">Client response</h3>
<p>The issue was closed as the ownership of the contract will be transferred to a multisig and the team expected not to update these functions unless there is a need for it.</p>
<h1 id="specification">Specification</h1>
<h2 id="uniswap-v3-as-an-orderbook">Uniswap V3 as an orderbook</h2>
<p>The decision to use concentrated liquidity pools from Uniswap V3, fully independent of the Truemarkets contracts, was made to discourage passive liquidity providers (LPs). Instead, market LPs are incentivized to take active positions by supplying liquidity only within specific price ranges they support.</p>
<p>As the market approaches finality, LPs are motivated to withdraw their liquidity to prevent trading after finalization. Those who provide liquidity across the entire price spread risk arbitrage, where users can buy 1 YES and 1 NO token for less than 1 USDC.</p>
<h2 id="oracle-council">Oracle Council</h2>
<p>Market disputes are handled by the Oracle Council, which oversees market resolution and disputes over proposed outcomes. Users can challenge the council’s decisions by posting a bond. Initially, the council will consist of protocol team members, but community members are expected to join over time.</p>
<h2 id="rewards-distributor">Rewards Distributor</h2>
<p>A StakingRewards contract distributes TRUE token rewards to LPs and TRUE stakers. When both the staking and reward tokens are TRUE, <code>notifyRewardAmount()</code> must be called with the contract's TRUE token balance. Passing an inflated value could allow early claimers to drain the contract. Additionally, caution is required during deployment and initialization, as <code>recoverERC20()</code> cannot be used in this scenario.</p>
<h2 id="contract-ownership">Contract Ownership</h2>
<p>A key concern of the audit was the risk of compromised owner keys, which could grant an attacker full control over the platform and market states. While some measures were implemented to mitigate this risk, it is critical that, upon successful deployment, contract ownership is transferred to a multi-signature wallet requiring multiple keys, each stored in separate team members' cold wallets.</p>
<h1 id="test-coverage-report">Test coverage report</h1>
<p>The coverage report of the provided tests on the final day of the audit is given below.</p>
<table>
<thead>
<tr>
<th>File</th>
<th>% Lines</th>
<th>% Statements</th>
<th>% Branches</th>
<th>% Funcs</th>
</tr>
</thead>
<tbody>
<tr>
<td>src/Escalation.sol</td>
<td>82.19% (60/73)</td>
<td>84.29% (59/70)</td>
<td>66.67% (10/15)</td>
<td>69.23% (9/13)</td>
</tr>
<tr>
<td>src/OracleBonds.sol</td>
<td>84.14% (122/145)</td>
<td>78.62% (114/145)</td>
<td>33.33% (12/36)</td>
<td>82.61% (19/23)</td>
</tr>
<tr>
<td>src/OraclePausable.sol</td>
<td>92.86% (13/14)</td>
<td>88.89% (8/9)</td>
<td>45.45% (5/11)</td>
<td>100.00% (3/3)</td>
</tr>
<tr>
<td>src/OrderExecutor.sol</td>
<td>0.00% (0/18)</td>
<td>0.00% (0/17)</td>
<td>0.00% (0/9)</td>
<td>0.00% (0/2)</td>
</tr>
<tr>
<td>src/RewardsDistributionRecipient.sol</td>
<td>50.00% (2/4)</td>
<td>50.00% (1/2)</td>
<td>0.00% (0/2)</td>
<td>50.00% (1/2)</td>
</tr>
<tr>
<td>src/StakingRewards.sol</td>
<td>69.57% (48/69)</td>
<td>67.80% (40/59)</td>
<td>17.65% (3/17)</td>
<td>75.00% (12/16)</td>
</tr>
<tr>
<td>src/TrueToken.sol</td>
<td>87.50% (14/16)</td>
<td>90.91% (10/11)</td>
<td>100.00% (1/1)</td>
<td>85.71% (6/7)</td>
</tr>
<tr>
<td>src/TruthMarket.sol</td>
<td>77.94% (219/281)</td>
<td>79.87% (254/318)</td>
<td>44.74% (34/76)</td>
<td>73.33% (22/30)</td>
</tr>
<tr>
<td>src/YesNoToken.sol</td>
<td>100.00% (2/2)</td>
<td>100.00% (1/1)</td>
<td>100.00% (0/0)</td>
<td>100.00% (1/1)</td>
</tr>
<tr>
<td>src/utils/libraries/AddressSetLib.sol</td>
<td>30.00% (9/30)</td>
<td>27.78% (10/36)</td>
<td>28.57% (2/7)</td>
<td>50.00% (2/4)</td>
</tr>
<tr>
<td>test/OracleBond.t.sol</td>
<td>100.00% (14/14)</td>
<td>100.00% (7/7)</td>
<td>100.00% (0/0)</td>
<td>100.00% (7/7)</td>
</tr>
<tr>
<td>test/StakingRewards.t.sol</td>
<td>100.00% (2/2)</td>
<td>100.00% (1/1)</td>
<td>100.00% (0/0)</td>
<td>100.00% (1/1)</td>
</tr>
<tr>
<td>test/TruthMarket.t.sol</td>
<td>100.00% (4/4)</td>
<td>100.00% (2/2)</td>
<td>100.00% (0/0)</td>
<td>100.00% (2/2)</td>
</tr>
<tr>
<td>test/TruthMarketManager.t.sol</td>
<td>50.00% (2/4)</td>
<td>50.00% (1/2)</td>
<td>100.00% (0/0)</td>
<td>50.00% (1/2)</td>
</tr>
<tr>
<td>test/e2e.t.sol</td>
<td>100.00% (4/4)</td>
<td>100.00% (2/2)</td>
<td>100.00% (0/0)</td>
<td>100.00% (2/2)</td>
</tr>
<tr>
<td>Total</td>
<td>43.67% (869/1990)</td>
<td>42.44% (879/2071)</td>
<td>40.85% (125/306)</td>
<td>40.44% (146/361)</td>
</tr>
</tbody>
</table>
<p>The project's test coverage is low and could be improved to ensure the code is more robust and less prone to issues.</p>

</article>
</main>
</div>

Secure your system.
Request a service
Start Now