diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..db0964493 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,13 @@ +.yarn/cache +.yarn/install-state.gz + +contracts/.env +contracts/test +contracts/lib +contracts/cache +contracts/cache_hardhat +contracts/config +contracts/tenderly.yaml + +*/.DS_Store +*/*.log \ No newline at end of file diff --git a/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs b/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs new file mode 100644 index 000000000..fc27b01d3 --- /dev/null +++ b/.yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs @@ -0,0 +1,28 @@ +/* eslint-disable */ +//prettier-ignore +module.exports = { +name: "@yarnpkg/plugin-workspace-tools", +factory: function (require) { +var plugin=(()=>{var _r=Object.create;var we=Object.defineProperty;var Er=Object.getOwnPropertyDescriptor;var br=Object.getOwnPropertyNames;var xr=Object.getPrototypeOf,Cr=Object.prototype.hasOwnProperty;var W=(e=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(e,{get:(r,t)=>(typeof require<"u"?require:r)[t]}):e)(function(e){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+e+'" is not supported')});var q=(e,r)=>()=>(r||e((r={exports:{}}).exports,r),r.exports),wr=(e,r)=>{for(var t in r)we(e,t,{get:r[t],enumerable:!0})},Je=(e,r,t,n)=>{if(r&&typeof r=="object"||typeof r=="function")for(let s of br(r))!Cr.call(e,s)&&s!==t&&we(e,s,{get:()=>r[s],enumerable:!(n=Er(r,s))||n.enumerable});return e};var Be=(e,r,t)=>(t=e!=null?_r(xr(e)):{},Je(r||!e||!e.__esModule?we(t,"default",{value:e,enumerable:!0}):t,e)),Sr=e=>Je(we({},"__esModule",{value:!0}),e);var ve=q(ee=>{"use strict";ee.isInteger=e=>typeof e=="number"?Number.isInteger(e):typeof e=="string"&&e.trim()!==""?Number.isInteger(Number(e)):!1;ee.find=(e,r)=>e.nodes.find(t=>t.type===r);ee.exceedsLimit=(e,r,t=1,n)=>n===!1||!ee.isInteger(e)||!ee.isInteger(r)?!1:(Number(r)-Number(e))/Number(t)>=n;ee.escapeNode=(e,r=0,t)=>{let n=e.nodes[r];!n||(t&&n.type===t||n.type==="open"||n.type==="close")&&n.escaped!==!0&&(n.value="\\"+n.value,n.escaped=!0)};ee.encloseBrace=e=>e.type!=="brace"?!1:e.commas>>0+e.ranges>>0===0?(e.invalid=!0,!0):!1;ee.isInvalidBrace=e=>e.type!=="brace"?!1:e.invalid===!0||e.dollar?!0:e.commas>>0+e.ranges>>0===0||e.open!==!0||e.close!==!0?(e.invalid=!0,!0):!1;ee.isOpenOrClose=e=>e.type==="open"||e.type==="close"?!0:e.open===!0||e.close===!0;ee.reduce=e=>e.reduce((r,t)=>(t.type==="text"&&r.push(t.value),t.type==="range"&&(t.type="text"),r),[]);ee.flatten=(...e)=>{let r=[],t=n=>{for(let s=0;s{"use strict";var tt=ve();rt.exports=(e,r={})=>{let t=(n,s={})=>{let i=r.escapeInvalid&&tt.isInvalidBrace(s),a=n.invalid===!0&&r.escapeInvalid===!0,c="";if(n.value)return(i||a)&&tt.isOpenOrClose(n)?"\\"+n.value:n.value;if(n.value)return n.value;if(n.nodes)for(let p of n.nodes)c+=t(p);return c};return t(e)}});var st=q((Jn,nt)=>{"use strict";nt.exports=function(e){return typeof e=="number"?e-e===0:typeof e=="string"&&e.trim()!==""?Number.isFinite?Number.isFinite(+e):isFinite(+e):!1}});var ht=q((es,pt)=>{"use strict";var at=st(),le=(e,r,t)=>{if(at(e)===!1)throw new TypeError("toRegexRange: expected the first argument to be a number");if(r===void 0||e===r)return String(e);if(at(r)===!1)throw new TypeError("toRegexRange: expected the second argument to be a number.");let n={relaxZeros:!0,...t};typeof n.strictZeros=="boolean"&&(n.relaxZeros=n.strictZeros===!1);let s=String(n.relaxZeros),i=String(n.shorthand),a=String(n.capture),c=String(n.wrap),p=e+":"+r+"="+s+i+a+c;if(le.cache.hasOwnProperty(p))return le.cache[p].result;let m=Math.min(e,r),h=Math.max(e,r);if(Math.abs(m-h)===1){let y=e+"|"+r;return n.capture?`(${y})`:n.wrap===!1?y:`(?:${y})`}let R=ft(e)||ft(r),f={min:e,max:r,a:m,b:h},$=[],_=[];if(R&&(f.isPadded=R,f.maxLen=String(f.max).length),m<0){let y=h<0?Math.abs(h):1;_=it(y,Math.abs(m),f,n),m=f.a=0}return h>=0&&($=it(m,h,f,n)),f.negatives=_,f.positives=$,f.result=vr(_,$,n),n.capture===!0?f.result=`(${f.result})`:n.wrap!==!1&&$.length+_.length>1&&(f.result=`(?:${f.result})`),le.cache[p]=f,f.result};function vr(e,r,t){let n=Me(e,r,"-",!1,t)||[],s=Me(r,e,"",!1,t)||[],i=Me(e,r,"-?",!0,t)||[];return n.concat(i).concat(s).join("|")}function Hr(e,r){let t=1,n=1,s=ut(e,t),i=new Set([r]);for(;e<=s&&s<=r;)i.add(s),t+=1,s=ut(e,t);for(s=ct(r+1,n)-1;e1&&c.count.pop(),c.count.push(h.count[0]),c.string=c.pattern+lt(c.count),a=m+1;continue}t.isPadded&&(R=Or(m,t,n)),h.string=R+h.pattern+lt(h.count),i.push(h),a=m+1,c=h}return i}function Me(e,r,t,n,s){let i=[];for(let a of e){let{string:c}=a;!n&&!ot(r,"string",c)&&i.push(t+c),n&&ot(r,"string",c)&&i.push(t+c)}return i}function Tr(e,r){let t=[];for(let n=0;nr?1:r>e?-1:0}function ot(e,r,t){return e.some(n=>n[r]===t)}function ut(e,r){return Number(String(e).slice(0,-r)+"9".repeat(r))}function ct(e,r){return e-e%Math.pow(10,r)}function lt(e){let[r=0,t=""]=e;return t||r>1?`{${r+(t?","+t:"")}}`:""}function Lr(e,r,t){return`[${e}${r-e===1?"":"-"}${r}]`}function ft(e){return/^-?(0+)\d/.test(e)}function Or(e,r,t){if(!r.isPadded)return e;let n=Math.abs(r.maxLen-String(e).length),s=t.relaxZeros!==!1;switch(n){case 0:return"";case 1:return s?"0?":"0";case 2:return s?"0{0,2}":"00";default:return s?`0{0,${n}}`:`0{${n}}`}}le.cache={};le.clearCache=()=>le.cache={};pt.exports=le});var Ue=q((ts,Et)=>{"use strict";var Nr=W("util"),At=ht(),dt=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),Ir=e=>r=>e===!0?Number(r):String(r),Pe=e=>typeof e=="number"||typeof e=="string"&&e!=="",Ae=e=>Number.isInteger(+e),De=e=>{let r=`${e}`,t=-1;if(r[0]==="-"&&(r=r.slice(1)),r==="0")return!1;for(;r[++t]==="0";);return t>0},Br=(e,r,t)=>typeof e=="string"||typeof r=="string"?!0:t.stringify===!0,Mr=(e,r,t)=>{if(r>0){let n=e[0]==="-"?"-":"";n&&(e=e.slice(1)),e=n+e.padStart(n?r-1:r,"0")}return t===!1?String(e):e},gt=(e,r)=>{let t=e[0]==="-"?"-":"";for(t&&(e=e.slice(1),r--);e.length{e.negatives.sort((a,c)=>ac?1:0),e.positives.sort((a,c)=>ac?1:0);let t=r.capture?"":"?:",n="",s="",i;return e.positives.length&&(n=e.positives.join("|")),e.negatives.length&&(s=`-(${t}${e.negatives.join("|")})`),n&&s?i=`${n}|${s}`:i=n||s,r.wrap?`(${t}${i})`:i},mt=(e,r,t,n)=>{if(t)return At(e,r,{wrap:!1,...n});let s=String.fromCharCode(e);if(e===r)return s;let i=String.fromCharCode(r);return`[${s}-${i}]`},Rt=(e,r,t)=>{if(Array.isArray(e)){let n=t.wrap===!0,s=t.capture?"":"?:";return n?`(${s}${e.join("|")})`:e.join("|")}return At(e,r,t)},yt=(...e)=>new RangeError("Invalid range arguments: "+Nr.inspect(...e)),_t=(e,r,t)=>{if(t.strictRanges===!0)throw yt([e,r]);return[]},Dr=(e,r)=>{if(r.strictRanges===!0)throw new TypeError(`Expected step "${e}" to be a number`);return[]},Ur=(e,r,t=1,n={})=>{let s=Number(e),i=Number(r);if(!Number.isInteger(s)||!Number.isInteger(i)){if(n.strictRanges===!0)throw yt([e,r]);return[]}s===0&&(s=0),i===0&&(i=0);let a=s>i,c=String(e),p=String(r),m=String(t);t=Math.max(Math.abs(t),1);let h=De(c)||De(p)||De(m),R=h?Math.max(c.length,p.length,m.length):0,f=h===!1&&Br(e,r,n)===!1,$=n.transform||Ir(f);if(n.toRegex&&t===1)return mt(gt(e,R),gt(r,R),!0,n);let _={negatives:[],positives:[]},y=T=>_[T<0?"negatives":"positives"].push(Math.abs(T)),E=[],S=0;for(;a?s>=i:s<=i;)n.toRegex===!0&&t>1?y(s):E.push(Mr($(s,S),R,f)),s=a?s-t:s+t,S++;return n.toRegex===!0?t>1?Pr(_,n):Rt(E,null,{wrap:!1,...n}):E},Gr=(e,r,t=1,n={})=>{if(!Ae(e)&&e.length>1||!Ae(r)&&r.length>1)return _t(e,r,n);let s=n.transform||(f=>String.fromCharCode(f)),i=`${e}`.charCodeAt(0),a=`${r}`.charCodeAt(0),c=i>a,p=Math.min(i,a),m=Math.max(i,a);if(n.toRegex&&t===1)return mt(p,m,!1,n);let h=[],R=0;for(;c?i>=a:i<=a;)h.push(s(i,R)),i=c?i-t:i+t,R++;return n.toRegex===!0?Rt(h,null,{wrap:!1,options:n}):h},$e=(e,r,t,n={})=>{if(r==null&&Pe(e))return[e];if(!Pe(e)||!Pe(r))return _t(e,r,n);if(typeof t=="function")return $e(e,r,1,{transform:t});if(dt(t))return $e(e,r,0,t);let s={...n};return s.capture===!0&&(s.wrap=!0),t=t||s.step||1,Ae(t)?Ae(e)&&Ae(r)?Ur(e,r,t,s):Gr(e,r,Math.max(Math.abs(t),1),s):t!=null&&!dt(t)?Dr(t,s):$e(e,r,1,t)};Et.exports=$e});var Ct=q((rs,xt)=>{"use strict";var qr=Ue(),bt=ve(),Kr=(e,r={})=>{let t=(n,s={})=>{let i=bt.isInvalidBrace(s),a=n.invalid===!0&&r.escapeInvalid===!0,c=i===!0||a===!0,p=r.escapeInvalid===!0?"\\":"",m="";if(n.isOpen===!0||n.isClose===!0)return p+n.value;if(n.type==="open")return c?p+n.value:"(";if(n.type==="close")return c?p+n.value:")";if(n.type==="comma")return n.prev.type==="comma"?"":c?n.value:"|";if(n.value)return n.value;if(n.nodes&&n.ranges>0){let h=bt.reduce(n.nodes),R=qr(...h,{...r,wrap:!1,toRegex:!0});if(R.length!==0)return h.length>1&&R.length>1?`(${R})`:R}if(n.nodes)for(let h of n.nodes)m+=t(h,n);return m};return t(e)};xt.exports=Kr});var vt=q((ns,St)=>{"use strict";var Wr=Ue(),wt=He(),he=ve(),fe=(e="",r="",t=!1)=>{let n=[];if(e=[].concat(e),r=[].concat(r),!r.length)return e;if(!e.length)return t?he.flatten(r).map(s=>`{${s}}`):r;for(let s of e)if(Array.isArray(s))for(let i of s)n.push(fe(i,r,t));else for(let i of r)t===!0&&typeof i=="string"&&(i=`{${i}}`),n.push(Array.isArray(i)?fe(s,i,t):s+i);return he.flatten(n)},jr=(e,r={})=>{let t=r.rangeLimit===void 0?1e3:r.rangeLimit,n=(s,i={})=>{s.queue=[];let a=i,c=i.queue;for(;a.type!=="brace"&&a.type!=="root"&&a.parent;)a=a.parent,c=a.queue;if(s.invalid||s.dollar){c.push(fe(c.pop(),wt(s,r)));return}if(s.type==="brace"&&s.invalid!==!0&&s.nodes.length===2){c.push(fe(c.pop(),["{}"]));return}if(s.nodes&&s.ranges>0){let R=he.reduce(s.nodes);if(he.exceedsLimit(...R,r.step,t))throw new RangeError("expanded array length exceeds range limit. Use options.rangeLimit to increase or disable the limit.");let f=Wr(...R,r);f.length===0&&(f=wt(s,r)),c.push(fe(c.pop(),f)),s.nodes=[];return}let p=he.encloseBrace(s),m=s.queue,h=s;for(;h.type!=="brace"&&h.type!=="root"&&h.parent;)h=h.parent,m=h.queue;for(let R=0;R{"use strict";Ht.exports={MAX_LENGTH:1024*64,CHAR_0:"0",CHAR_9:"9",CHAR_UPPERCASE_A:"A",CHAR_LOWERCASE_A:"a",CHAR_UPPERCASE_Z:"Z",CHAR_LOWERCASE_Z:"z",CHAR_LEFT_PARENTHESES:"(",CHAR_RIGHT_PARENTHESES:")",CHAR_ASTERISK:"*",CHAR_AMPERSAND:"&",CHAR_AT:"@",CHAR_BACKSLASH:"\\",CHAR_BACKTICK:"`",CHAR_CARRIAGE_RETURN:"\r",CHAR_CIRCUMFLEX_ACCENT:"^",CHAR_COLON:":",CHAR_COMMA:",",CHAR_DOLLAR:"$",CHAR_DOT:".",CHAR_DOUBLE_QUOTE:'"',CHAR_EQUAL:"=",CHAR_EXCLAMATION_MARK:"!",CHAR_FORM_FEED:"\f",CHAR_FORWARD_SLASH:"/",CHAR_HASH:"#",CHAR_HYPHEN_MINUS:"-",CHAR_LEFT_ANGLE_BRACKET:"<",CHAR_LEFT_CURLY_BRACE:"{",CHAR_LEFT_SQUARE_BRACKET:"[",CHAR_LINE_FEED:` +`,CHAR_NO_BREAK_SPACE:"\xA0",CHAR_PERCENT:"%",CHAR_PLUS:"+",CHAR_QUESTION_MARK:"?",CHAR_RIGHT_ANGLE_BRACKET:">",CHAR_RIGHT_CURLY_BRACE:"}",CHAR_RIGHT_SQUARE_BRACKET:"]",CHAR_SEMICOLON:";",CHAR_SINGLE_QUOTE:"'",CHAR_SPACE:" ",CHAR_TAB:" ",CHAR_UNDERSCORE:"_",CHAR_VERTICAL_LINE:"|",CHAR_ZERO_WIDTH_NOBREAK_SPACE:"\uFEFF"}});var Nt=q((as,Ot)=>{"use strict";var Fr=He(),{MAX_LENGTH:Tt,CHAR_BACKSLASH:Ge,CHAR_BACKTICK:Qr,CHAR_COMMA:Xr,CHAR_DOT:Zr,CHAR_LEFT_PARENTHESES:Yr,CHAR_RIGHT_PARENTHESES:zr,CHAR_LEFT_CURLY_BRACE:Vr,CHAR_RIGHT_CURLY_BRACE:Jr,CHAR_LEFT_SQUARE_BRACKET:kt,CHAR_RIGHT_SQUARE_BRACKET:Lt,CHAR_DOUBLE_QUOTE:en,CHAR_SINGLE_QUOTE:tn,CHAR_NO_BREAK_SPACE:rn,CHAR_ZERO_WIDTH_NOBREAK_SPACE:nn}=$t(),sn=(e,r={})=>{if(typeof e!="string")throw new TypeError("Expected a string");let t=r||{},n=typeof t.maxLength=="number"?Math.min(Tt,t.maxLength):Tt;if(e.length>n)throw new SyntaxError(`Input length (${e.length}), exceeds max characters (${n})`);let s={type:"root",input:e,nodes:[]},i=[s],a=s,c=s,p=0,m=e.length,h=0,R=0,f,$={},_=()=>e[h++],y=E=>{if(E.type==="text"&&c.type==="dot"&&(c.type="text"),c&&c.type==="text"&&E.type==="text"){c.value+=E.value;return}return a.nodes.push(E),E.parent=a,E.prev=c,c=E,E};for(y({type:"bos"});h0){if(a.ranges>0){a.ranges=0;let E=a.nodes.shift();a.nodes=[E,{type:"text",value:Fr(a)}]}y({type:"comma",value:f}),a.commas++;continue}if(f===Zr&&R>0&&a.commas===0){let E=a.nodes;if(R===0||E.length===0){y({type:"text",value:f});continue}if(c.type==="dot"){if(a.range=[],c.value+=f,c.type="range",a.nodes.length!==3&&a.nodes.length!==5){a.invalid=!0,a.ranges=0,c.type="text";continue}a.ranges++,a.args=[];continue}if(c.type==="range"){E.pop();let S=E[E.length-1];S.value+=c.value+f,c=S,a.ranges--;continue}y({type:"dot",value:f});continue}y({type:"text",value:f})}do if(a=i.pop(),a.type!=="root"){a.nodes.forEach(T=>{T.nodes||(T.type==="open"&&(T.isOpen=!0),T.type==="close"&&(T.isClose=!0),T.nodes||(T.type="text"),T.invalid=!0)});let E=i[i.length-1],S=E.nodes.indexOf(a);E.nodes.splice(S,1,...a.nodes)}while(i.length>0);return y({type:"eos"}),s};Ot.exports=sn});var Mt=q((is,Bt)=>{"use strict";var It=He(),an=Ct(),on=vt(),un=Nt(),X=(e,r={})=>{let t=[];if(Array.isArray(e))for(let n of e){let s=X.create(n,r);Array.isArray(s)?t.push(...s):t.push(s)}else t=[].concat(X.create(e,r));return r&&r.expand===!0&&r.nodupes===!0&&(t=[...new Set(t)]),t};X.parse=(e,r={})=>un(e,r);X.stringify=(e,r={})=>It(typeof e=="string"?X.parse(e,r):e,r);X.compile=(e,r={})=>(typeof e=="string"&&(e=X.parse(e,r)),an(e,r));X.expand=(e,r={})=>{typeof e=="string"&&(e=X.parse(e,r));let t=on(e,r);return r.noempty===!0&&(t=t.filter(Boolean)),r.nodupes===!0&&(t=[...new Set(t)]),t};X.create=(e,r={})=>e===""||e.length<3?[e]:r.expand!==!0?X.compile(e,r):X.expand(e,r);Bt.exports=X});var me=q((os,qt)=>{"use strict";var cn=W("path"),se="\\\\/",Pt=`[^${se}]`,ie="\\.",ln="\\+",fn="\\?",Te="\\/",pn="(?=.)",Dt="[^/]",qe=`(?:${Te}|$)`,Ut=`(?:^|${Te})`,Ke=`${ie}{1,2}${qe}`,hn=`(?!${ie})`,dn=`(?!${Ut}${Ke})`,gn=`(?!${ie}{0,1}${qe})`,An=`(?!${Ke})`,mn=`[^.${Te}]`,Rn=`${Dt}*?`,Gt={DOT_LITERAL:ie,PLUS_LITERAL:ln,QMARK_LITERAL:fn,SLASH_LITERAL:Te,ONE_CHAR:pn,QMARK:Dt,END_ANCHOR:qe,DOTS_SLASH:Ke,NO_DOT:hn,NO_DOTS:dn,NO_DOT_SLASH:gn,NO_DOTS_SLASH:An,QMARK_NO_DOT:mn,STAR:Rn,START_ANCHOR:Ut},yn={...Gt,SLASH_LITERAL:`[${se}]`,QMARK:Pt,STAR:`${Pt}*?`,DOTS_SLASH:`${ie}{1,2}(?:[${se}]|$)`,NO_DOT:`(?!${ie})`,NO_DOTS:`(?!(?:^|[${se}])${ie}{1,2}(?:[${se}]|$))`,NO_DOT_SLASH:`(?!${ie}{0,1}(?:[${se}]|$))`,NO_DOTS_SLASH:`(?!${ie}{1,2}(?:[${se}]|$))`,QMARK_NO_DOT:`[^.${se}]`,START_ANCHOR:`(?:^|[${se}])`,END_ANCHOR:`(?:[${se}]|$)`},_n={alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};qt.exports={MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:_n,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,SEP:cn.sep,extglobChars(e){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${e.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(e){return e===!0?yn:Gt}}});var Re=q(F=>{"use strict";var En=W("path"),bn=process.platform==="win32",{REGEX_BACKSLASH:xn,REGEX_REMOVE_BACKSLASH:Cn,REGEX_SPECIAL_CHARS:wn,REGEX_SPECIAL_CHARS_GLOBAL:Sn}=me();F.isObject=e=>e!==null&&typeof e=="object"&&!Array.isArray(e);F.hasRegexChars=e=>wn.test(e);F.isRegexChar=e=>e.length===1&&F.hasRegexChars(e);F.escapeRegex=e=>e.replace(Sn,"\\$1");F.toPosixSlashes=e=>e.replace(xn,"/");F.removeBackslashes=e=>e.replace(Cn,r=>r==="\\"?"":r);F.supportsLookbehinds=()=>{let e=process.version.slice(1).split(".").map(Number);return e.length===3&&e[0]>=9||e[0]===8&&e[1]>=10};F.isWindows=e=>e&&typeof e.windows=="boolean"?e.windows:bn===!0||En.sep==="\\";F.escapeLast=(e,r,t)=>{let n=e.lastIndexOf(r,t);return n===-1?e:e[n-1]==="\\"?F.escapeLast(e,r,n-1):`${e.slice(0,n)}\\${e.slice(n)}`};F.removePrefix=(e,r={})=>{let t=e;return t.startsWith("./")&&(t=t.slice(2),r.prefix="./"),t};F.wrapOutput=(e,r={},t={})=>{let n=t.contains?"":"^",s=t.contains?"":"$",i=`${n}(?:${e})${s}`;return r.negated===!0&&(i=`(?:^(?!${i}).*$)`),i}});var Yt=q((cs,Zt)=>{"use strict";var Kt=Re(),{CHAR_ASTERISK:We,CHAR_AT:vn,CHAR_BACKWARD_SLASH:ye,CHAR_COMMA:Hn,CHAR_DOT:je,CHAR_EXCLAMATION_MARK:Fe,CHAR_FORWARD_SLASH:Xt,CHAR_LEFT_CURLY_BRACE:Qe,CHAR_LEFT_PARENTHESES:Xe,CHAR_LEFT_SQUARE_BRACKET:$n,CHAR_PLUS:Tn,CHAR_QUESTION_MARK:Wt,CHAR_RIGHT_CURLY_BRACE:kn,CHAR_RIGHT_PARENTHESES:jt,CHAR_RIGHT_SQUARE_BRACKET:Ln}=me(),Ft=e=>e===Xt||e===ye,Qt=e=>{e.isPrefix!==!0&&(e.depth=e.isGlobstar?1/0:1)},On=(e,r)=>{let t=r||{},n=e.length-1,s=t.parts===!0||t.scanToEnd===!0,i=[],a=[],c=[],p=e,m=-1,h=0,R=0,f=!1,$=!1,_=!1,y=!1,E=!1,S=!1,T=!1,L=!1,z=!1,I=!1,re=0,K,g,v={value:"",depth:0,isGlob:!1},k=()=>m>=n,l=()=>p.charCodeAt(m+1),H=()=>(K=g,p.charCodeAt(++m));for(;m0&&(B=p.slice(0,h),p=p.slice(h),R-=h),w&&_===!0&&R>0?(w=p.slice(0,R),o=p.slice(R)):_===!0?(w="",o=p):w=p,w&&w!==""&&w!=="/"&&w!==p&&Ft(w.charCodeAt(w.length-1))&&(w=w.slice(0,-1)),t.unescape===!0&&(o&&(o=Kt.removeBackslashes(o)),w&&T===!0&&(w=Kt.removeBackslashes(w)));let u={prefix:B,input:e,start:h,base:w,glob:o,isBrace:f,isBracket:$,isGlob:_,isExtglob:y,isGlobstar:E,negated:L,negatedExtglob:z};if(t.tokens===!0&&(u.maxDepth=0,Ft(g)||a.push(v),u.tokens=a),t.parts===!0||t.tokens===!0){let M;for(let b=0;b{"use strict";var ke=me(),Z=Re(),{MAX_LENGTH:Le,POSIX_REGEX_SOURCE:Nn,REGEX_NON_SPECIAL_CHARS:In,REGEX_SPECIAL_CHARS_BACKREF:Bn,REPLACEMENTS:zt}=ke,Mn=(e,r)=>{if(typeof r.expandRange=="function")return r.expandRange(...e,r);e.sort();let t=`[${e.join("-")}]`;try{new RegExp(t)}catch{return e.map(s=>Z.escapeRegex(s)).join("..")}return t},de=(e,r)=>`Missing ${e}: "${r}" - use "\\\\${r}" to match literal characters`,Vt=(e,r)=>{if(typeof e!="string")throw new TypeError("Expected a string");e=zt[e]||e;let t={...r},n=typeof t.maxLength=="number"?Math.min(Le,t.maxLength):Le,s=e.length;if(s>n)throw new SyntaxError(`Input length: ${s}, exceeds maximum allowed length: ${n}`);let i={type:"bos",value:"",output:t.prepend||""},a=[i],c=t.capture?"":"?:",p=Z.isWindows(r),m=ke.globChars(p),h=ke.extglobChars(m),{DOT_LITERAL:R,PLUS_LITERAL:f,SLASH_LITERAL:$,ONE_CHAR:_,DOTS_SLASH:y,NO_DOT:E,NO_DOT_SLASH:S,NO_DOTS_SLASH:T,QMARK:L,QMARK_NO_DOT:z,STAR:I,START_ANCHOR:re}=m,K=A=>`(${c}(?:(?!${re}${A.dot?y:R}).)*?)`,g=t.dot?"":E,v=t.dot?L:z,k=t.bash===!0?K(t):I;t.capture&&(k=`(${k})`),typeof t.noext=="boolean"&&(t.noextglob=t.noext);let l={input:e,index:-1,start:0,dot:t.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:a};e=Z.removePrefix(e,l),s=e.length;let H=[],w=[],B=[],o=i,u,M=()=>l.index===s-1,b=l.peek=(A=1)=>e[l.index+A],V=l.advance=()=>e[++l.index]||"",J=()=>e.slice(l.index+1),Q=(A="",O=0)=>{l.consumed+=A,l.index+=O},Ee=A=>{l.output+=A.output!=null?A.output:A.value,Q(A.value)},Rr=()=>{let A=1;for(;b()==="!"&&(b(2)!=="("||b(3)==="?");)V(),l.start++,A++;return A%2===0?!1:(l.negated=!0,l.start++,!0)},be=A=>{l[A]++,B.push(A)},oe=A=>{l[A]--,B.pop()},C=A=>{if(o.type==="globstar"){let O=l.braces>0&&(A.type==="comma"||A.type==="brace"),d=A.extglob===!0||H.length&&(A.type==="pipe"||A.type==="paren");A.type!=="slash"&&A.type!=="paren"&&!O&&!d&&(l.output=l.output.slice(0,-o.output.length),o.type="star",o.value="*",o.output=k,l.output+=o.output)}if(H.length&&A.type!=="paren"&&(H[H.length-1].inner+=A.value),(A.value||A.output)&&Ee(A),o&&o.type==="text"&&A.type==="text"){o.value+=A.value,o.output=(o.output||"")+A.value;return}A.prev=o,a.push(A),o=A},xe=(A,O)=>{let d={...h[O],conditions:1,inner:""};d.prev=o,d.parens=l.parens,d.output=l.output;let x=(t.capture?"(":"")+d.open;be("parens"),C({type:A,value:O,output:l.output?"":_}),C({type:"paren",extglob:!0,value:V(),output:x}),H.push(d)},yr=A=>{let O=A.close+(t.capture?")":""),d;if(A.type==="negate"){let x=k;A.inner&&A.inner.length>1&&A.inner.includes("/")&&(x=K(t)),(x!==k||M()||/^\)+$/.test(J()))&&(O=A.close=`)$))${x}`),A.inner.includes("*")&&(d=J())&&/^\.[^\\/.]+$/.test(d)&&(O=A.close=`)${d})${x})`),A.prev.type==="bos"&&(l.negatedExtglob=!0)}C({type:"paren",extglob:!0,value:u,output:O}),oe("parens")};if(t.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(e)){let A=!1,O=e.replace(Bn,(d,x,P,j,G,Ie)=>j==="\\"?(A=!0,d):j==="?"?x?x+j+(G?L.repeat(G.length):""):Ie===0?v+(G?L.repeat(G.length):""):L.repeat(P.length):j==="."?R.repeat(P.length):j==="*"?x?x+j+(G?k:""):k:x?d:`\\${d}`);return A===!0&&(t.unescape===!0?O=O.replace(/\\/g,""):O=O.replace(/\\+/g,d=>d.length%2===0?"\\\\":d?"\\":"")),O===e&&t.contains===!0?(l.output=e,l):(l.output=Z.wrapOutput(O,l,r),l)}for(;!M();){if(u=V(),u==="\0")continue;if(u==="\\"){let d=b();if(d==="/"&&t.bash!==!0||d==="."||d===";")continue;if(!d){u+="\\",C({type:"text",value:u});continue}let x=/^\\+/.exec(J()),P=0;if(x&&x[0].length>2&&(P=x[0].length,l.index+=P,P%2!==0&&(u+="\\")),t.unescape===!0?u=V():u+=V(),l.brackets===0){C({type:"text",value:u});continue}}if(l.brackets>0&&(u!=="]"||o.value==="["||o.value==="[^")){if(t.posix!==!1&&u===":"){let d=o.value.slice(1);if(d.includes("[")&&(o.posix=!0,d.includes(":"))){let x=o.value.lastIndexOf("["),P=o.value.slice(0,x),j=o.value.slice(x+2),G=Nn[j];if(G){o.value=P+G,l.backtrack=!0,V(),!i.output&&a.indexOf(o)===1&&(i.output=_);continue}}}(u==="["&&b()!==":"||u==="-"&&b()==="]")&&(u=`\\${u}`),u==="]"&&(o.value==="["||o.value==="[^")&&(u=`\\${u}`),t.posix===!0&&u==="!"&&o.value==="["&&(u="^"),o.value+=u,Ee({value:u});continue}if(l.quotes===1&&u!=='"'){u=Z.escapeRegex(u),o.value+=u,Ee({value:u});continue}if(u==='"'){l.quotes=l.quotes===1?0:1,t.keepQuotes===!0&&C({type:"text",value:u});continue}if(u==="("){be("parens"),C({type:"paren",value:u});continue}if(u===")"){if(l.parens===0&&t.strictBrackets===!0)throw new SyntaxError(de("opening","("));let d=H[H.length-1];if(d&&l.parens===d.parens+1){yr(H.pop());continue}C({type:"paren",value:u,output:l.parens?")":"\\)"}),oe("parens");continue}if(u==="["){if(t.nobracket===!0||!J().includes("]")){if(t.nobracket!==!0&&t.strictBrackets===!0)throw new SyntaxError(de("closing","]"));u=`\\${u}`}else be("brackets");C({type:"bracket",value:u});continue}if(u==="]"){if(t.nobracket===!0||o&&o.type==="bracket"&&o.value.length===1){C({type:"text",value:u,output:`\\${u}`});continue}if(l.brackets===0){if(t.strictBrackets===!0)throw new SyntaxError(de("opening","["));C({type:"text",value:u,output:`\\${u}`});continue}oe("brackets");let d=o.value.slice(1);if(o.posix!==!0&&d[0]==="^"&&!d.includes("/")&&(u=`/${u}`),o.value+=u,Ee({value:u}),t.literalBrackets===!1||Z.hasRegexChars(d))continue;let x=Z.escapeRegex(o.value);if(l.output=l.output.slice(0,-o.value.length),t.literalBrackets===!0){l.output+=x,o.value=x;continue}o.value=`(${c}${x}|${o.value})`,l.output+=o.value;continue}if(u==="{"&&t.nobrace!==!0){be("braces");let d={type:"brace",value:u,output:"(",outputIndex:l.output.length,tokensIndex:l.tokens.length};w.push(d),C(d);continue}if(u==="}"){let d=w[w.length-1];if(t.nobrace===!0||!d){C({type:"text",value:u,output:u});continue}let x=")";if(d.dots===!0){let P=a.slice(),j=[];for(let G=P.length-1;G>=0&&(a.pop(),P[G].type!=="brace");G--)P[G].type!=="dots"&&j.unshift(P[G].value);x=Mn(j,t),l.backtrack=!0}if(d.comma!==!0&&d.dots!==!0){let P=l.output.slice(0,d.outputIndex),j=l.tokens.slice(d.tokensIndex);d.value=d.output="\\{",u=x="\\}",l.output=P;for(let G of j)l.output+=G.output||G.value}C({type:"brace",value:u,output:x}),oe("braces"),w.pop();continue}if(u==="|"){H.length>0&&H[H.length-1].conditions++,C({type:"text",value:u});continue}if(u===","){let d=u,x=w[w.length-1];x&&B[B.length-1]==="braces"&&(x.comma=!0,d="|"),C({type:"comma",value:u,output:d});continue}if(u==="/"){if(o.type==="dot"&&l.index===l.start+1){l.start=l.index+1,l.consumed="",l.output="",a.pop(),o=i;continue}C({type:"slash",value:u,output:$});continue}if(u==="."){if(l.braces>0&&o.type==="dot"){o.value==="."&&(o.output=R);let d=w[w.length-1];o.type="dots",o.output+=u,o.value+=u,d.dots=!0;continue}if(l.braces+l.parens===0&&o.type!=="bos"&&o.type!=="slash"){C({type:"text",value:u,output:R});continue}C({type:"dot",value:u,output:R});continue}if(u==="?"){if(!(o&&o.value==="(")&&t.noextglob!==!0&&b()==="("&&b(2)!=="?"){xe("qmark",u);continue}if(o&&o.type==="paren"){let x=b(),P=u;if(x==="<"&&!Z.supportsLookbehinds())throw new Error("Node.js v10 or higher is required for regex lookbehinds");(o.value==="("&&!/[!=<:]/.test(x)||x==="<"&&!/<([!=]|\w+>)/.test(J()))&&(P=`\\${u}`),C({type:"text",value:u,output:P});continue}if(t.dot!==!0&&(o.type==="slash"||o.type==="bos")){C({type:"qmark",value:u,output:z});continue}C({type:"qmark",value:u,output:L});continue}if(u==="!"){if(t.noextglob!==!0&&b()==="("&&(b(2)!=="?"||!/[!=<:]/.test(b(3)))){xe("negate",u);continue}if(t.nonegate!==!0&&l.index===0){Rr();continue}}if(u==="+"){if(t.noextglob!==!0&&b()==="("&&b(2)!=="?"){xe("plus",u);continue}if(o&&o.value==="("||t.regex===!1){C({type:"plus",value:u,output:f});continue}if(o&&(o.type==="bracket"||o.type==="paren"||o.type==="brace")||l.parens>0){C({type:"plus",value:u});continue}C({type:"plus",value:f});continue}if(u==="@"){if(t.noextglob!==!0&&b()==="("&&b(2)!=="?"){C({type:"at",extglob:!0,value:u,output:""});continue}C({type:"text",value:u});continue}if(u!=="*"){(u==="$"||u==="^")&&(u=`\\${u}`);let d=In.exec(J());d&&(u+=d[0],l.index+=d[0].length),C({type:"text",value:u});continue}if(o&&(o.type==="globstar"||o.star===!0)){o.type="star",o.star=!0,o.value+=u,o.output=k,l.backtrack=!0,l.globstar=!0,Q(u);continue}let A=J();if(t.noextglob!==!0&&/^\([^?]/.test(A)){xe("star",u);continue}if(o.type==="star"){if(t.noglobstar===!0){Q(u);continue}let d=o.prev,x=d.prev,P=d.type==="slash"||d.type==="bos",j=x&&(x.type==="star"||x.type==="globstar");if(t.bash===!0&&(!P||A[0]&&A[0]!=="/")){C({type:"star",value:u,output:""});continue}let G=l.braces>0&&(d.type==="comma"||d.type==="brace"),Ie=H.length&&(d.type==="pipe"||d.type==="paren");if(!P&&d.type!=="paren"&&!G&&!Ie){C({type:"star",value:u,output:""});continue}for(;A.slice(0,3)==="/**";){let Ce=e[l.index+4];if(Ce&&Ce!=="/")break;A=A.slice(3),Q("/**",3)}if(d.type==="bos"&&M()){o.type="globstar",o.value+=u,o.output=K(t),l.output=o.output,l.globstar=!0,Q(u);continue}if(d.type==="slash"&&d.prev.type!=="bos"&&!j&&M()){l.output=l.output.slice(0,-(d.output+o.output).length),d.output=`(?:${d.output}`,o.type="globstar",o.output=K(t)+(t.strictSlashes?")":"|$)"),o.value+=u,l.globstar=!0,l.output+=d.output+o.output,Q(u);continue}if(d.type==="slash"&&d.prev.type!=="bos"&&A[0]==="/"){let Ce=A[1]!==void 0?"|$":"";l.output=l.output.slice(0,-(d.output+o.output).length),d.output=`(?:${d.output}`,o.type="globstar",o.output=`${K(t)}${$}|${$}${Ce})`,o.value+=u,l.output+=d.output+o.output,l.globstar=!0,Q(u+V()),C({type:"slash",value:"/",output:""});continue}if(d.type==="bos"&&A[0]==="/"){o.type="globstar",o.value+=u,o.output=`(?:^|${$}|${K(t)}${$})`,l.output=o.output,l.globstar=!0,Q(u+V()),C({type:"slash",value:"/",output:""});continue}l.output=l.output.slice(0,-o.output.length),o.type="globstar",o.output=K(t),o.value+=u,l.output+=o.output,l.globstar=!0,Q(u);continue}let O={type:"star",value:u,output:k};if(t.bash===!0){O.output=".*?",(o.type==="bos"||o.type==="slash")&&(O.output=g+O.output),C(O);continue}if(o&&(o.type==="bracket"||o.type==="paren")&&t.regex===!0){O.output=u,C(O);continue}(l.index===l.start||o.type==="slash"||o.type==="dot")&&(o.type==="dot"?(l.output+=S,o.output+=S):t.dot===!0?(l.output+=T,o.output+=T):(l.output+=g,o.output+=g),b()!=="*"&&(l.output+=_,o.output+=_)),C(O)}for(;l.brackets>0;){if(t.strictBrackets===!0)throw new SyntaxError(de("closing","]"));l.output=Z.escapeLast(l.output,"["),oe("brackets")}for(;l.parens>0;){if(t.strictBrackets===!0)throw new SyntaxError(de("closing",")"));l.output=Z.escapeLast(l.output,"("),oe("parens")}for(;l.braces>0;){if(t.strictBrackets===!0)throw new SyntaxError(de("closing","}"));l.output=Z.escapeLast(l.output,"{"),oe("braces")}if(t.strictSlashes!==!0&&(o.type==="star"||o.type==="bracket")&&C({type:"maybe_slash",value:"",output:`${$}?`}),l.backtrack===!0){l.output="";for(let A of l.tokens)l.output+=A.output!=null?A.output:A.value,A.suffix&&(l.output+=A.suffix)}return l};Vt.fastpaths=(e,r)=>{let t={...r},n=typeof t.maxLength=="number"?Math.min(Le,t.maxLength):Le,s=e.length;if(s>n)throw new SyntaxError(`Input length: ${s}, exceeds maximum allowed length: ${n}`);e=zt[e]||e;let i=Z.isWindows(r),{DOT_LITERAL:a,SLASH_LITERAL:c,ONE_CHAR:p,DOTS_SLASH:m,NO_DOT:h,NO_DOTS:R,NO_DOTS_SLASH:f,STAR:$,START_ANCHOR:_}=ke.globChars(i),y=t.dot?R:h,E=t.dot?f:h,S=t.capture?"":"?:",T={negated:!1,prefix:""},L=t.bash===!0?".*?":$;t.capture&&(L=`(${L})`);let z=g=>g.noglobstar===!0?L:`(${S}(?:(?!${_}${g.dot?m:a}).)*?)`,I=g=>{switch(g){case"*":return`${y}${p}${L}`;case".*":return`${a}${p}${L}`;case"*.*":return`${y}${L}${a}${p}${L}`;case"*/*":return`${y}${L}${c}${p}${E}${L}`;case"**":return y+z(t);case"**/*":return`(?:${y}${z(t)}${c})?${E}${p}${L}`;case"**/*.*":return`(?:${y}${z(t)}${c})?${E}${L}${a}${p}${L}`;case"**/.*":return`(?:${y}${z(t)}${c})?${a}${p}${L}`;default:{let v=/^(.*?)\.(\w+)$/.exec(g);if(!v)return;let k=I(v[1]);return k?k+a+v[2]:void 0}}},re=Z.removePrefix(e,T),K=I(re);return K&&t.strictSlashes!==!0&&(K+=`${c}?`),K};Jt.exports=Vt});var rr=q((fs,tr)=>{"use strict";var Pn=W("path"),Dn=Yt(),Ze=er(),Ye=Re(),Un=me(),Gn=e=>e&&typeof e=="object"&&!Array.isArray(e),D=(e,r,t=!1)=>{if(Array.isArray(e)){let h=e.map(f=>D(f,r,t));return f=>{for(let $ of h){let _=$(f);if(_)return _}return!1}}let n=Gn(e)&&e.tokens&&e.input;if(e===""||typeof e!="string"&&!n)throw new TypeError("Expected pattern to be a non-empty string");let s=r||{},i=Ye.isWindows(r),a=n?D.compileRe(e,r):D.makeRe(e,r,!1,!0),c=a.state;delete a.state;let p=()=>!1;if(s.ignore){let h={...r,ignore:null,onMatch:null,onResult:null};p=D(s.ignore,h,t)}let m=(h,R=!1)=>{let{isMatch:f,match:$,output:_}=D.test(h,a,r,{glob:e,posix:i}),y={glob:e,state:c,regex:a,posix:i,input:h,output:_,match:$,isMatch:f};return typeof s.onResult=="function"&&s.onResult(y),f===!1?(y.isMatch=!1,R?y:!1):p(h)?(typeof s.onIgnore=="function"&&s.onIgnore(y),y.isMatch=!1,R?y:!1):(typeof s.onMatch=="function"&&s.onMatch(y),R?y:!0)};return t&&(m.state=c),m};D.test=(e,r,t,{glob:n,posix:s}={})=>{if(typeof e!="string")throw new TypeError("Expected input to be a string");if(e==="")return{isMatch:!1,output:""};let i=t||{},a=i.format||(s?Ye.toPosixSlashes:null),c=e===n,p=c&&a?a(e):e;return c===!1&&(p=a?a(e):e,c=p===n),(c===!1||i.capture===!0)&&(i.matchBase===!0||i.basename===!0?c=D.matchBase(e,r,t,s):c=r.exec(p)),{isMatch:Boolean(c),match:c,output:p}};D.matchBase=(e,r,t,n=Ye.isWindows(t))=>(r instanceof RegExp?r:D.makeRe(r,t)).test(Pn.basename(e));D.isMatch=(e,r,t)=>D(r,t)(e);D.parse=(e,r)=>Array.isArray(e)?e.map(t=>D.parse(t,r)):Ze(e,{...r,fastpaths:!1});D.scan=(e,r)=>Dn(e,r);D.compileRe=(e,r,t=!1,n=!1)=>{if(t===!0)return e.output;let s=r||{},i=s.contains?"":"^",a=s.contains?"":"$",c=`${i}(?:${e.output})${a}`;e&&e.negated===!0&&(c=`^(?!${c}).*$`);let p=D.toRegex(c,r);return n===!0&&(p.state=e),p};D.makeRe=(e,r={},t=!1,n=!1)=>{if(!e||typeof e!="string")throw new TypeError("Expected a non-empty string");let s={negated:!1,fastpaths:!0};return r.fastpaths!==!1&&(e[0]==="."||e[0]==="*")&&(s.output=Ze.fastpaths(e,r)),s.output||(s=Ze(e,r)),D.compileRe(s,r,t,n)};D.toRegex=(e,r)=>{try{let t=r||{};return new RegExp(e,t.flags||(t.nocase?"i":""))}catch(t){if(r&&r.debug===!0)throw t;return/$^/}};D.constants=Un;tr.exports=D});var sr=q((ps,nr)=>{"use strict";nr.exports=rr()});var cr=q((hs,ur)=>{"use strict";var ir=W("util"),or=Mt(),ae=sr(),ze=Re(),ar=e=>e===""||e==="./",N=(e,r,t)=>{r=[].concat(r),e=[].concat(e);let n=new Set,s=new Set,i=new Set,a=0,c=h=>{i.add(h.output),t&&t.onResult&&t.onResult(h)};for(let h=0;h!n.has(h));if(t&&m.length===0){if(t.failglob===!0)throw new Error(`No matches found for "${r.join(", ")}"`);if(t.nonull===!0||t.nullglob===!0)return t.unescape?r.map(h=>h.replace(/\\/g,"")):r}return m};N.match=N;N.matcher=(e,r)=>ae(e,r);N.isMatch=(e,r,t)=>ae(r,t)(e);N.any=N.isMatch;N.not=(e,r,t={})=>{r=[].concat(r).map(String);let n=new Set,s=[],a=N(e,r,{...t,onResult:c=>{t.onResult&&t.onResult(c),s.push(c.output)}});for(let c of s)a.includes(c)||n.add(c);return[...n]};N.contains=(e,r,t)=>{if(typeof e!="string")throw new TypeError(`Expected a string: "${ir.inspect(e)}"`);if(Array.isArray(r))return r.some(n=>N.contains(e,n,t));if(typeof r=="string"){if(ar(e)||ar(r))return!1;if(e.includes(r)||e.startsWith("./")&&e.slice(2).includes(r))return!0}return N.isMatch(e,r,{...t,contains:!0})};N.matchKeys=(e,r,t)=>{if(!ze.isObject(e))throw new TypeError("Expected the first argument to be an object");let n=N(Object.keys(e),r,t),s={};for(let i of n)s[i]=e[i];return s};N.some=(e,r,t)=>{let n=[].concat(e);for(let s of[].concat(r)){let i=ae(String(s),t);if(n.some(a=>i(a)))return!0}return!1};N.every=(e,r,t)=>{let n=[].concat(e);for(let s of[].concat(r)){let i=ae(String(s),t);if(!n.every(a=>i(a)))return!1}return!0};N.all=(e,r,t)=>{if(typeof e!="string")throw new TypeError(`Expected a string: "${ir.inspect(e)}"`);return[].concat(r).every(n=>ae(n,t)(e))};N.capture=(e,r,t)=>{let n=ze.isWindows(t),i=ae.makeRe(String(e),{...t,capture:!0}).exec(n?ze.toPosixSlashes(r):r);if(i)return i.slice(1).map(a=>a===void 0?"":a)};N.makeRe=(...e)=>ae.makeRe(...e);N.scan=(...e)=>ae.scan(...e);N.parse=(e,r)=>{let t=[];for(let n of[].concat(e||[]))for(let s of or(String(n),r))t.push(ae.parse(s,r));return t};N.braces=(e,r)=>{if(typeof e!="string")throw new TypeError("Expected a string");return r&&r.nobrace===!0||!/\{.*\}/.test(e)?[e]:or(e,r)};N.braceExpand=(e,r)=>{if(typeof e!="string")throw new TypeError("Expected a string");return N.braces(e,{...r,expand:!0})};ur.exports=N});var fr=q((ds,lr)=>{"use strict";lr.exports=(e,...r)=>new Promise(t=>{t(e(...r))})});var hr=q((gs,Ve)=>{"use strict";var qn=fr(),pr=e=>{if(e<1)throw new TypeError("Expected `concurrency` to be a number from 1 and up");let r=[],t=0,n=()=>{t--,r.length>0&&r.shift()()},s=(c,p,...m)=>{t++;let h=qn(c,...m);p(h),h.then(n,n)},i=(c,p,...m)=>{tnew Promise(m=>i(c,m,...p));return Object.defineProperties(a,{activeCount:{get:()=>t},pendingCount:{get:()=>r.length}}),a};Ve.exports=pr;Ve.exports.default=pr});var Fn={};wr(Fn,{default:()=>jn});var Se=W("@yarnpkg/cli"),ne=W("@yarnpkg/core"),et=W("@yarnpkg/core"),ue=W("clipanion"),ce=class extends Se.BaseCommand{constructor(){super(...arguments);this.json=ue.Option.Boolean("--json",!1,{description:"Format the output as an NDJSON stream"});this.production=ue.Option.Boolean("--production",!1,{description:"Only install regular dependencies by omitting dev dependencies"});this.all=ue.Option.Boolean("-A,--all",!1,{description:"Install the entire project"});this.workspaces=ue.Option.Rest()}async execute(){let t=await ne.Configuration.find(this.context.cwd,this.context.plugins),{project:n,workspace:s}=await ne.Project.find(t,this.context.cwd),i=await ne.Cache.find(t);await n.restoreInstallState({restoreResolutions:!1});let a;if(this.all)a=new Set(n.workspaces);else if(this.workspaces.length===0){if(!s)throw new Se.WorkspaceRequiredError(n.cwd,this.context.cwd);a=new Set([s])}else a=new Set(this.workspaces.map(p=>n.getWorkspaceByIdent(et.structUtils.parseIdent(p))));for(let p of a)for(let m of this.production?["dependencies"]:ne.Manifest.hardDependencies)for(let h of p.manifest.getForScope(m).values()){let R=n.tryWorkspaceByDescriptor(h);R!==null&&a.add(R)}for(let p of n.workspaces)a.has(p)?this.production&&p.manifest.devDependencies.clear():(p.manifest.installConfig=p.manifest.installConfig||{},p.manifest.installConfig.selfReferences=!1,p.manifest.dependencies.clear(),p.manifest.devDependencies.clear(),p.manifest.peerDependencies.clear(),p.manifest.scripts.clear());return(await ne.StreamReport.start({configuration:t,json:this.json,stdout:this.context.stdout,includeLogs:!0},async p=>{await n.install({cache:i,report:p,persistProject:!1})})).exitCode()}};ce.paths=[["workspaces","focus"]],ce.usage=ue.Command.Usage({category:"Workspace-related commands",description:"install a single workspace and its dependencies",details:"\n This command will run an install as if the specified workspaces (and all other workspaces they depend on) were the only ones in the project. If no workspaces are explicitly listed, the active one will be assumed.\n\n Note that this command is only very moderately useful when using zero-installs, since the cache will contain all the packages anyway - meaning that the only difference between a full install and a focused install would just be a few extra lines in the `.pnp.cjs` file, at the cost of introducing an extra complexity.\n\n If the `-A,--all` flag is set, the entire project will be installed. Combine with `--production` to replicate the old `yarn install --production`.\n "});var Ne=W("@yarnpkg/cli"),ge=W("@yarnpkg/core"),_e=W("@yarnpkg/core"),Y=W("@yarnpkg/core"),gr=W("@yarnpkg/plugin-git"),U=W("clipanion"),Oe=Be(cr()),Ar=W("os"),mr=Be(hr()),te=Be(W("typanion")),pe=class extends Ne.BaseCommand{constructor(){super(...arguments);this.recursive=U.Option.Boolean("-R,--recursive",!1,{description:"Find packages via dependencies/devDependencies instead of using the workspaces field"});this.from=U.Option.Array("--from",[],{description:"An array of glob pattern idents from which to base any recursion"});this.all=U.Option.Boolean("-A,--all",!1,{description:"Run the command on all workspaces of a project"});this.verbose=U.Option.Boolean("-v,--verbose",!1,{description:"Prefix each output line with the name of the originating workspace"});this.parallel=U.Option.Boolean("-p,--parallel",!1,{description:"Run the commands in parallel"});this.interlaced=U.Option.Boolean("-i,--interlaced",!1,{description:"Print the output of commands in real-time instead of buffering it"});this.jobs=U.Option.String("-j,--jobs",{description:"The maximum number of parallel tasks that the execution will be limited to; or `unlimited`",validator:te.isOneOf([te.isEnum(["unlimited"]),te.applyCascade(te.isNumber(),[te.isInteger(),te.isAtLeast(1)])])});this.topological=U.Option.Boolean("-t,--topological",!1,{description:"Run the command after all workspaces it depends on (regular) have finished"});this.topologicalDev=U.Option.Boolean("--topological-dev",!1,{description:"Run the command after all workspaces it depends on (regular + dev) have finished"});this.include=U.Option.Array("--include",[],{description:"An array of glob pattern idents; only matching workspaces will be traversed"});this.exclude=U.Option.Array("--exclude",[],{description:"An array of glob pattern idents; matching workspaces won't be traversed"});this.publicOnly=U.Option.Boolean("--no-private",{description:"Avoid running the command on private workspaces"});this.since=U.Option.String("--since",{description:"Only include workspaces that have been changed since the specified ref.",tolerateBoolean:!0});this.commandName=U.Option.String();this.args=U.Option.Proxy()}async execute(){let t=await ge.Configuration.find(this.context.cwd,this.context.plugins),{project:n,workspace:s}=await ge.Project.find(t,this.context.cwd);if(!this.all&&!s)throw new Ne.WorkspaceRequiredError(n.cwd,this.context.cwd);await n.restoreInstallState();let i=this.cli.process([this.commandName,...this.args]),a=i.path.length===1&&i.path[0]==="run"&&typeof i.scriptName<"u"?i.scriptName:null;if(i.path.length===0)throw new U.UsageError("Invalid subcommand name for iteration - use the 'run' keyword if you wish to execute a script");let c=this.all?n.topLevelWorkspace:s,p=this.since?Array.from(await gr.gitUtils.fetchChangedWorkspaces({ref:this.since,project:n})):[c,...this.from.length>0?c.getRecursiveWorkspaceChildren():[]],m=g=>Oe.default.isMatch(Y.structUtils.stringifyIdent(g.locator),this.from),h=this.from.length>0?p.filter(m):p,R=new Set([...h,...h.map(g=>[...this.recursive?this.since?g.getRecursiveWorkspaceDependents():g.getRecursiveWorkspaceDependencies():g.getRecursiveWorkspaceChildren()]).flat()]),f=[],$=!1;if(a!=null&&a.includes(":")){for(let g of n.workspaces)if(g.manifest.scripts.has(a)&&($=!$,$===!1))break}for(let g of R)a&&!g.manifest.scripts.has(a)&&!$&&!(await ge.scriptUtils.getWorkspaceAccessibleBinaries(g)).has(a)||a===process.env.npm_lifecycle_event&&g.cwd===s.cwd||this.include.length>0&&!Oe.default.isMatch(Y.structUtils.stringifyIdent(g.locator),this.include)||this.exclude.length>0&&Oe.default.isMatch(Y.structUtils.stringifyIdent(g.locator),this.exclude)||this.publicOnly&&g.manifest.private===!0||f.push(g);let _=this.parallel?this.jobs==="unlimited"?1/0:Number(this.jobs)||Math.max(1,(0,Ar.cpus)().length/2):1,y=_===1?!1:this.parallel,E=y?this.interlaced:!0,S=(0,mr.default)(_),T=new Map,L=new Set,z=0,I=null,re=!1,K=await _e.StreamReport.start({configuration:t,stdout:this.context.stdout},async g=>{let v=async(k,{commandIndex:l})=>{if(re)return-1;!y&&this.verbose&&l>1&&g.reportSeparator();let H=Kn(k,{configuration:t,verbose:this.verbose,commandIndex:l}),[w,B]=dr(g,{prefix:H,interlaced:E}),[o,u]=dr(g,{prefix:H,interlaced:E});try{this.verbose&&g.reportInfo(null,`${H} Process started`);let M=Date.now(),b=await this.cli.run([this.commandName,...this.args],{cwd:k.cwd,stdout:w,stderr:o})||0;w.end(),o.end(),await B,await u;let V=Date.now();if(this.verbose){let J=t.get("enableTimers")?`, completed in ${Y.formatUtils.pretty(t,V-M,Y.formatUtils.Type.DURATION)}`:"";g.reportInfo(null,`${H} Process exited (exit code ${b})${J}`)}return b===130&&(re=!0,I=b),b}catch(M){throw w.end(),o.end(),await B,await u,M}};for(let k of f)T.set(k.anchoredLocator.locatorHash,k);for(;T.size>0&&!g.hasErrors();){let k=[];for(let[w,B]of T){if(L.has(B.anchoredDescriptor.descriptorHash))continue;let o=!0;if(this.topological||this.topologicalDev){let u=this.topologicalDev?new Map([...B.manifest.dependencies,...B.manifest.devDependencies]):B.manifest.dependencies;for(let M of u.values()){let b=n.tryWorkspaceByDescriptor(M);if(o=b===null||!T.has(b.anchoredLocator.locatorHash),!o)break}}if(!!o&&(L.add(B.anchoredDescriptor.descriptorHash),k.push(S(async()=>{let u=await v(B,{commandIndex:++z});return T.delete(w),L.delete(B.anchoredDescriptor.descriptorHash),u})),!y))break}if(k.length===0){let w=Array.from(T.values()).map(B=>Y.structUtils.prettyLocator(t,B.anchoredLocator)).join(", ");g.reportError(_e.MessageName.CYCLIC_DEPENDENCIES,`Dependency cycle detected (${w})`);return}let H=(await Promise.all(k)).find(w=>w!==0);I===null&&(I=typeof H<"u"?1:I),(this.topological||this.topologicalDev)&&typeof H<"u"&&g.reportError(_e.MessageName.UNNAMED,"The command failed for workspaces that are depended upon by other workspaces; can't satisfy the dependency graph")}});return I!==null?I:K.exitCode()}};pe.paths=[["workspaces","foreach"]],pe.usage=U.Command.Usage({category:"Workspace-related commands",description:"run a command on all workspaces",details:"\n This command will run a given sub-command on current and all its descendant workspaces. Various flags can alter the exact behavior of the command:\n\n - If `-p,--parallel` is set, the commands will be ran in parallel; they'll by default be limited to a number of parallel tasks roughly equal to half your core number, but that can be overridden via `-j,--jobs`, or disabled by setting `-j unlimited`.\n\n - If `-p,--parallel` and `-i,--interlaced` are both set, Yarn will print the lines from the output as it receives them. If `-i,--interlaced` wasn't set, it would instead buffer the output from each process and print the resulting buffers only after their source processes have exited.\n\n - If `-t,--topological` is set, Yarn will only run the command after all workspaces that it depends on through the `dependencies` field have successfully finished executing. If `--topological-dev` is set, both the `dependencies` and `devDependencies` fields will be considered when figuring out the wait points.\n\n - If `-A,--all` is set, Yarn will run the command on all the workspaces of a project. By default yarn runs the command only on current and all its descendant workspaces.\n\n - If `-R,--recursive` is set, Yarn will find workspaces to run the command on by recursively evaluating `dependencies` and `devDependencies` fields, instead of looking at the `workspaces` fields.\n\n - If `--from` is set, Yarn will use the packages matching the 'from' glob as the starting point for any recursive search.\n\n - If `--since` is set, Yarn will only run the command on workspaces that have been modified since the specified ref. By default Yarn will use the refs specified by the `changesetBaseRefs` configuration option.\n\n - The command may apply to only some workspaces through the use of `--include` which acts as a whitelist. The `--exclude` flag will do the opposite and will be a list of packages that mustn't execute the script. Both flags accept glob patterns (if valid Idents and supported by [micromatch](https://github.com/micromatch/micromatch)). Make sure to escape the patterns, to prevent your own shell from trying to expand them.\n\n Adding the `-v,--verbose` flag will cause Yarn to print more information; in particular the name of the workspace that generated the output will be printed at the front of each line.\n\n If the command is `run` and the script being run does not exist the child workspace will be skipped without error.\n ",examples:[["Publish current and all descendant packages","yarn workspaces foreach npm publish --tolerate-republish"],["Run build script on current and all descendant packages","yarn workspaces foreach run build"],["Run build script on current and all descendant packages in parallel, building package dependencies first","yarn workspaces foreach -pt run build"],["Run build script on several packages and all their dependencies, building dependencies first","yarn workspaces foreach -ptR --from '{workspace-a,workspace-b}' run build"]]});function dr(e,{prefix:r,interlaced:t}){let n=e.createStreamReporter(r),s=new Y.miscUtils.DefaultStream;s.pipe(n,{end:!1}),s.on("finish",()=>{n.end()});let i=new Promise(c=>{n.on("finish",()=>{c(s.active)})});if(t)return[s,i];let a=new Y.miscUtils.BufferStream;return a.pipe(s,{end:!1}),a.on("finish",()=>{s.end()}),[a,i]}function Kn(e,{configuration:r,commandIndex:t,verbose:n}){if(!n)return null;let i=`[${Y.structUtils.stringifyIdent(e.locator)}]:`,a=["#2E86AB","#A23B72","#F18F01","#C73E1D","#CCE2A3"],c=a[t%a.length];return Y.formatUtils.pretty(r,i,c)}var Wn={commands:[ce,pe]},jn=Wn;return Sr(Fn);})(); +/*! + * fill-range + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Licensed under the MIT License. + */ +/*! + * is-number + * + * Copyright (c) 2014-present, Jon Schlinkert. + * Released under the MIT License. + */ +/*! + * to-regex-range + * + * Copyright (c) 2015-present, Jon Schlinkert. + * Released under the MIT License. + */ +return plugin; +} +}; diff --git a/.yarnrc.yml b/.yarnrc.yml index 333a8cf26..fc7f280f8 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -7,5 +7,7 @@ plugins: spec: "@yarnpkg/plugin-stage" - path: .yarn/plugins/@yarnpkg/plugin-version.cjs spec: "@yarnpkg/plugin-version" + - path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs + spec: "@yarnpkg/plugin-workspace-tools" yarnPath: .yarn/releases/yarn-3.3.1.cjs diff --git a/contracts/config/DisputeTemplate.simple.json b/contracts/config/DisputeTemplate.simple.json new file mode 100644 index 000000000..50b3760dc --- /dev/null +++ b/contracts/config/DisputeTemplate.simple.json @@ -0,0 +1,23 @@ +{ + "$schema": "../NewDisputeTemplate.schema.json", + "title": "Let's do this", + "description": "We want to do this: %s", + "question": "Does it comply with the policy?", + "answers": [ + { + "title": "Yes", + "description": "Select this if you agree that it must be done." + }, + { + "title": "No", + "description": "Select this if you do not agree that it must be done." + } + ], + "policyURI": "/ipfs/Qmdvk...rSD6cE/policy.pdf", + "frontendUrl": "https://kleros-v2.netlify.app/#/cases/%s/overview", + "arbitratorChainID": "421613", + "arbitratorAddress": "0xD08Ab99480d02bf9C092828043f611BcDFEA917b", + "category": "Others", + "specification": "KIP001", + "lang": "en_US" +} diff --git a/contracts/deploy/00-home-chain-arbitrable.ts b/contracts/deploy/00-home-chain-arbitrable.ts index 84827f520..62f731fdf 100644 --- a/contracts/deploy/00-home-chain-arbitrable.ts +++ b/contracts/deploy/00-home-chain-arbitrable.ts @@ -1,6 +1,6 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; -import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; +import disputeTemplate from "../config/DisputeTemplate.simple.json"; enum HomeChains { ARBITRUM_ONE = 42161, diff --git a/contracts/deploy/03-vea-mock.ts b/contracts/deploy/03-vea-mock.ts index c0c51897b..6bf753ce5 100644 --- a/contracts/deploy/03-vea-mock.ts +++ b/contracts/deploy/03-vea-mock.ts @@ -2,7 +2,7 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; import getContractAddress from "../deploy-helpers/getContractAddress"; import { KlerosCore__factory } from "../typechain-types"; -import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; +import disputeTemplate from "../config/DisputeTemplate.simple.json"; const HARDHAT_NETWORK = 31337; diff --git a/contracts/deploy/04-foreign-arbitrable.ts b/contracts/deploy/04-foreign-arbitrable.ts index 3623aca43..725c5c03c 100644 --- a/contracts/deploy/04-foreign-arbitrable.ts +++ b/contracts/deploy/04-foreign-arbitrable.ts @@ -1,6 +1,6 @@ import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; -import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; +import disputeTemplate from "../config/DisputeTemplate.simple.json"; enum ForeignChains { ETHEREUM_MAINNET = 1, diff --git a/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts b/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts index 49760a685..c96bbf326 100644 --- a/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts +++ b/contracts/deploy/04-klerosliquid-to-v2-gnosis.ts @@ -1,7 +1,7 @@ import { parseUnits, parseEther } from "ethers/lib/utils"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { DeployFunction } from "hardhat-deploy/types"; -import disputeTemplate from "../../kleros-sdk/config/v2-disputetemplate/simple/NewDisputeTemplate.simple.json"; +import disputeTemplate from "../config/DisputeTemplate.simple.json"; enum ForeignChains { GNOSIS_MAINNET = 100, diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index b7c6f2cd4..47741a36b 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -47,6 +47,16 @@ const config: HardhatUserConfig = { chainId: 31337, saveDeployments: true, tags: ["test", "local"], + companionNetworks: { + home: "localhost", + foreign: "localhost", + }, + }, + dockerhost: { + url: `http://host.docker.internal:8545`, + chainId: 31337, + saveDeployments: true, + tags: ["test", "local"], companionNetworks: { foreign: "localhost", }, diff --git a/contracts/package.json b/contracts/package.json index 2daa33f77..0d6016a53 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -26,6 +26,9 @@ "simulate": "hardhat simulate:all", "simulate-local": "hardhat simulate:all --network localhost", "bot:keeper": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch hardhat run ./scripts/keeperBot.ts", + "bot:relayer-from-chiado": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch hardhat run ./scripts/disputeRelayerBotFromChiado.ts", + "bot:relayer-from-goerli": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch hardhat run ./scripts/disputeRelayerBotFromGoerli.ts", + "bot:relayer-from-hardhat": "NODE_NO_WARNINGS=1 NODE_OPTIONS=--experimental-fetch hardhat run ./scripts/disputeRelayerBotFromHardhat.ts", "etherscan-verify": "hardhat etherscan-verify", "sourcify": "hardhat sourcify --write-failing-metadata", "size": "hardhat size-contracts --no-compile", @@ -54,6 +57,7 @@ "dotenv": "^16.3.1", "ethereumjs-util": "^7.1.5", "ethers": "^5.7.2", + "graphql": "^16.7.1", "graphql-request": "^6.1.0", "hardhat": "^2.15.0", "hardhat-contract-sizer": "^2.10.0", diff --git a/contracts/scripts/disputeRelayerBot.ts b/contracts/scripts/disputeRelayerBot.ts new file mode 100644 index 000000000..9437bdf52 --- /dev/null +++ b/contracts/scripts/disputeRelayerBot.ts @@ -0,0 +1,114 @@ +import env from "./utils/env"; +import loggerFactory from "./utils/logger"; +import hre = require("hardhat"); +import { + KlerosCore, + ForeignGateway__factory, + HomeGateway, + TestERC20, + IArbitrableV2__factory, +} from "../typechain-types"; +import { DisputeRequestEventObject } from "../typechain-types/src/arbitration/interfaces/IArbitrableV2"; +import { HttpNetworkConfig } from "hardhat/types"; +import { DeploymentsExtension } from "hardhat-deploy/types"; + +const { ethers } = hre; +const HEARTBEAT_URL = env.optionalNoDefault("HEARTBEAT_URL_RELAYER_BOT"); + +const loggerOptions = env.optionalNoDefault("LOGTAIL_TOKEN_RELAYER_BOT") + ? { + transportTargetOptions: { + target: "@logtail/pino", + options: { sourceToken: env.require("LOGTAIL_TOKEN_RELAYER_BOT") }, + level: env.optional("LOG_LEVEL", "info"), + }, + level: env.optional("LOG_LEVEL", "info"), // for pino-pretty + } + : {}; + +export default async function main( + foreignNetwork: HttpNetworkConfig, + foreignDeployments: DeploymentsExtension, + foreignGatewayArtifact: string, + homeGatewayArtifact: string, + feeTokenArtifact?: string +) { + const core = (await ethers.getContract("KlerosCore")) as KlerosCore; + const homeGateway = (await ethers.getContract(homeGatewayArtifact)) as HomeGateway; + const feeToken = feeTokenArtifact ? ((await ethers.getContract(feeTokenArtifact)) as TestERC20) : undefined; + + const foreignChainProvider = new ethers.providers.JsonRpcProvider(foreignNetwork.url); + const foreignGatewayDeployment = await foreignDeployments.get(foreignGatewayArtifact); + const foreignGateway = await ForeignGateway__factory.connect(foreignGatewayDeployment.address, foreignChainProvider); + const foreignChainID = await foreignChainProvider.getNetwork().then((network) => network.chainId); + const arbitrableInterface = IArbitrableV2__factory.createInterface(); + + const logger = loggerFactory.createLogger(loggerOptions).child({ foreignChainId: foreignChainID }); + logger.info(`Listening for events from ${foreignGatewayArtifact}...`); + + if (HEARTBEAT_URL) { + logger.debug("Sending heartbeat"); + fetch(HEARTBEAT_URL); + } else { + logger.debug("Heartbeat not set up, skipping"); + } + + // Event subscription + // WARNING: The callback might run more than once if the script is restarted in the same block + // type Listener = [ eventArg1, ...eventArgN, transactionReceipt ] + foreignGateway.on( + "CrossChainDisputeOutgoing", + async (foreignBlockHash, foreignArbitrable, foreignDisputeID, choices, extraData, txReceipt) => { + logger.info( + `CrossChainDisputeOutgoing: ${foreignBlockHash} ${foreignArbitrable} ${foreignDisputeID} ${choices} ${extraData}` + ); + logger.debug(`tx receipt: ${JSON.stringify(txReceipt)}`); + + // txReceipt is missing the full logs for this tx so we need to request it here + const fullTxReceipt = await foreignChainProvider.getTransactionReceipt(txReceipt.transactionHash); + + // Retrieve the DisputeRequest event + const disputeRequests: DisputeRequestEventObject[] = fullTxReceipt.logs + .filter((log) => log.topics[0] === arbitrableInterface.getEventTopic("DisputeRequest")) + .map((log) => arbitrableInterface.parseLog(log).args as unknown as DisputeRequestEventObject); + logger.warn(`More than 1 DisputeRequest event: not supported yet, skipping the others events.`); + + const disputeRequest = disputeRequests[0]; + logger.info(`tx events DisputeRequest: ${JSON.stringify(disputeRequest)}`); + + const relayCreateDisputeParams = { + foreignBlockHash, + foreignChainID, + foreignArbitrable, + foreignDisputeID, + externalDisputeID: disputeRequest._externalDisputeID, + templateId: disputeRequest._templateId, + templateUri: disputeRequest._templateUri, + choices, + extraData, + }; + logger.info(`Relaying dispute to home chain... ${JSON.stringify(relayCreateDisputeParams)}`); + + let tx; + if (feeToken === undefined) { + // Paying in native Arbitrum ETH + const cost = (await core.functions["arbitrationCost(bytes)"](extraData)).cost; + tx = await homeGateway.functions[ + "relayCreateDispute((bytes32,uint256,address,uint256,uint256,uint256,string,uint256,bytes))" + ](relayCreateDisputeParams, { value: cost }); + } else { + // Paying in ERC20 + const cost = (await core.functions["arbitrationCost(bytes,address)"](extraData, feeToken.address)).cost; + await (await feeToken.approve(homeGateway.address, cost)).wait(); + tx = await homeGateway.functions[ + "relayCreateDispute((bytes32,uint256,address,uint256,uint256,uint256,string,uint256,bytes),uint256)" + ](relayCreateDisputeParams, cost); + } + tx = tx.wait(); + logger.info(`relayCreateDispute txId: ${tx.transactionHash}`); + } + ); + + const delay = (ms) => new Promise((x) => setTimeout(x, ms)); + await delay(60 * 60 * 1000); // 1 hour +} diff --git a/contracts/scripts/disputeRelayerBotFromChiado.ts b/contracts/scripts/disputeRelayerBotFromChiado.ts new file mode 100644 index 000000000..a4c46dc81 --- /dev/null +++ b/contracts/scripts/disputeRelayerBotFromChiado.ts @@ -0,0 +1,20 @@ +import hre = require("hardhat"); +import relayer from "./disputeRelayerBot"; +import { HttpNetworkConfig } from "hardhat/types"; + +async function main() { + await relayer( + hre.config.networks.chiado as HttpNetworkConfig, + hre.companionNetworks.foreignChiado.deployments, + "ForeignGatewayOnGnosis", + "HomeGatewayToGnosis", + "DAI" + ); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/contracts/scripts/disputeRelayerBotFromGoerli.ts b/contracts/scripts/disputeRelayerBotFromGoerli.ts new file mode 100644 index 000000000..b9191a578 --- /dev/null +++ b/contracts/scripts/disputeRelayerBotFromGoerli.ts @@ -0,0 +1,19 @@ +import hre = require("hardhat"); +import relayer from "./disputeRelayerBot"; +import { HttpNetworkConfig } from "hardhat/types"; + +async function main() { + await relayer( + hre.config.networks.goerli as HttpNetworkConfig, + hre.companionNetworks.foreignGoerli.deployments, + "ForeignGatewayOnEthereum", + "HomeGatewayToEthereum" + ); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/contracts/scripts/disputeRelayerBotFromHardhat.ts b/contracts/scripts/disputeRelayerBotFromHardhat.ts new file mode 100644 index 000000000..6031f8baf --- /dev/null +++ b/contracts/scripts/disputeRelayerBotFromHardhat.ts @@ -0,0 +1,19 @@ +import hre = require("hardhat"); +import relayer from "./disputeRelayerBot"; +import { HttpNetworkConfig } from "hardhat/types"; + +async function main() { + await relayer( + hre.config.networks.localhost as HttpNetworkConfig, + hre.companionNetworks.foreign.deployments, + "ForeignGatewayOnEthereum", + "HomeGatewayToEthereum" + ); +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/contracts/scripts/keeperBot.ts b/contracts/scripts/keeperBot.ts index 3360c7f4b..9cf8d0453 100644 --- a/contracts/scripts/keeperBot.ts +++ b/contracts/scripts/keeperBot.ts @@ -2,10 +2,10 @@ import { DisputeKitClassic, KlerosCore, PNK, RandomizerRNG, SortitionModule } fr import request from "graphql-request"; import env from "./utils/env"; import loggerFactory from "./utils/logger"; +import { BigNumber } from "ethers"; import hre = require("hardhat"); const { ethers } = hre; -const { BigNumber } = ethers; const MAX_DRAW_ITERATIONS = 30; const MAX_EXECUTE_ITERATIONS = 20; const WAIT_FOR_RNG_DURATION = 5 * 1000; // 5 seconds @@ -13,12 +13,17 @@ const ITERATIONS_COOLDOWN_PERIOD = 20 * 1000; // 20 seconds const HIGH_GAS_LIMIT = { gasLimit: 50000000 }; // 50M gas const HEARTBEAT_URL = env.optionalNoDefault("HEARTBEAT_URL_KEEPER_BOT"); const SUBGRAPH_URL = env.require("SUBGRAPH_URL"); +const MAX_JURORS_PER_DISPUTE = 1000; // Skip disputes with more than this number of jurors +const DISPUTES_TO_SKIP = env + .optional("DISPUTES_TO_SKIP", "") + .split(",") + .map((s) => s.trim()); -const loggerOptions = env.optionalNoDefault("LOGTAIL_TOKEN") +const loggerOptions = env.optionalNoDefault("LOGTAIL_TOKEN_KEEPER_BOT") ? { transportTargetOptions: { target: "@logtail/pino", - options: { sourceToken: env.require("LOGTAIL_TOKEN") }, + options: { sourceToken: env.require("LOGTAIL_TOKEN_KEEPER_BOT") }, level: env.optional("LOG_LEVEL", "info"), }, level: env.optional("LOG_LEVEL", "info"), // for pino-pretty @@ -269,30 +274,48 @@ const executeRuling = async (dispute: { id: string }) => { return success; }; -const withdrawAppealContribution = async (dispute: Dispute, contribution: Contribution): Promise => { +const withdrawAppealContribution = async ( + disputeId: string, + roundId: string, + contribution: Contribution +): Promise => { const { disputeKitClassic: kit } = await getContracts(); let success = false; + let amountWithdrawn = BigNumber.from(0); try { + amountWithdrawn = await kit.callStatic.withdrawFeesAndRewards( + disputeId, + contribution.contributor.id, + roundId, + contribution.choice + ); + } catch (e) { logger.info( - `Withdrawing appeal contribution for dispute #${dispute.id}, round #${dispute.currentRoundIndex}, choice ${contribution.choice} and beneficiary ${contribution.contributor.id} ` + `WithdrawFeesAndRewards: will fail for dispute #${disputeId}, round #${roundId}, choice ${contribution.choice} and beneficiary ${contribution.contributor.id}, skipping` + ); + return success; + } + if (amountWithdrawn.isZero()) { + logger.debug( + `WithdrawFeesAndRewards: no fees or rewards to withdraw for dispute #${disputeId}, round #${roundId}, choice ${contribution.choice} and beneficiary ${contribution.contributor.id}, skipping` + ); + return success; + } + try { + logger.info( + `WithdrawFeesAndRewards: appeal contribution for dispute #${disputeId}, round #${roundId}, choice ${contribution.choice} and beneficiary ${contribution.contributor.id}` ); const gas = ( - await kit.estimateGas.withdrawFeesAndRewards( - dispute.id, - contribution.contributor.id, - dispute.currentRoundIndex, - contribution.choice - ) + await kit.estimateGas.withdrawFeesAndRewards(disputeId, contribution.contributor.id, roundId, contribution.choice) ) .mul(150) .div(100); // 50% extra gas - await kit.withdrawFeesAndRewards( - dispute.id, - contribution.contributor.id, - dispute.currentRoundIndex, - contribution.choice, - { gasLimit: gas } - ); + const tx = await ( + await kit.withdrawFeesAndRewards(disputeId, contribution.contributor.id, roundId, contribution.choice, { + gasLimit: gas, + }) + ).wait(); + logger.info(`WithdrawFeesAndRewards txID: ${tx?.transactionHash}`); success = true; } catch (e) { handleError(e); @@ -321,6 +344,15 @@ const getNumberOfMissingRepartitions = async ( : 2 * drawnJurors.length - repartitions.toNumber(); }; +const filterDisputesToSkip = (disputes: Dispute[]) => { + logger.debug( + `Skipping disputes: ${disputes + .filter((dispute) => DISPUTES_TO_SKIP.includes(dispute.id)) + .map((dispute) => dispute.id)}` + ); + return disputes.filter((dispute) => !DISPUTES_TO_SKIP.includes(dispute.id)); +}; + const mapAsync = (array: T[], callbackfn: (value: T, index: number, array: T[]) => Promise): Promise => { return Promise.all(array.map(callbackfn)); }; @@ -381,22 +413,20 @@ async function main() { return PHASES[await sortition.phase()] === Phase.DRAWING; }; + logger.info("Starting up"); + await sendHeartbeat(); logger.info(`Current phase: ${PHASES[await sortition.phase()]}`); - const disputes = await getNonFinalDisputes().catch((e) => handleError(e)); + // Retrieve the disputes which are in a non-final period + let disputes = await getNonFinalDisputes().catch((e) => handleError(e)); if (!disputes) { return; } - for (var dispute of disputes) { - logger.info(`Dispute #${dispute.id}, round #${dispute.currentRoundIndex}, ${dispute.period} period`); - } - - const disputesWithoutJurors = await filterAsync(disputes, async (dispute) => { + let disputesWithoutJurors = await filterAsync(disputes, async (dispute) => { return !(await isDisputeFullyDrawn(dispute)); }); - logger.info(`Disputes needing more jurors: ${disputesWithoutJurors.map((dispute) => dispute.id)}`); // Just a sanity check const numberOfDisputesWithoutJurors = await sortition.disputesWithoutJurors(); @@ -406,6 +436,14 @@ async function main() { logger.error(`SortitionModule.disputesWithoutJurors = ${numberOfDisputesWithoutJurors}`); } + // Skip some disputes + disputes = filterDisputesToSkip(disputes); + disputesWithoutJurors = filterDisputesToSkip(disputesWithoutJurors); + for (var dispute of disputes) { + logger.info(`Dispute #${dispute.id}, round #${dispute.currentRoundIndex}, ${dispute.period} period`); + } + logger.info(`Disputes needing more jurors: ${disputesWithoutJurors.map((dispute) => dispute.id)}`); + if ((await hasMinStakingTimePassed()) && disputesWithoutJurors.length > 0) { // ----------------------------------------------- // // DRAWING ATTEMPT // @@ -431,6 +469,10 @@ async function main() { break; } let numberOfMissingJurors = await getMissingJurors(dispute); + if (numberOfMissingJurors.gt(MAX_JURORS_PER_DISPUTE)) { + logger.warn(`Skipping dispute #${dispute.id} with too many jurors to draw`); + continue; + } do { const drawIterations = Math.min(MAX_DRAW_ITERATIONS, numberOfMissingJurors.toNumber()); logger.info( @@ -481,8 +523,8 @@ async function main() { ); // Disputes union and deduplicate - const unprocessedDisputesInExecution = getUniqueDisputes( - unexecutedDisputes.concat(disputesWithContributionsNotYetWithdrawn).concat(disputes) + const unprocessedDisputesInExecution = filterDisputesToSkip( + getUniqueDisputes(unexecutedDisputes.concat(disputesWithContributionsNotYetWithdrawn).concat(disputes)) ); logger.info(`Disputes not fully executed: ${unprocessedDisputesInExecution.map((dispute) => dispute.id)}`); @@ -539,9 +581,12 @@ async function main() { }); // Remove duplicates which may have a different contribution amount for the same round, choice and beneficiary contributions = [...new Set(contributions)]; - for (var contribution of contributions) { - await withdrawAppealContribution(dispute, contribution); - await delay(ITERATIONS_COOLDOWN_PERIOD); // To avoid spiking the gas price + for (let contribution of contributions) { + // Could be improved by pinpointing exactly which round requires a withdrawal, just try all of them for now. + for (let round = BigNumber.from(dispute.currentRoundIndex); round.gte(0); round = round.sub(1)) { + await withdrawAppealContribution(dispute.id, round.toString(), contribution); + await delay(ITERATIONS_COOLDOWN_PERIOD); // To avoid spiking the gas price + } } } @@ -566,6 +611,7 @@ async function main() { await sendHeartbeat(); + logger.info("Shutting down"); await delay(2000); // Some log messages may be lost otherwise } diff --git a/cspell.json b/cspell.json index 7e9e2a494..f94489bbf 100644 --- a/cspell.json +++ b/cspell.json @@ -13,6 +13,7 @@ "commitlint", "COOLDOWN", "datetime", + "dockerhost", "Ethfinex", "hearbeat", "IERC", @@ -23,7 +24,8 @@ "repartitions", "solhint", "typechain", - "Unslashed" + "Unslashed", + "autorestart" ], "ignoreWords": [], "import": [] diff --git a/services/bots/.env.testnet.example b/services/bots/.env.testnet.example new file mode 100644 index 000000000..7ac85da62 --- /dev/null +++ b/services/bots/.env.testnet.example @@ -0,0 +1,16 @@ +# Bot account +PRIVATE_KEY=0x000000.....00000 + +# Bot subgraph +SUBGRAPH_URL=https://api.thegraph.com/subgraphs/name/alcercu/kleroscoretest + +# Logging +LOG_LEVEL=debug +LOGTAIL_TOKEN_KEEPER_BOT= +LOGTAIL_TOKEN_RELAYER_BOT= + +# Heartbeat +HEARTBEAT_URL_KEEPER_BOT= +HEARTBEAT_URL_RELAYER_BOT= + +DISPUTES_TO_SKIP= \ No newline at end of file diff --git a/services/bots/.gitignore b/services/bots/.gitignore new file mode 100644 index 000000000..16974fb72 --- /dev/null +++ b/services/bots/.gitignore @@ -0,0 +1,2 @@ +.env.testnet +.env.mainnet diff --git a/services/bots/Dockerfile b/services/bots/Dockerfile new file mode 100644 index 000000000..54056ad73 --- /dev/null +++ b/services/bots/Dockerfile @@ -0,0 +1,29 @@ +FROM node:16-alpine + +WORKDIR /usr/src/app + +RUN npm install --ignore-scripts -g pm2 + +COPY --chown=node:node "./contracts" "./contracts" +COPY --chown=node:node "./eslint-config" "./eslint-config" +COPY --chown=node:node "./prettier-config" "./prettier-config" +COPY --chown=node:node "./tsconfig" "./tsconfig" +COPY --chown=node:node "./.yarn" "./.yarn" +COPY --chown=node:node [ ".yarnrc.yml", ".nvmrc", ".eslintignore", "package.json", "yarn.lock", "./" ] + +RUN yarn set version 3.3.1 && \ + yarn --version && \ + node --version && \ + cd contracts && \ + yarn workspaces focus && \ + yarn build && \ + chown -R node:node . + +USER node +WORKDIR /usr/src/app/contracts +ENTRYPOINT [ "yarn" ] + +LABEL org.opencontainers.image.source=https://github.com/kleros/kleros-v2 +LABEL org.opencontainers.image.title="Kleros v2 Bots" +LABEL org.opencontainers.image.description="Bots for the Kleros v2 arbitration protocol." +LABEL org.opencontainers.image.licenses=MIT diff --git a/services/bots/common.yml b/services/bots/common.yml new file mode 100644 index 000000000..41268f7f4 --- /dev/null +++ b/services/bots/common.yml @@ -0,0 +1,11 @@ +version: '3.3' +services: + bot-base: + build: + context: ../../ + dockerfile: ./services/bots/Dockerfile + tags: + - kleros-v2-bots + image: ghcr.io/kleros/kleros-v2-bots + pull_policy: missing + command: --help \ No newline at end of file diff --git a/services/bots/docker-compose.yml b/services/bots/docker-compose.yml new file mode 100644 index 000000000..b07c942d6 --- /dev/null +++ b/services/bots/docker-compose.yml @@ -0,0 +1,70 @@ +version: '3' +services: + keeper-bot-testnet: + extends: + file: common.yml + service: bot-base + # command: bot:keeper --network arbitrumGoerli + entrypoint: + [ + "/bin/sh", + "-c", + "pm2-runtime ecosystem.config.js --only keeper-bot-testnet --no-auto-exit" + ] + # entrypoint: + # [ + # "/bin/sh", + # "-c", + # "pm2-runtime ecosystem.config.js --only foo --no-auto-exit" + # ] + env_file: .env.testnet + volumes: + - type: bind + source: ./ecosystem.config.js + target: /usr/src/app/contracts/ecosystem.config.js + + relayer-bot-from-chiado-testnet: + extends: + file: common.yml + service: bot-base + # command: bot:relayer-from-chiado --network arbitrumGoerli + entrypoint: + [ + "/bin/sh", + "-c", + "pm2-runtime ecosystem.config.js --only relayer-bot-from-chiado-testnet --no-auto-exit" + ] + volumes: + - type: bind + source: ./ecosystem.config.js + target: /usr/src/app/contracts/ecosystem.config.js + profiles: + - chiado + env_file: + - .env.testnet + + relayer-bot-from-goerli-testnet: + extends: + file: common.yml + service: bot-base + command: bot:relayer-from-goerli --network arbitrumGoerli + profiles: + - goerli + env_file: + - .env.testnet + + relayer-bot-from-hardhat-host: + extends: + file: common.yml + service: bot-base + command: bot:relayer-from-hardhat --network dockerhost + extra_hosts: + - host.docker.internal:host-gateway + volumes: + - type: bind + source: ../../contracts/deployments/localhost + target: /usr/src/app/contracts/deployments/localhost + profiles: + - hardhat + env_file: + - .env.testnet diff --git a/services/bots/ecosystem.config.js b/services/bots/ecosystem.config.js new file mode 100644 index 000000000..7ee79d398 --- /dev/null +++ b/services/bots/ecosystem.config.js @@ -0,0 +1,28 @@ +module.exports = { + apps: [ + { + name: "foo", + interpreter: "sh", + script: "yarn", + args: "foo", + restart_delay: 3000, + autorestart: true, + }, + { + name: "keeper-bot-testnet", + interpreter: "sh", + script: "yarn", + args: "bot:keeper --network arbitrumGoerli", + restart_delay: 600000, + autorestart: true, + }, + { + name: "relayer-bot-from-chiado-testnet", + interpreter: "sh", + script: "yarn", + args: "bot:relayer-from-chiado --network arbitrumGoerli", + restart_delay: 5000, + autorestart: true, + }, + ], +}; diff --git a/yarn.lock b/yarn.lock index dd8b2bb91..ba43df44d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5170,6 +5170,7 @@ __metadata: dotenv: ^16.3.1 ethereumjs-util: ^7.1.5 ethers: ^5.7.2 + graphql: ^16.7.1 graphql-request: ^6.1.0 hardhat: ^2.15.0 hardhat-contract-sizer: ^2.10.0