Nexus Mutual Protocol Upgrade 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');.codequality td{min-width:6em;} 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">Nexus Mutual Protocol Upgrade Smart Contract Audit</div>
<div class="frontpage-subtitle">Nexus Mutual, 17 September 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-nxm-pgr-024-total-active-cover-incorrect-after-migration">IO-NXM-PGR-024 Total active cover incorrect after migration</a></li>
<li>
<a href="#io-nxm-pgr-001-changes-to-memory-not-committed-to-storage">IO-NXM-PGR-001 Changes to memory not committed to storage</a></li>
<li>
<a href="#io-nxm-pgr-002-twap-can-be-updated-during-system-pause">IO-NXM-PGR-002 TWAP can be updated during system pause</a></li>
<li>
<a href="#io-nxm-pgr-003-global-pause-not-checked">IO-NXM-PGR-003 Global pause not checked</a></li>
<li>
<a href="#io-nxm-pgr-004-add-zero-address-check-for-new-proxy-owner">IO-NXM-PGR-004 Add zero address check for new proxy owner</a></li>
<li>
<a href="#io-nxm-pgr-019-ab-member-votes-are-not-tallied-by-seat">IO-NXM-PGR-019 AB member votes are not tallied by seat</a></li>
<li>
<a href="#io-nxm-pgr-021-assessor-groups-can-be-created-without-specifying-0-as-the-groupid">IO-NXM-PGR-021 Assessor groups can be created without specifying 0 as the groupId</a></li>
</ul>
</li>
<li>
<a href="#code-quality-improvement-suggestions">Code quality improvement suggestions</a></li>
<li>
<a href="#specification">Specification</a><ul>
<li>
<a href="#governance">Governance</a></li>
<li>
<a href="#registry">Registry</a></li>
<li>
<a href="#assessments">Assessments</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 Nexus Mutual to perform a smart contract audit of the updated Assessments and Governance modules. The audit was conducted by two auditors over 24 audit days, between 20 August and 9 September 2025.</p>
<h4 id="overview">Overview</h4>
<p>The audit identified one high-risk, six low-risk, and seventeen informational issues – all of these were either resolved or closed during the audit.</p>
<p>The resolved high-risk pertained to an issue in the migration of assets in the capital pool during the protocol upgrade, which would have resulted in an incorrect total active cover value.</p>
<p>The resolved low-risk issues included memory changes not committed to storage, TWAP updates during system pauses, global pause checks, incorrect handling of assessor group creation, and zero address validation for proxy ownership transfers.</p>
<p>The open low-risk issue pertains to improper handling of assessor group creation.</p>
<p>Informational findings highlighted areas for code quality improvements, such as parameter validation, redundant checks, and unused contracts. All issues were addressed appropriately, enhancing the protocol's security and operational robustness.</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>1</td>
<td>0</td>
<td>6</td>
<td>13</td>
</tr>
<tr>
<td>Closed</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>0</td>
<td>4</td>
</tr>
</tbody>
</table>
<h4 id="scope">Scope</h4>
<p>The assessment focused on the source file 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> Protocol Upgrade</li>
<li><strong>Initial audit commit:</strong> <a href="https://github.com/NexusMutual/smart-contracts/tree/37884fb496af98848b1076142aaf27d42a789954">37884fb</a></li>
<li><strong>Final review commit:</strong> <a href="https://github.com/NexusMutual/smart-contracts/tree/dfb83d2d9362367bcd70b2dd3a50d9e347f1af03">aa18d78</a></li>
<li><strong>Files:</strong> EIP712.sol, ReentrancyGuard.sol, RegistryAware.sol, WETH9.sol, CoverBroker.sol, Pool.sol, Ramm.sol, SafeTracker.sol, SwapOperator.sol, Governor.sol, NXMaster.sol, Registry.sol, TemporaryGovernance.sol, UpgradeableProxy.sol, LegacyAssessment.sol, LegacyMCR.sol, LegacyMemberRoles.sol, StakingProducts.sol, StakingViewer.sol, TokenController.sol, EnumerableSet.sol, Assessment.sol, Claims.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-NXM-PGR-024">IO-NXM-PGR-024</a></td>
<td>Total active cover incorrect after migration</td>
<td class="rating-high">High</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-NXM-PGR-001">IO-NXM-PGR-001</a></td>
<td>Changes to memory not committed to storage</td>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-NXM-PGR-002">IO-NXM-PGR-002</a></td>
<td>TWAP can be updated during system pause</td>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-NXM-PGR-003">IO-NXM-PGR-003</a></td>
<td>Global pause not checked</td>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-NXM-PGR-004">IO-NXM-PGR-004</a></td>
<td>Add zero address check for new proxy owner</td>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-NXM-PGR-019">IO-NXM-PGR-019</a></td>
<td>AB member votes are not tallied by seat</td>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
</tr>
<tr>
<td><a href="#IO-NXM-PGR-021">IO-NXM-PGR-021</a></td>
<td>Assessor groups can be created without specifying 0 as the groupId</td>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</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-NXM-PGR-024"></a><h2 id="io-nxm-pgr-024-total-active-cover-incorrect-after-migration" class="break-before"><strong>IO-NXM-PGR-024</strong> Total active cover incorrect after migration</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-high">High</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/Pool.sol#L498-L500">Pool.sol#L498-L500</a></td>
</tr>
</tbody>
</table>
<p><code>Pool::migrate()</code> skips DAI when moving supported assets from the previous pool. This causes the asset IDs in <code>Pool::getTotalActiveCoverAmount()</code> to mismatch the asset IDs still in the Cover contract, resulting in an incorrect calculation of total active cover, which is relied on in critical areas of the protocol, including when updating MCR.</p>
<h3 id="recommendation">Recommendation</h3>
<p>DAI should not be skipped during the migration, but rather marked as abandoned.</p>
<h3 id="client-response">Client response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/commit/0f280c7e989a4a5d9321648d1de4f3919cd6c9c1">0f280c7</a>.</p>
<a name="IO-NXM-PGR-001"></a><h2 id="io-nxm-pgr-001-changes-to-memory-not-committed-to-storage" class="break-before"><strong>IO-NXM-PGR-001</strong> Changes to memory not committed to storage</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L170">Governor.sol#L170</a></td>
</tr>
</tbody>
</table>
<p>The timelock cooldown is not automatically started when an Advisory Board proposal reaches its threshold due to the updated <code>executeAfter</code> value being set in <code>memory</code> and not saved to <code>storage</code>.</p>
<p>The following snippet shows a proof of concept for this vulnerability.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">loadFixture</span> <span class="p">,</span> <span class="nx">time</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'@nomicfoundation/hardhat-network-helpers'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">expect</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'chai'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">setup</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'test/unit/Governor/setup'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">parseEther</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'ethers'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">ethers</span><span class="p">,</span> <span class="nx">nexus</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'hardhat'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">Choice</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">nexus</span><span class="p">.</span><span class="nx">constants</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">it</span><span class="p">(</span><span class="s1">'does not start timelock cooldown when AB threshold is met (executeAfter not updated in storage)'</span><span class="p">,</span> <span class="kr">async</span> <span class="p">()</span> <span class="p">=></span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">governor</span><span class="p">,</span> <span class="nx">accounts</span><span class="p">,</span> <span class="nx">registry</span><span class="p">,</span> <span class="nx">tokenController</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">loadFixture</span><span class="p">(</span><span class="nx">setup</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">abMembers</span> <span class="o">=</span> <span class="nx">accounts</span><span class="p">.</span><span class="nx">advisoryBoardMembers</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">[</span><span class="nx">member</span><span class="p">]</span> <span class="o">=</span> <span class="nx">accounts</span><span class="p">.</span><span class="nx">members</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">abMemberIds</span> <span class="o">=</span> <span class="kr">await</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">m</span> <span class="p">=></span> <span class="nx">registry</span><span class="p">.</span><span class="nx">memberIds</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">address</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">memberId</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">registry</span><span class="p">.</span><span class="nx">memberIds</span><span class="p">(</span><span class="nx">member</span><span class="p">.</span><span class="nx">address</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Give member enough tokens to propose
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">await</span> <span class="nx">tokenController</span><span class="p">.</span><span class="nx">setTotalBalanceOf</span><span class="p">(</span><span class="nx">member</span><span class="p">.</span><span class="nx">address</span><span class="p">,</span> <span class="nx">parseEther</span><span class="p">(</span><span class="s1">'100'</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">tokenController</span><span class="p">.</span><span class="nx">setTotalSupply</span><span class="p">(</span><span class="nx">parseEther</span><span class="p">(</span><span class="s1">'10000'</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Create a board swap proposal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="nx">txs</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">target</span><span class="o">:</span> <span class="nx">registry</span><span class="p">.</span><span class="nx">target</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">value</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">data</span><span class="o">:</span> <span class="s2">"0x"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Propose
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="nx">tx</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">[</span><span class="mi">0</span><span class="p">]).</span><span class="nx">propose</span><span class="p">(</span><span class="nx">txs</span><span class="p">,</span> <span class="s1">'X'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">receipt</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">tx</span><span class="p">.</span><span class="nx">wait</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">proposalBlockTimestamp</span> <span class="o">=</span> <span class="p">(</span><span class="kr">await</span> <span class="nx">ethers</span><span class="p">.</span><span class="nx">provider</span><span class="p">.</span><span class="nx">getBlock</span><span class="p">(</span><span class="nx">receipt</span><span class="p">.</span><span class="nx">blockNumber</span><span class="p">)).</span><span class="nx">timestamp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">proposalId</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// Assuming proposal ID is 1 for simplicity
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    
</span></span><span class="line"><span class="cl">    <span class="c1">// Calculate expected executeAfter values
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="nx">VOTING_PERIOD</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">*</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">60</span><span class="p">;</span> <span class="c1">// 3 days in seconds
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="nx">TIMELOCK_PERIOD</span> <span class="o">=</span> <span class="mi">24</span> <span class="o">*</span> <span class="mi">60</span> <span class="o">*</span> <span class="mi">60</span><span class="p">;</span> <span class="c1">// 1 day in seconds
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="nx">expectedOriginalExecuteAfter</span> <span class="o">=</span> <span class="nx">proposalBlockTimestamp</span> <span class="o">+</span> <span class="nx">VOTING_PERIOD</span> <span class="o">+</span> <span class="nx">TIMELOCK_PERIOD</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Check proposal storage for executeAfter
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">let</span> <span class="nx">proposal</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">getProposal</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">expect</span><span class="p">(</span><span class="nx">proposal</span><span class="p">.</span><span class="nx">executeAfter</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">expectedOriginalExecuteAfter</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Cast votes from enough AB members to meet threshold
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">3</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kd">let</span> <span class="nx">voteTx</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">[</span><span class="nx">i</span><span class="p">]).</span><span class="nx">vote</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">,</span> <span class="nx">Choice</span><span class="p">.</span><span class="nx">For</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">proposal</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">getProposal</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">tally</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">getProposalTally</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">expect</span><span class="p">(</span><span class="nx">tally</span><span class="p">.</span><span class="nx">forVotes</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="nx">gte</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> <span class="c1">// Ensure votes exceed 3 votes to pass threshhold
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">const</span> <span class="nx">blockTimestamp</span> <span class="o">=</span> <span class="p">(</span><span class="kr">await</span> <span class="nx">ethers</span><span class="p">.</span><span class="nx">provider</span><span class="p">.</span><span class="nx">getBlock</span><span class="p">(</span><span class="s1">'latest'</span><span class="p">)).</span><span class="nx">timestamp</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">expectedExecuteAfter</span> <span class="o">=</span> <span class="nx">blockTimestamp</span> <span class="o">+</span> <span class="nx">TIMELOCK_PERIOD</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Assert executeAfter is updated to the expected value
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nx">expect</span><span class="p">(</span><span class="nx">ethers</span><span class="p">.</span><span class="nx">toBigInt</span><span class="p">(</span><span class="nx">proposal</span><span class="p">.</span><span class="nx">executeAfter</span><span class="p">)).</span><span class="nx">to</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">ethers</span><span class="p">.</span><span class="nx">toBigInt</span><span class="p">(</span><span class="nx">expectedExecuteAfter</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="nx">expect</span><span class="p">(</span><span class="nx">proposal</span><span class="p">.</span><span class="nx">executeAfter</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">not</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">expectedOriginalExecuteAfter</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span></code></pre><h3 id="recommendation-1">Recommendation</h3>
<p>The contract should instead set</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="n">proposals</span><span class="p">[</span><span class="n">proposalId</span><span class="p">].</span><span class="n">executeAfter</span> <span class="o">=</span>  <span class="p">(</span><span class="nb">block</span><span class="p">.</span><span class="nb">timestamp</span> <span class="o">+</span> <span class="n">TIMELOCK_PERIOD</span><span class="p">).</span><span class="n">toUint32</span><span class="p">();</span>
</span></span></code></pre><h3 id="client-response-1">Client response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/18b32b2df1b40d91d32fc6644d4461a29ab0a067">18b32b2</a>.</p>
<a name="IO-NXM-PGR-002"></a><h2 id="io-nxm-pgr-002-twap-can-be-updated-during-system-pause" class="break-before"><strong>IO-NXM-PGR-002</strong> TWAP can be updated during system pause</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/Ramm.sol#L636">Ramm.sol#L636</a></td>
</tr>
</tbody>
</table>
<p>Anyone can call <code>Ramm::updateTwap()</code> even when the global system pause has been enabled. The function queries values such as the capital pool's balances and the MCR, which might be unreliable during a system upgrade.</p>
<h3 id="recommendation-2">Recommendation</h3>
<p>To prevent artificial and unexpected fluctuations in the reported TWAP value during system maintenance, a <code>WhenNotPaused()</code> modifier should be added. This issue also affects <code>Ramm::getInternalPriceAndUpdateTwap()</code> . As such, the <code>WhenNotPaused()</code> modifier could be added to the internal <code>_updateTwap()</code> to cover both functions. Alternatively, and ideally, <code>Ramm::getInternalPriceAndUpdateTwap()</code> could be refactored to call <code>updateTwap()</code> as the TWAP update logic is the same in both functions.</p>
<h3 id="client-response-2">Client response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/commit/feef986a79206176ec8e8863c13857b1dc9b4176">feef986</a> and <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/d8ef8da514bd960db274538becfad1443c83e913">d8ef8da</a>.</p>
<a name="IO-NXM-PGR-003"></a><h2 id="io-nxm-pgr-003-global-pause-not-checked" class="break-before"><strong>IO-NXM-PGR-003</strong> Global pause not checked</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Registry.sol#L96-L98">Registry.sol#L96-L98</a></td>
</tr>
</tbody>
</table>
<p><code>Registry::isPaused</code> does not check whether the system is paused globally, similar to the <code>WhenNotPaused()</code> modifier. This currently has no impact, as the only <a href="https://github.com/NexusMutual/smart-contracts/blob/b6943cf7ca27212416e45a5a6b21ebf73bda2214/contracts/modules/governance/NXMaster.sol#L36">caller</a> of this function passes in a <code>PAUSE_GLOBAL</code> mask. However, bugs may be introduced if additional features are added in the future that use this function.</p>
<h3 id="recommendation-3">Recommendation</h3>
<p><code>Registry::isPaused</code> should check for a global system pause by performing a bitwise and between the mask and the <code>PAUSE_GLOBAL</code> value, similar to the <code>whenNotPaused</code> modifier.</p>
<h3 id="client-response-3">Client response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/4d69169e5925f4a3fedb1db034e8bb40a1eaadcd">4d69169</a>.</p>
<a name="IO-NXM-PGR-004"></a><h2 id="io-nxm-pgr-004-add-zero-address-check-for-new-proxy-owner" class="break-before"><strong>IO-NXM-PGR-004</strong> Add zero address check for new proxy owner</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/UpgradeableProxy.sol#L39-L43">UpgradeableProxy.sol#L39-L43</a></td>
</tr>
</tbody>
</table>
<p><code>UpgradeableProxy::transferProxyOwnership()</code> should check that the <code>_newOwner</code> address is not zero, and revert if so, to avoid accidentally losing ownership of a proxy.</p>
<h3 id="recommendation-4">Recommendation</h3>
<p>Add a zero address check to the argument passed in to prevent loss of proxy ownership.</p>
<h3 id="client-response-4">Client response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/b9f07ef7fbfaa7ae27818303efb77030070ca5fa">b9f07ef</a>.</p>
<a name="IO-NXM-PGR-019"></a><h2 id="io-nxm-pgr-019-ab-member-votes-are-not-tallied-by-seat" class="break-before"><strong>IO-NXM-PGR-019</strong> AB member votes are not tallied by seat</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L145">Govenor.sol#L145</a></td>
</tr>
</tbody>
</table>
<p>After a <code>swapAdvisoryBoardMember</code> proposal, the votes of the advisory board member are not transferred to the new member. This can cause AB member proposals to have more than five votes in total.</p>
<p>The following snippet shows a proof of concept for this vulnerability.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">loadFixture</span> <span class="p">,</span> <span class="nx">time</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'@nomicfoundation/hardhat-network-helpers'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">expect</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'chai'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="nx">setup</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'test/unit/Governor/setup'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">parseEther</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'ethers'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">ethers</span><span class="p">,</span> <span class="nx">nexus</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'hardhat'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">Choice</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">nexus</span><span class="p">.</span><span class="nx">constants</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nx">it</span><span class="p">(</span><span class="s1">'does not transfer votes to new AB member after a swapAdvisoryBoardMember proposal'</span><span class="p">,</span> <span class="kr">async</span> <span class="p">()</span> <span class="p">=></span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">governor</span><span class="p">,</span> <span class="nx">accounts</span><span class="p">,</span> <span class="nx">registry</span><span class="p">,</span> <span class="nx">tokenController</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">loadFixture</span><span class="p">(</span><span class="nx">setup</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">abMembers</span> <span class="o">=</span> <span class="nx">accounts</span><span class="p">.</span><span class="nx">advisoryBoardMembers</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">[</span><span class="nx">member</span><span class="p">]</span> <span class="o">=</span> <span class="nx">accounts</span><span class="p">.</span><span class="nx">members</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">abMemberIds</span> <span class="o">=</span> <span class="kr">await</span> <span class="nb">Promise</span><span class="p">.</span><span class="nx">all</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">m</span> <span class="p">=></span> <span class="nx">registry</span><span class="p">.</span><span class="nx">memberIds</span><span class="p">(</span><span class="nx">m</span><span class="p">.</span><span class="nx">address</span><span class="p">)));</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">memberId</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">registry</span><span class="p">.</span><span class="nx">memberIds</span><span class="p">(</span><span class="nx">member</span><span class="p">.</span><span class="nx">address</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Allocate sufficient tokens to the proposer to meet the proposal threshold
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kr">await</span> <span class="nx">tokenController</span><span class="p">.</span><span class="nx">setTotalBalanceOf</span><span class="p">(</span><span class="nx">member</span><span class="p">.</span><span class="nx">address</span><span class="p">,</span> <span class="nx">parseEther</span><span class="p">(</span><span class="s1">'200'</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">tokenController</span><span class="p">.</span><span class="nx">setTotalSupply</span><span class="p">(</span><span class="nx">parseEther</span><span class="p">(</span><span class="s1">'10000'</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">txs</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nx">target</span><span class="o">:</span> <span class="nx">registry</span><span class="p">.</span><span class="nx">target</span><span class="p">,</span> <span class="c1">// Ensure this is a valid address
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nx">value</span><span class="o">:</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="nx">data</span><span class="o">:</span> <span class="s2">"0x"</span><span class="p">,</span> <span class="c1">// Placeholder data
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">tx</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">accounts</span><span class="p">.</span><span class="nx">advisoryBoardMembers</span><span class="p">[</span><span class="mi">0</span><span class="p">]).</span><span class="nx">propose</span><span class="p">(</span><span class="nx">txs</span><span class="p">,</span> <span class="s1">'Test Proposal'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">receipt</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">tx</span><span class="p">.</span><span class="nx">wait</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">proposalId</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">tokenController</span><span class="p">.</span><span class="nx">setTotalBalanceOf</span><span class="p">(</span><span class="nx">member</span><span class="p">.</span><span class="nx">address</span><span class="p">,</span> <span class="nx">parseEther</span><span class="p">(</span><span class="s1">'0'</span><span class="p">));</span> <span class="c1">//remove tokens after proposal
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Cast votes from AB members for a draw
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">[</span><span class="nx">i</span><span class="p">]).</span><span class="nx">vote</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">,</span> <span class="nx">Choice</span><span class="p">.</span><span class="nx">For</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">4</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">[</span><span class="nx">i</span><span class="p">]).</span><span class="nx">vote</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">,</span> <span class="nx">Choice</span><span class="p">.</span><span class="nx">Against</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">abMembers</span><span class="p">[</span><span class="mi">4</span><span class="p">]).</span><span class="nx">vote</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">,</span> <span class="nx">Choice</span><span class="p">.</span><span class="nx">Abstain</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// Check the total votes
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="kd">let</span> <span class="nx">tallyForVotesBeforeSwap</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">member</span><span class="p">).</span><span class="nx">getProposalTally</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">tallyForVotesBeforeSwap</span> <span class="o">=</span> <span class="nx">tallyForVotesBeforeSwap</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)[</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">registry</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">member</span><span class="p">).</span><span class="nx">swapAdvisoryBoardMember</span><span class="p">(</span><span class="nx">abMemberIds</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="nx">memberId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">expect</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">      <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">member</span><span class="p">).</span><span class="nx">vote</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">,</span> <span class="nx">Choice</span><span class="p">.</span><span class="nx">For</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="nx">revertedWithCustomError</span><span class="p">(</span><span class="nx">governor</span><span class="p">,</span> <span class="s1">'AlreadyVoted'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kd">let</span> <span class="nx">tallyForVotesAfterSwap</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">governor</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">member</span><span class="p">).</span><span class="nx">getProposalTally</span><span class="p">(</span><span class="nx">proposalId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="nx">tallyForVotesAfterSwap</span> <span class="o">=</span> <span class="nx">tallyForVotesAfterSwap</span><span class="p">.</span><span class="nx">toString</span><span class="p">().</span><span class="nx">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)[</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nx">expect</span><span class="p">(</span><span class="nx">tallyForVotesAfterSwap</span><span class="p">.</span><span class="nx">toString</span><span class="p">()).</span><span class="nx">to</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="nx">tallyForVotesBeforeSwap</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span> <span class="c1">// Ensure votes are the same
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">    <span class="nx">expect</span><span class="p">(</span><span class="nx">tallyForVotesAfterSwap</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="nx">equal</span><span class="p">(</span><span class="s1">'2'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span></code></pre><h3 id="recommendation-5">Recommendation</h3>
<p>AB member votes should be indexed according to seat number instead of <code>memberId</code>. This can be achieved by moving the <code>voterId</code> before the weight check, and using <code>voterId</code> instead of <code>memberId</code>, e.g., <code>votes[proposalId][voterId]</code>. If a new member disagrees with their seat's vote, they can call <code>cancelVote()</code>.</p>
<h3 id="client-response-5">Client response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/99bfd61875f516482f50131079021b866c04d63f">99bfd61</a></p>
<a name="IO-NXM-PGR-021"></a><h2 id="io-nxm-pgr-021-assessor-groups-can-be-created-without-specifying-0-as-the-groupid" class="break-before"><strong>IO-NXM-PGR-021</strong> Assessor groups can be created without specifying 0 as the groupId</h2>
<table class="metadata">

<tbody>
<tr>
<td class="rating-low">Low</td>
<td class="status-resolved">Resolved</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/assessment/Assessment.sol#L108">Assessment.sol#108</a></td>
</tr>
</tbody>
</table>
<p>When calling the <code>Assessment::addAssessorsToGroup()</code> function, it is possible to create a new assessor group by specifying any <code>groupId</code> that's not equal to 0 and greater than the current <code>groupCount</code>. If an assessor group is created this way, this will result in the returned <code>groupCount</code> being incorrect, as it will not be incremented. Additionally, any calls to <code>setGroupMetadata()</code>, <code>removeAssessorFromGroup()</code>, and <code>setAssessmentDataForProductTypes()</code> will revert if given the new <code>groupId</code>.</p>
<p>The following snippet shows a proof of concept for this vulnerability.</p>
<pre tabindex="0" class="chroma"><code><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">expect</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'chai'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">loadFixture</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'@nomicfoundation/hardhat-network-helpers'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kr">const</span> <span class="p">{</span> <span class="nx">setup</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="s1">'test/unit/Assessment/setup'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">it</span><span class="p">(</span><span class="s1">'should revert when groupId is invalid (greater than group count)'</span><span class="p">,</span> <span class="kr">async</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">contracts</span><span class="p">,</span> <span class="nx">accounts</span> <span class="p">}</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">loadFixture</span><span class="p">(</span><span class="nx">setup</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">{</span> <span class="nx">assessment</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">contracts</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="p">[</span><span class="nx">governanceAccount</span><span class="p">]</span> <span class="o">=</span> <span class="nx">accounts</span><span class="p">.</span><span class="nx">governanceContracts</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">currentGroupCount</span> <span class="o">=</span> <span class="kr">await</span> <span class="nx">assessment</span><span class="p">.</span><span class="nx">getGroupsCount</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">invalidGroupId</span> <span class="o">=</span> <span class="nx">currentGroupCount</span> <span class="o">+</span> <span class="mi">1</span><span class="nx">n</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="kr">const</span> <span class="nx">addAssessorsToGroup</span> <span class="o">=</span> <span class="nx">assessment</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">governanceAccount</span><span class="p">).</span><span class="nx">addAssessorsToGroup</span><span class="p">([</span><span class="mi">1</span><span class="nx">n</span><span class="p">,</span> <span class="mi">2</span><span class="nx">n</span><span class="p">],</span> <span class="nx">invalidGroupId</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="kr">await</span> <span class="nx">expect</span><span class="p">(</span><span class="nx">addAssessorsToGroup</span><span class="p">).</span><span class="nx">to</span><span class="p">.</span><span class="nx">be</span><span class="p">.</span><span class="nx">revertedWithCustomError</span><span class="p">(</span><span class="nx">assessment</span><span class="p">,</span> <span class="s1">'InvalidGroupId'</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="p">});</span>
</span></span></code></pre><h3 id="recommendation-6">Recommendation</h3>
<p>The function should require that the given <code>groupId</code> is equal to 0 or less than the <code>groupCount</code>; otherwise, revert if it is not.</p>
<h3 id="client-response-6">Client Response</h3>
<p>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/5f05f1a1ef1136b9fd41e835d92878bd9b4bb871">5f05f1a</a></p>
<h1 id="code-quality-improvement-suggestions">Code quality improvement suggestions</h1>
<p>Code improvement suggestions without security implications are listed below.</p>
<table class="codequality">
<thead>
<tr>
<th>#</th>
<th>Location</th>
<th>Details</th>
</tr>
</thead>
<tbody>
<tr>
<td>IO-NXM-PGR-005</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/SwapOperator.sol#L395">SwapOperator.sol#L395</a></td>
<td>The <code>receiver</code> parameter in <code>SwapOperator::recoverAsset(...)</code> is not validated to ensure it is a non-zero address. For supported assets, the <code>recipient</code> parameter is unused, and therefore, an AB member might expect that specifying a zero address is reasonable. However, if the pool doesn't support the asset or it has been abandoned without the knowledge of all AB members, the funds could be inadvertently transferred to the zero address.</td>
</tr>
<tr>
<td>IO-NXM-PGR-006</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L58">Governor.sol#L58</a>, <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L66">Governor.sol#L66</a></td>
<td>The <code>Governor::proposeAdvisoryBoardSwap(...)</code> and <code>Governor::propose</code> functions do not return the <code>proposalId</code> that is assigned, requiring members to rely on events to obtain the <code>proposalId</code>. This makes atomic proposals and voting difficult, increasing the chance that a proposal might be front-run and result in an unintended vote. In a worst-case scenario, a member might rely on the output from a simulation to create an atomic batch of transactions. A malicious actor could monitor the mempool for such an occurrence and front-run the proposal, causing the victim to inadvertently vote for the malicious actor's proposal instead of their own.</td>
</tr>
<tr>
<td>IO-NXM-PGR-007</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L66">Governor.sol#L66</a></td>
<td>To prevent proposals that fail at execution, <code>Governor::proposeAdvisoryBoardSwap(...)</code> should also validate that the <code>from</code> address is an existing AB member, and that the <code>to</code> address belongs to a normal member.</td>
</tr>
<tr>
<td>IO-NXM-PGR-008</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L174">Governor.sol#L174</a></td>
<td>When voting, the member's tokens are always locked for  <code>VOTING_PERIOD + TIMELOCK_PERIOD</code> seconds regardless of when their vote is cast. Consequently, members' tokens could be locked well after the timelock has already elapsed. Instead, the lock duration should be the difference between the timestamp when the vote is cast and the <code>executeAfter</code> timestamp of the proposal. This can be achieved by simply passing the <code>executeAfter</code> timestamp as the <code>deadline</code> argument to <code>_lockTokenTransfers</code>.</td>
</tr>
<tr>
<td>IO-NXM-PGR-009</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/NXMaster.sol#L35-L37">NXMaster.sol#L35-L37</a></td>
<td><code>NXMaster::isPause()</code> does not check whether migration has been completed and there is a valid instance of registry, similar to <code>NXMaster::isInternal()</code>. In such cases, the function could fall back to returning the last value of the <code>paused</code> storage variable.</td>
</tr>
<tr>
<td>IO-NXM-PGR-010</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/cover/LimitOrders.sol#L298">LimitOrders.sol#L298</a></td>
<td>The <code>LimitOrders</code> contract has not been updated following the changes to <code>TokenController</code> and therefore the <code>whitelistSelf()</code> function will always revert.</td>
</tr>
<tr>
<td>IO-NXM-PGR-011-1</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Registry.sol#L389">Registry.sol#L389</a></td>
<td><code>memberId</code> can be re-used instead of reloading the value from storage on <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Registry.sol#L389">Registry.sol#L389</a>.</td>
</tr>
<tr>
<td>IO-NXM-PGR-011-2</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/SwapOperator.sol#L368-L369">SwapOperator.sol#L368-L369</a></td>
<td>The checks on <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/SwapOperator.sol#L368-L369">SwapOperator.sol#L368-L369</a> could be performed earlier, before the cross-contract call to Pool.</td>
</tr>
<tr>
<td>IO-NXM-PGR-011-3</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/cover/Cover.sol#L624">Cover.sol#L624</a></td>
<td>The casting to address on <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/cover/Cover.sol#L624">Cover.sol#L624</a> can be removed as <code>stakingPoolFactory</code> is now an address</td>
</tr>
<tr>
<td>IO-NXM-PGR-012</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L203-L236">Governor.sol#L203-L236</a></td>
<td><code>Governor::execute()</code> does not validate whether the ETH sent in the call is not more than what is required to execute the proposal's transactions. Should the caller send too much ETH, the excess would be stuck in the contract. Add a check that requires `(isAbProposal</td>
</tr>
<tr>
<td>IO-NXM-PGR-013</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/assessment/Claims.sol#L240">Claims.sol#L240</a></td>
<td>To enable accurate tracking of claim deposits, the <code>redeemClaimPayout()</code> function should also emit <code>ClaimDepositRetrieved</code> if the deposit has not been retrieved previously.</td>
</tr>
<tr>
<td>IO-NXM-PGR-014</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/assessment/Claims.sol#L257">Claims.sol#L257</a>, <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/assessment/Claims.sol#L277">Claims.sol#L277</a>, <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/Pool.sol#L253">Pool.sol#L253</a></td>
<td>By reworking the <code>Pool::sendPayout()</code> function to only call <code>_updateMCR(true)</code> when <code>amount > 0</code>, <code>Claims::retrieveDeposit</code> can be be updated to use <code>Pool::sendPayout()</code> instead of <code>Pool::sendEth()</code>. This allows reducing the access control for <code>Pool::sendEth()</code> to <code>C_RAMM</code> only, ensuring clear access control separation. It is further recommended that <code>Pool::sendPayout()</code> performs a single value transfer when the payout asset is <code>ETH</code>, as opposed to individual calls for the deposit and for the payout amount.</td>
</tr>
<tr>
<td>IO-NXM-PGR-015</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/token/TokenController.sol#L94">TokenController.sol#L94</a></td>
<td>The modifier for <code>TokenController::burnFrom(...)</code> uses addition instead of a bitwise OR for its bit mask. This results in the same bitmask in this instance, but could be dangerous as a general pattern.</td>
</tr>
<tr>
<td>IO-NXM-PGR-016</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L151">Governor.sol#L151</a></td>
<td>The check on <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L151">Governor.sol#L151</a> is not necessary as <code>memberId</code> has already been verified to be non-zero on <a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L144">Governor.sol#L144</a> and <code>Registry::getAdvisoryBoardSeat()</code> <a href="https://github.com/NexusMutual/smart-contracts/blob/b6943cf7ca27212416e45a5a6b21ebf73bda2214/contracts/modules/governance/Registry.sol#L196">reverts</a> if <code>seat</code> is zero.</td>
</tr>
<tr>
<td>IO-NXM-PGR-017</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/capital/Pool.sol#L216-L235">Pool.sol#L216-L235</a></td>
<td>A asset transfer event similar to that emitted in <code>Pool::transferAssetToSafe()</code> could be added to <code>Pool::transferAssetToSwapOperator()</code>.</td>
</tr>
<tr>
<td>IO-NXM-PGR-018</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L170">Governor.sol#L170</a></td>
<td>A vote after an AB proposal's timelock has already been advanced will extend the timelock. <code>executeAfter</code> should be set to be the minimum between <code>block.timestamp + TIMELOCK_PERIOD</code> and the current <code>executeAfter</code>. Alternatively, <code>proposals[proposalId].voteBefore</code> should be set to the current <code>block.timestamp</code> in addition to setting <code>executeAfter</code>.</td>
</tr>
<tr>
<td>IO-NXM-PGR-023</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L211C2-L212C6">Govenor.sol#L211-212</a></td>
<td>In <code>Governor::execute(…)</code> the statements `require(isAbProposal</td>
</tr>
<tr>
<td>IO-NXM-PGR-020</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/Governor.sol#L153">Governor.sol#L153</a></td>
<td>Votes are tracked as <code>uint96</code>, which does not result in well-packed Vote or Tally structs.</td>
</tr>
<tr>
<td>IO-NXM-PGR-022</td>
<td><a href="https://github.com/NexusMutual/smart-contracts/blob/37884fb496af98848b1076142aaf27d42a789954/contracts/modules/governance/VotePower.sol">VotePower.sol</a></td>
<td>The <code>VotePower</code> contract is not referenced by any other contracts and therefore is not used in the current protocol implementation. This contract should be removed or added to legacy, as it is no longer required.</td>
</tr>
</tbody>
</table>
<h3 id="client-response-7">Client response</h3>
<dl>
<dt>IO-NXM-PGR-005</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/commit/03de8f52de72cd302cbf5fd72590f2ac9b117938">03de8f5</a>.</dd>
<dt>IO-NXM-PGR-006</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/9cff2072c5d085f55d65bff11f1966df14fbbbac">9cff207</a>.</dd>
<dt>IO-NXM-PGR-007</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/468e5f26222b0679615ba868551bfecbb9548d14">468e5f2</a>.</dd>
<dt>IO-NXM-PGR-008</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/b94d314f6206477822d4b6093dc9f23ee92783fb">b94d314</a>.</dd>
<dt>IO-NXM-PGR-009</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/8860cc4baece87c4ae2b884457045392f00ea5d1">8860cc4</a>.</dd>
<dt>IO-NXM-PGR-010</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/4ec0abf5242c8417af96d2eca983f873b7fae210">4ec0abf</a>.</dd>
<dt>IO-NXM-PGR-011-1</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/commit/7923d9f7fbb95a16a5b29617529bbd856f055c0b">7923d9f</a>.</dd>
<dt>IO-NXM-PGR-011-2</dt>
<dd>Closed.</dd>
<dt>IO-NXM-PGR-011-3</dt>
<dd>Closed.</dd>
<dt>IO-NXM-PGR-012</dt>
<dd>Closed.</dd>
<dt>IO-NXM-PGR-013</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/55e1bacbb6bffb778f354aba9c4a2a75cc51cc7f">55e1bac</a>.</dd>
<dt>IO-NXM-PGR-014</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/02e38d0f2f5dc7ebefe448d1c769bf2e8005152e">02e38d0</a>.</dd>
<dt>IO-NXM-PGR-015</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/ea1e623a580a7753dc8a1823a040f6710189e62b">ea1e623</a>.</dd>
<dt>IO-NXM-PGR-016</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/ff9ceb50f5fdab4f486137a282c990e118fc1d2d">ff9ceb5</a>.</dd>
<dt>IO-NXM-PGR-017</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/18eebde8b774695a1fd1cf16442ee1bf50ad8372">18eebde</a>.</dd>
<dt>IO-NXM-PGR-018</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1429/commits/30351eb9b7e3a1ad28d157d74103881b085ed0ec">30351eb</a>.</dd>
<dt>IO-NXM-PGR-023</dt>
<dd>Closed.</dd>
<dt>IO-NXM-PGR-020</dt>
<dd>Closed.</dd>
<dt>IO-NXM-PGR-022</dt>
<dd>Fixed in <a href="https://github.com/NexusMutual/smart-contracts/pull/1457/commits/080c188195bc3d0b335230db9f8a4a1e08f52f17">080c188</a> and <a href="https://github.com/NexusMutual/smart-contracts/pull/1457/commits/8c4475889d76a45df34da9531303f7e5be535288">8c44758</a>.</dd>
</dl>
<h1 id="specification">Specification</h1>
<p>The following section outlines the system's intended functionality at a high level, based on its implementation in the codebase. Any perceived points of conflict should be highlighted with the auditing team to determine the source of the discrepancy.</p>
<h2 id="governance">Governance</h2>
<p>Nexus Mutual have migrated to a new governance system with the introduction of the Governor contract and the deprecation of the previous Governance contract. The new system allows for the submission of two types of proposals:</p>
<p>Advisory Board (AB) Proposals, which can execute one or more arbitrary transactions, and proposals to swap Advisory Board members.</p>
<p>AB Proposals can only be submitted by advisory board members, whereas proposals to swap advisory board members can be submitted by any member of the mutual, provided they hold a minimum of 100 NXM tokens at the time of proposal submission.</p>
<p>AB proposals can only be voted on by AB members, each of whom have a single vote, whereas AB swap proposals can be voted on by any member, with their vote power being equal to their NXM token balance, capped to 5% of the total supply at the time of voting.</p>
<p>AB and AB swap proposals are considered passed through a simple majority, provided a quorum is reached – quorum requirements for AB proposals are three out of the five AB seats, while AB swap proposals require approximately 15% of the total supply as quorum for a vote to be passed. Voting periods are three days for all proposals. Once a proposal is passed, it enters a time lock period of one day before it can be executed.</p>
<p>Similar to the previous governance system, staking pool managers can vote on behalf of stakers through their delegated NXM in AB swap proposals, with their vote weight also capped to 5%. In AB swap proposals, NXM token transfers are locked after voting and until the time lock period has passed to prevent double voting.</p>
<h2 id="registry">Registry</h2>
<p>A Registry contract was introduced to replace the NXMaster and Member Roles contracts. The Registry is meant to serve as a central point of truth for current members, advisory board members, and their respective member IDs and seat numbers. To this end, the Registry also exposes functionality for new members to join the mutual, once they have completed the off-chain KYC process and have a join request signed by the KYC authentication address. Additionally, member access control checks across the protocol are now routed to the Registry.</p>
<p>The Registry also serves as the central directory for all internal contracts in the protocol, allowing contracts to query the addresses of other internal contracts through a contract index system, and limit access to privileged functions to specific internal contracts. New contracts can be added and upgraded through Registry, after an AB governance proposal has been passed to do so.</p>
<h2 id="assessments">Assessments</h2>
<p>The new Assessment module implements a permissioned assessor model where only Governance-approved assessors can participate in claim voting. Assessors are organized into assessment groups, with each product type assigned to a specific group. The Advisory Board, via governance proposals, manages the assessor groups by adding and removing members and setting product-type parameters, including cooldown periods, redemption periods, and assessment group assignments.</p>
<p>Each member of an assessment group has one vote. The default voting period is 72 hours, which can end early if all assessors in the group have voted. After voting concludes, a configurable cooldown period begins during which Governance can investigate potential fraud, extend voting periods, or undo fraudulent votes. Claims are decided by majority vote, with no minimum participation requirement – a single vote can approve a claim if no other votes are cast. Draw outcomes result in no payout but allow claimants to retrieve their deposit.</p>
<p>The Advisory Board can pause assessments, extend voting periods by 72 hours, and explicitly undo votes. Votes from assessors removed mid-assessment remain valid unless explicitly undone by an Advisory Board proposal.</p>
<h3 id="migration">Migration</h3>
<p>The migration process upgrades the Nexus Mutual governance system to a new architecture while ensuring compatibility with legacy contracts. It begins with deploying the Registry implementation and proxy contracts, transferring ownership to the Advisory Board (AB) multisig, and deploying temporary contract implementations such as TemporaryGovernance, LegacyAssessment, and LegacyMemberRoles.</p>
<p>The first AB actions involve upgrading the Governance contract to use TemporaryGovernance, upgrading Assessment and MemberRoles to their legacy implementations, and migrating the Registry to upgrade the Governor to TemporaryGovernance. Next, member data is migrated, ETH is recovered from MemberRoles, legacy assessment stakes and rewards are pushed, and new contract implementations for modules like Pool, SwapOperator, Ramm, SafeTracker, Assessments, Claims, TokenController, Cover, CoverProducts, and Governor are deployed.</p>
<p>The last phase involves upgrading the proxies of these contracts to the new implementations, setting emergency admin addresses, initialising the Claims contract, migrating the Pool and Master contracts to transfer assets and funds, transferring ownership of the Registry proxy to the Governor, and establishing assessment groups for product types. Finally, the Governor is upgraded to its new implementation, and the existing CoverProduct product types are updated with new parameters.</p>
<h3 id="swap-operator">Swap Operator</h3>
<p>The <code>SwapOperator</code> contract has been updated to function as a proxy, enabling easier upgrades and maintenance. The contract is used by a <code>swapController</code> address, which is set by the advisory board.</p>
<p>The previous slippage checks have been removed, simplifying the swap execution process. A new swap request feature has been introduced, allowing the Governor, through an AB proposal, to define and manage asset swaps with specific parameters such as the source asset, target asset, amounts, and deadlines. These swaps are then executed by the <code>swapController</code>.</p>
<p>The contract integrates with the CoW protocol for asset swaps and includes validations for asset compatibility, deadlines, and amounts. Additionally, the contract supports asset recovery to the pool or a specified receiver, ensuring no ongoing CoW swap orders during recovery operations. Swapping Enzyme vault shares for ETH and vice versa is also supported.</p>
<h1 id="test-coverage-report">Test coverage report</h1>
<p>The coverage report of the provided tests as of 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>Assessments.sol</td>
<td>99.02%</td>
<td>98.7%</td>
<td>98.44%</td>
<td>95.65%</td>
</tr>
<tr>
<td>Claims.sol</td>
<td>100.00%</td>
<td>100.00%</td>
<td>92.00%</td>
<td>100.00%</td>
</tr>
<tr>
<td>Pool.sol</td>
<td>93.63%</td>
<td>95.24%</td>
<td>76.27%</td>
<td>96.30%</td>
</tr>
<tr>
<td>Ramm.sol</td>
<td>49.42%</td>
<td>50.54%</td>
<td>36.27%</td>
<td>57.14%</td>
</tr>
<tr>
<td>SafeTracker.sol</td>
<td>53.33%</td>
<td>40.91%</td>
<td>11.11%</td>
<td>33.33%</td>
</tr>
<tr>
<td>SwapOperator.sol</td>
<td>100.00%</td>
<td>100.00%</td>
<td>98.08%</td>
<td>100.00%</td>
</tr>
<tr>
<td>Governor.sol</td>
<td>91.75%</td>
<td>92.41%</td>
<td>93.90%</td>
<td>75.00%</td>
</tr>
<tr>
<td>NXMaster.sol</td>
<td>15.79%</td>
<td>17.65%</td>
<td>45.65%</td>
<td>33.33%</td>
</tr>
<tr>
<td>Registry.sol</td>
<td>80.72%</td>
<td>78.13%</td>
<td>88.79%</td>
<td>90.48%</td>
</tr>
<tr>
<td>TemporaryGovernance.sol</td>
<td>11.11%</td>
<td>0.00%</td>
<td>0.00%</td>
<td>25.00%</td>
</tr>
<tr>
<td>UpgradeableProxy.sol</td>
<td>100.00%</td>
<td>100.00%</td>
<td>60.00%</td>
<td>100.00%</td>
</tr>
<tr>
<td>StakingProducts.sol</td>
<td>60.71%</td>
<td>61.86%</td>
<td>42.42%</td>
<td>55.56%</td>
</tr>
<tr>
<td>TokenController.sol</td>
<td>96.70%</td>
<td>95.71%</td>
<td>96.77%</td>
<td>96.97%</td>
</tr>
<tr>
<td>All files</td>
<td>56.32%</td>
<td>56.45%</td>
<td>49.28%</td>
<td>55.92%</td>
</tr>
</tbody>
</table>
<p>The in-scope source files demonstrated strong test coverage for the primary use cases. To further enhance robustness, expanding coverage to edge cases and less-tested modules is recommended.</p>

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

Secure your system.
Request a service
Start Now