[{"data":1,"prerenderedAt":1888},["ShallowReactive",2],{"audit-gold-exchange-audit":3},{"id":4,"title":5,"auditor":6,"body":7,"date":1877,"description":1878,"extension":1879,"language":1880,"meta":1881,"navigation":332,"path":1882,"project":1883,"seo":1884,"stem":1885,"type":1886,"__hash__":1887},"audits\u002Faudits\u002Fgold-exchange-audit.md","Gold Exchange Protocol","Jordy",{"type":8,"value":9,"toc":1795},"minimark",[10,15,20,24,28,32,35,39,52,56,62,66,126,130,248,252,263,267,270,273,276,279,282,285,296,299,310,313,364,367,534,537,548,552,556,559,562,565,568,571,582,585,589,592,651,654,771,774,785,789,792,795,798,801,804,807,818,821,825,828,857,860,970,973,984,988,991,994,997,1000,1003,1006,1017,1020,1025,1028,1062,1065,1151,1154,1165,1169,1172,1175,1178,1181,1184,1187,1198,1201,1209,1212,1250,1253,1330,1333,1344,1348,1351,1354,1357,1360,1363,1366,1377,1380,1388,1391,1425,1428,1540,1543,1554,1558,1562,1565,1568,1571,1574,1577,1588,1591,1596,1599,1653,1656,1777,1780,1791],[11,12,14],"h2",{"id":13},"owner-mint-bypasses-reserve-checks","Owner Mint Bypasses Reserve Checks",[16,17,19],"h3",{"id":18},"severity-critical","Severity: Critical",[16,21,23],{"id":22},"description","Description",[25,26,27],"p",{},"The GBAR.mint() admin function only checks that GbarVault is configured and amount > 0. It does not evaluate the vault’s GOLD reserves or the oracle at all. Any privileged entity (or a compromised owner key) can arbitrarily mint\nGBAR to the vault and sell it, instantly breaking the 85% collateral promise.",[16,29,31],{"id":30},"impact","Impact",[25,33,34],{},"Full loss of peg: attackers can print infinite GBAR, dump it, and leave the system insolvent.",[16,36,38],{"id":37},"attack-path","Attack Path",[40,41,42,46,49],"ol",{},[43,44,45],"li",{},"Malicious owner calls setGBARVault to point at a wallet they control (optional).",[43,47,48],{},"Call mint(hugeAmount) to mint GBAR straight into that wallet.",[43,50,51],{},"Dump the unbacked tokens or use them to redeem physical gold, draining reserves.",[16,53,55],{"id":54},"affected-components","Affected Components",[57,58,59],"ul",{},[43,60,61],{},"contracts\u002FGBAR.sol:172-193",[16,63,65],{"id":64},"code-samples","Code Samples",[67,68,73],"pre",{"className":69,"code":70,"language":71,"meta":72,"style":72},"language-solidity shiki shiki-themes github-light github-dark","\u002F\u002F contracts\u002FGBAR.sol:183-193\nfunction mint(uint amount) public onlyOwner nonReentrant returns(bool) {\n    if (address(GbarVault) == address(0)) revert GBARVaultNotSet();\n    if (amount == 0) revert AmountCannotBeZero();\n    _totalSupply += amount;\n    _mint(address(GbarVault), amount);\n    return true;\n}\n","solidity","",[74,75,76,84,90,96,102,108,114,120],"code",{"__ignoreMap":72},[77,78,81],"span",{"class":79,"line":80},"line",1,[77,82,83],{},"\u002F\u002F contracts\u002FGBAR.sol:183-193\n",[77,85,87],{"class":79,"line":86},2,[77,88,89],{},"function mint(uint amount) public onlyOwner nonReentrant returns(bool) {\n",[77,91,93],{"class":79,"line":92},3,[77,94,95],{},"    if (address(GbarVault) == address(0)) revert GBARVaultNotSet();\n",[77,97,99],{"class":79,"line":98},4,[77,100,101],{},"    if (amount == 0) revert AmountCannotBeZero();\n",[77,103,105],{"class":79,"line":104},5,[77,106,107],{},"    _totalSupply += amount;\n",[77,109,111],{"class":79,"line":110},6,[77,112,113],{},"    _mint(address(GbarVault), amount);\n",[77,115,117],{"class":79,"line":116},7,[77,118,119],{},"    return true;\n",[77,121,123],{"class":79,"line":122},8,[77,124,125],{},"}\n",[16,127,129],{"id":128},"proof-of-concept-poc","Proof of Concept (PoC)",[67,131,135],{"className":132,"code":133,"language":134,"meta":72,"style":72},"language-typescript shiki shiki-themes github-light github-dark","\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:149-157\nconst backedAmount = calcGbarValue(BigInt(goldSupply), STALE_PRICE);\nconst unbacked = backedAmount * 20n; \u002F\u002F 20x the collateral\nawait gbar.mint(toBN(unbacked));\nexpect(await gbar.totalSupply()).to.equal(toBN(unbacked));\n","typescript",[74,136,137,143,176,203,222],{"__ignoreMap":72},[77,138,139],{"class":79,"line":80},[77,140,142],{"class":141},"sJ8bj","\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:149-157\n",[77,144,145,149,153,156,160,164,167,170,173],{"class":79,"line":86},[77,146,148],{"class":147},"szBVR","const",[77,150,152],{"class":151},"sj4cs"," backedAmount",[77,154,155],{"class":147}," =",[77,157,159],{"class":158},"sScJk"," calcGbarValue",[77,161,163],{"class":162},"sVt8B","(",[77,165,166],{"class":158},"BigInt",[77,168,169],{"class":162},"(goldSupply), ",[77,171,172],{"class":151},"STALE_PRICE",[77,174,175],{"class":162},");\n",[77,177,178,180,183,185,188,191,194,197,200],{"class":79,"line":92},[77,179,148],{"class":147},[77,181,182],{"class":151}," unbacked",[77,184,155],{"class":147},[77,186,187],{"class":162}," backedAmount ",[77,189,190],{"class":147},"*",[77,192,193],{"class":151}," 20",[77,195,196],{"class":147},"n",[77,198,199],{"class":162},"; ",[77,201,202],{"class":141},"\u002F\u002F 20x the collateral\n",[77,204,205,208,211,214,216,219],{"class":79,"line":98},[77,206,207],{"class":147},"await",[77,209,210],{"class":162}," gbar.",[77,212,213],{"class":158},"mint",[77,215,163],{"class":162},[77,217,218],{"class":158},"toBN",[77,220,221],{"class":162},"(unbacked));\n",[77,223,224,227,229,231,233,236,239,242,244,246],{"class":79,"line":104},[77,225,226],{"class":158},"expect",[77,228,163],{"class":162},[77,230,207],{"class":147},[77,232,210],{"class":162},[77,234,235],{"class":158},"totalSupply",[77,237,238],{"class":162},"()).to.",[77,240,241],{"class":158},"equal",[77,243,163],{"class":162},[77,245,218],{"class":158},[77,247,221],{"class":162},[16,249,251],{"id":250},"recommendations","Recommendations",[57,253,254,257,260],{},[43,255,256],{},"Remove or heavily constrain direct admin minting; instead, route all supply changes through collateral-aware flows (goldValueMint with freshness checks).",[43,258,259],{},"If admin mint must exist (e.g., emergency), cap it tightly and require multi-sig plus post-mint proof of reserves.",[43,261,262],{},"Emit events showing reserve checks to aid monitoring.",[11,264,266],{"id":265},"oracle-price-freshness-is-never-validated","Oracle Price Freshness Is Never Validated",[16,268,19],{"id":269},"severity-critical-1",[16,271,23],{"id":272},"description-1",[25,274,275],{},"GoldPriceOracle stores the feed timestamp in lastUpdateTimestamp but getLatestPrice() simply returns the cached value whenever latestPrice != 0. None of the minting or stabilization entry points in GOLD or GBAR verify that the\nprice was updated recently, so a halted oracle keeps being treated as authoritative forever. Because the system mints\u002Fburns GBAR using the USD value of gold, stale USD quotes immediately translate into incorrect collateralization\ndecisions.",[16,277,31],{"id":278},"impact-1",[25,280,281],{},"A single stale price can freeze the peg at an obsolete exchange rate, causing every subsequent mint, stake reward, or stabilization cycle to over-burn or over-mint GBAR. Users depositing or redeeming after a large metal price move\ncan permanently lose value or receive unbacked tokens.",[16,283,38],{"id":284},"attack-path-1",[40,286,287,290,293],{},[43,288,289],{},"Oracle maintainer stops calling setLatestPrice, leaving lastUpdateTimestamp stuck while gold’s market price drifts.",[43,291,292],{},"After days or weeks, any privileged actor invokes mintGoldAndGbar, stakeMint, or stabilize.",[43,294,295],{},"The protocol blindly uses the stale USD quote, so every supply adjustment is computed with obsolete data.",[16,297,55],{"id":298},"affected-components-1",[57,300,301,304,307],{},[43,302,303],{},"contracts\u002Foracles\u002FGoldOracle.sol:10-87",[43,305,306],{},"contracts\u002FGOLD.sol:111-155",[43,308,309],{},"contracts\u002FGBAR.sol:593-624",[16,311,65],{"id":312},"code-samples-1",[67,314,316],{"className":69,"code":315,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002Foracles\u002FGoldOracle.sol:10-41\nuint public lastUpdateTimestamp;\n\nfunction getLatestPrice() public view returns (int) {\n    if (latestPrice == 0) {\n        revert GoldPriceNotSet();\n    }\n    return latestPrice;\n}\n",[74,317,318,323,328,334,339,344,349,354,359],{"__ignoreMap":72},[77,319,320],{"class":79,"line":80},[77,321,322],{},"\u002F\u002F contracts\u002Foracles\u002FGoldOracle.sol:10-41\n",[77,324,325],{"class":79,"line":86},[77,326,327],{},"uint public lastUpdateTimestamp;\n",[77,329,330],{"class":79,"line":92},[77,331,333],{"emptyLinePlaceholder":332},true,"\n",[77,335,336],{"class":79,"line":98},[77,337,338],{},"function getLatestPrice() public view returns (int) {\n",[77,340,341],{"class":79,"line":104},[77,342,343],{},"    if (latestPrice == 0) {\n",[77,345,346],{"class":79,"line":110},[77,347,348],{},"        revert GoldPriceNotSet();\n",[77,350,351],{"class":79,"line":116},[77,352,353],{},"    }\n",[77,355,356],{"class":79,"line":122},[77,357,358],{},"    return latestPrice;\n",[77,360,362],{"class":79,"line":361},9,[77,363,125],{},[16,365,129],{"id":366},"proof-of-concept-poc-1",[67,368,370],{"className":132,"code":369,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:86-95\nit(\"accepts months-old oracle values during stabilization\", async function () {\n    await gold.mintGoldAndGbar(owner.address, 1000);\n    await increaseTime(60 * DAY); \u002F\u002F > 2 months\n    const now = (await ethers.provider.getBlock(\"latest\")).timestamp;\n    expect(now - (await goldOracle.lastUpdateTimestamp())).to.be.gt(50 * DAY);\n    await expect(gbar.stabilize()).to.not.be.reverted; \u002F\u002F stale price still accepted\n});\n",[74,371,372,377,400,419,443,472,510,529],{"__ignoreMap":72},[77,373,374],{"class":79,"line":80},[77,375,376],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:86-95\n",[77,378,379,382,384,388,391,394,397],{"class":79,"line":86},[77,380,381],{"class":158},"it",[77,383,163],{"class":162},[77,385,387],{"class":386},"sZZnC","\"accepts months-old oracle values during stabilization\"",[77,389,390],{"class":162},", ",[77,392,393],{"class":147},"async",[77,395,396],{"class":147}," function",[77,398,399],{"class":162}," () {\n",[77,401,402,405,408,411,414,417],{"class":79,"line":92},[77,403,404],{"class":147},"    await",[77,406,407],{"class":162}," gold.",[77,409,410],{"class":158},"mintGoldAndGbar",[77,412,413],{"class":162},"(owner.address, ",[77,415,416],{"class":151},"1000",[77,418,175],{"class":162},[77,420,421,423,426,428,431,434,437,440],{"class":79,"line":98},[77,422,404],{"class":147},[77,424,425],{"class":158}," increaseTime",[77,427,163],{"class":162},[77,429,430],{"class":151},"60",[77,432,433],{"class":147}," *",[77,435,436],{"class":151}," DAY",[77,438,439],{"class":162},"); ",[77,441,442],{"class":141},"\u002F\u002F > 2 months\n",[77,444,445,448,451,453,456,458,461,464,466,469],{"class":79,"line":104},[77,446,447],{"class":147},"    const",[77,449,450],{"class":151}," now",[77,452,155],{"class":147},[77,454,455],{"class":162}," (",[77,457,207],{"class":147},[77,459,460],{"class":162}," ethers.provider.",[77,462,463],{"class":158},"getBlock",[77,465,163],{"class":162},[77,467,468],{"class":386},"\"latest\"",[77,470,471],{"class":162},")).timestamp;\n",[77,473,474,477,480,483,485,487,490,493,496,499,501,504,506,508],{"class":79,"line":110},[77,475,476],{"class":158},"    expect",[77,478,479],{"class":162},"(now ",[77,481,482],{"class":147},"-",[77,484,455],{"class":162},[77,486,207],{"class":147},[77,488,489],{"class":162}," goldOracle.",[77,491,492],{"class":158},"lastUpdateTimestamp",[77,494,495],{"class":162},"())).to.be.",[77,497,498],{"class":158},"gt",[77,500,163],{"class":162},[77,502,503],{"class":151},"50",[77,505,433],{"class":147},[77,507,436],{"class":151},[77,509,175],{"class":162},[77,511,512,514,517,520,523,526],{"class":79,"line":116},[77,513,404],{"class":147},[77,515,516],{"class":158}," expect",[77,518,519],{"class":162},"(gbar.",[77,521,522],{"class":158},"stabilize",[77,524,525],{"class":162},"()).to.not.be.reverted; ",[77,527,528],{"class":141},"\u002F\u002F stale price still accepted\n",[77,530,531],{"class":79,"line":122},[77,532,533],{"class":162},"});\n",[16,535,251],{"id":536},"recommendations-1",[57,538,539,542,545],{},[43,540,541],{},"Enforce a configurable MAX_PRICE_AGE in getLatestPrice() (or at every call site) and revert when block.timestamp - lastUpdateTimestamp exceeds it.",[43,543,544],{},"Consider sourcing the feed from a battle-tested provider (Chainlink) and aggregating fallback feeds.",[43,546,547],{},"Emit and persist the price age that stabilize, mintGoldAndGbar, and stakeMint used so off-chain monitors can catch anomalies.",[11,549,551],{"id":550},"stabilize-burns-healthy-supply-when-oracle-undervalues-gold","Stabilize Burns Healthy Supply When Oracle Undervalues Gold",[16,553,555],{"id":554},"severity-high","Severity: High",[16,557,23],{"id":558},"description-2",[25,560,561],{},"GBAR.stabilize() compares gbarTotalSupply against gbarValue computed with the oracle price and burns the difference whenever supply exceeds the computed target. If the oracle is stuck on an old, low USD price, gbarValue is\nartificially small and the function happily burns otherwise correctly backed GBAR from the vault.",[16,563,31],{"id":564},"impact-2",[25,566,567],{},"The on-chain supply shrinks even though the vault is fully collateralized, forcing redemptions to fail, squeezing the secondary-market price upward, and permanently harming users who minted at the correct price.",[16,569,38],{"id":570},"attack-path-2",[40,572,573,576,579],{},[43,574,575],{},"Oracle price lags the real market and reports $2,000\u002Foz while the vault actually holds gold worth $4,200\u002Foz.",[43,577,578],{},"Supply was minted using the real price (e.g., via emergency mint after fixing the oracle off-chain).",[43,580,581],{},"Once the 28-day timer unlocks, stabilize() is called and burns gbarTotalSupply - gbarValue(stale price) from GbarVault, destroying healthy liquidity.",[16,583,55],{"id":584},"affected-components-2",[57,586,587],{},[43,588,309],{},[16,590,65],{"id":591},"code-samples-2",[67,593,595],{"className":69,"code":594,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002FGBAR.sol:593-624\n(uint goldPriceGram,, uint gbarValue) = GoldOracle.getGoldGbarConversion(goldTotalSupply);\n\nif (gbarTotalSupply > gbarValue) {\n    uint amountToBurn = gbarTotalSupply - gbarValue;\n    if (vaultBalance >= amountToBurn) {\n        _burn(address(GbarVault), amountToBurn);\n    } else {\n        _burn(address(GbarVault), vaultBalance);\n    }\n}\n",[74,596,597,602,607,611,616,621,626,631,636,641,646],{"__ignoreMap":72},[77,598,599],{"class":79,"line":80},[77,600,601],{},"\u002F\u002F contracts\u002FGBAR.sol:593-624\n",[77,603,604],{"class":79,"line":86},[77,605,606],{},"(uint goldPriceGram,, uint gbarValue) = GoldOracle.getGoldGbarConversion(goldTotalSupply);\n",[77,608,609],{"class":79,"line":92},[77,610,333],{"emptyLinePlaceholder":332},[77,612,613],{"class":79,"line":98},[77,614,615],{},"if (gbarTotalSupply > gbarValue) {\n",[77,617,618],{"class":79,"line":104},[77,619,620],{},"    uint amountToBurn = gbarTotalSupply - gbarValue;\n",[77,622,623],{"class":79,"line":110},[77,624,625],{},"    if (vaultBalance >= amountToBurn) {\n",[77,627,628],{"class":79,"line":116},[77,629,630],{},"        _burn(address(GbarVault), amountToBurn);\n",[77,632,633],{"class":79,"line":122},[77,634,635],{},"    } else {\n",[77,637,638],{"class":79,"line":361},[77,639,640],{},"        _burn(address(GbarVault), vaultBalance);\n",[77,642,644],{"class":79,"line":643},10,[77,645,353],{},[77,647,649],{"class":79,"line":648},11,[77,650,125],{},[16,652,129],{"id":653},"proof-of-concept-poc-2",[67,655,657],{"className":132,"code":656,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:96-109\nconst backedSupply = calcGbarValue(BigInt(goldSupply), FRESH_PRICE); \u002F\u002F real $4,200 price\nawait gbar.mint(toBN(backedSupply));\nawait increaseTime(29 * DAY);          \u002F\u002F allow stabilization\nawait gbar.stabilize();                \u002F\u002F burns down to calc(..., STALE_PRICE)\nexpect(await gbar.totalSupply()).to.equal(calcGbarValue(BigInt(goldSupply), STALE_PRICE));\n",[74,658,659,664,689,704,725,739],{"__ignoreMap":72},[77,660,661],{"class":79,"line":80},[77,662,663],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:96-109\n",[77,665,666,668,671,673,675,677,679,681,684,686],{"class":79,"line":86},[77,667,148],{"class":147},[77,669,670],{"class":151}," backedSupply",[77,672,155],{"class":147},[77,674,159],{"class":158},[77,676,163],{"class":162},[77,678,166],{"class":158},[77,680,169],{"class":162},[77,682,683],{"class":151},"FRESH_PRICE",[77,685,439],{"class":162},[77,687,688],{"class":141},"\u002F\u002F real $4,200 price\n",[77,690,691,693,695,697,699,701],{"class":79,"line":92},[77,692,207],{"class":147},[77,694,210],{"class":162},[77,696,213],{"class":158},[77,698,163],{"class":162},[77,700,218],{"class":158},[77,702,703],{"class":162},"(backedSupply));\n",[77,705,706,708,710,712,715,717,719,722],{"class":79,"line":98},[77,707,207],{"class":147},[77,709,425],{"class":158},[77,711,163],{"class":162},[77,713,714],{"class":151},"29",[77,716,433],{"class":147},[77,718,436],{"class":151},[77,720,721],{"class":162},");          ",[77,723,724],{"class":141},"\u002F\u002F allow stabilization\n",[77,726,727,729,731,733,736],{"class":79,"line":104},[77,728,207],{"class":147},[77,730,210],{"class":162},[77,732,522],{"class":158},[77,734,735],{"class":162},"();                ",[77,737,738],{"class":141},"\u002F\u002F burns down to calc(..., STALE_PRICE)\n",[77,740,741,743,745,747,749,751,753,755,757,760,762,764,766,768],{"class":79,"line":110},[77,742,226],{"class":158},[77,744,163],{"class":162},[77,746,207],{"class":147},[77,748,210],{"class":162},[77,750,235],{"class":158},[77,752,238],{"class":162},[77,754,241],{"class":158},[77,756,163],{"class":162},[77,758,759],{"class":158},"calcGbarValue",[77,761,163],{"class":162},[77,763,166],{"class":158},[77,765,169],{"class":162},[77,767,172],{"class":151},[77,769,770],{"class":162},"));\n",[16,772,251],{"id":773},"recommendations-2",[57,775,776,779,782],{},[43,777,778],{},"Require a fresh oracle price before running stabilization (see Issue #1).",[43,780,781],{},"Include tolerance bands so minor oracle deviations don’t annihilate supply immediately.",[43,783,784],{},"Consider storing the USD value of collateral at mint time so stabilization can reason about historical prices instead of trusting a single snapshot.",[11,786,788],{"id":787},"stabilize-mints-unbacked-gbar-when-oracle-overvalues-gold","Stabilize Mints Unbacked GBAR When Oracle Overvalues Gold",[16,790,555],{"id":791},"severity-high-1",[16,793,23],{"id":794},"description-3",[25,796,797],{},"The same stabilization logic mints amountToMint = gbarValue - gbarTotalSupply whenever the oracle implies that supply is too low. When the oracle is stuck on a high USD price while gold has fallen, this branch mints free GBAR even\nthough the vault cannot back it.",[16,799,31],{"id":800},"impact-3",[25,802,803],{},"Attackers monitoring the stale price can front-run a stabilization call, receive newly minted GBAR, and dump it before anyone notices it is unbacked, directly harming peg credibility.",[16,805,38],{"id":806},"attack-path-3",[40,808,809,812,815],{},[43,810,811],{},"Oracle shows an old $4,200 price while the real market has dropped to $2,000.",[43,813,814],{},"gbarTotalSupply still matches the real collateral.",[43,816,817],{},"stabilize() mints gbarValue(high price) - gbarTotalSupply tokens to the vault, creating uncollateralized inventory ready for sale.",[16,819,55],{"id":820},"affected-components-3",[57,822,823],{},[43,824,309],{},[16,826,65],{"id":827},"code-samples-3",[67,829,831],{"className":69,"code":830,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002FGBAR.sol:620-624\n} else if (gbarValue > gbarTotalSupply) {\n    uint amountToMint = gbarValue - gbarTotalSupply;\n    mint(amountToMint);\n}\n",[74,832,833,838,843,848,853],{"__ignoreMap":72},[77,834,835],{"class":79,"line":80},[77,836,837],{},"\u002F\u002F contracts\u002FGBAR.sol:620-624\n",[77,839,840],{"class":79,"line":86},[77,841,842],{},"} else if (gbarValue > gbarTotalSupply) {\n",[77,844,845],{"class":79,"line":92},[77,846,847],{},"    uint amountToMint = gbarValue - gbarTotalSupply;\n",[77,849,850],{"class":79,"line":98},[77,851,852],{},"    mint(amountToMint);\n",[77,854,855],{"class":79,"line":104},[77,856,125],{},[16,858,129],{"id":859},"proof-of-concept-poc-3",[67,861,863],{"className":132,"code":862,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:111-125\nconst staleSupply = calcGbarValue(BigInt(goldSupply), STALE_PRICE); \u002F\u002F real price is low\nawait gbar.mint(toBN(staleSupply));\nawait goldOracle.setLatestPrice(ethers.BigNumber.from(FRESH_PRICE.toString())); \u002F\u002F stale high quote\nawait increaseTime(29 * DAY);\nawait gbar.stabilize(); \u002F\u002F totalSupply jumps to calc(..., FRESH_PRICE) with no new gold\n",[74,864,865,870,894,909,940,956],{"__ignoreMap":72},[77,866,867],{"class":79,"line":80},[77,868,869],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:111-125\n",[77,871,872,874,877,879,881,883,885,887,889,891],{"class":79,"line":86},[77,873,148],{"class":147},[77,875,876],{"class":151}," staleSupply",[77,878,155],{"class":147},[77,880,159],{"class":158},[77,882,163],{"class":162},[77,884,166],{"class":158},[77,886,169],{"class":162},[77,888,172],{"class":151},[77,890,439],{"class":162},[77,892,893],{"class":141},"\u002F\u002F real price is low\n",[77,895,896,898,900,902,904,906],{"class":79,"line":92},[77,897,207],{"class":147},[77,899,210],{"class":162},[77,901,213],{"class":158},[77,903,163],{"class":162},[77,905,218],{"class":158},[77,907,908],{"class":162},"(staleSupply));\n",[77,910,911,913,915,918,921,924,926,928,931,934,937],{"class":79,"line":98},[77,912,207],{"class":147},[77,914,489],{"class":162},[77,916,917],{"class":158},"setLatestPrice",[77,919,920],{"class":162},"(ethers.BigNumber.",[77,922,923],{"class":158},"from",[77,925,163],{"class":162},[77,927,683],{"class":151},[77,929,930],{"class":162},".",[77,932,933],{"class":158},"toString",[77,935,936],{"class":162},"())); ",[77,938,939],{"class":141},"\u002F\u002F stale high quote\n",[77,941,942,944,946,948,950,952,954],{"class":79,"line":104},[77,943,207],{"class":147},[77,945,425],{"class":158},[77,947,163],{"class":162},[77,949,714],{"class":151},[77,951,433],{"class":147},[77,953,436],{"class":151},[77,955,175],{"class":162},[77,957,958,960,962,964,967],{"class":79,"line":110},[77,959,207],{"class":147},[77,961,210],{"class":162},[77,963,522],{"class":158},[77,965,966],{"class":162},"(); ",[77,968,969],{"class":141},"\u002F\u002F totalSupply jumps to calc(..., FRESH_PRICE) with no new gold\n",[16,971,251],{"id":972},"recommendations-3",[57,974,975,978,981],{},[43,976,977],{},"Couple stabilization with trusted price feeds and multiple sources; pause minting if the oracle age or deviation exceeds thresholds.",[43,979,980],{},"Require proof of physical gold balances (vault attestations) before minting as part of stabilization.",[43,982,983],{},"Consider capping amountToMint per cycle to limit damage if the oracle lies.",[11,985,987],{"id":986},"mintgoldandgbar-uses-stale-oracle-data","mintGoldAndGbar Uses Stale Oracle Data",[16,989,555],{"id":990},"severity-high-2",[16,992,23],{"id":993},"description-4",[25,995,996],{},"GOLD.mintGoldAndGbar() mints GBAR equal to 85% of the USD value returned by _goldOracle.getGoldGbarConversion(amount) without verifying how recent the quote is. When gold rallies, depositors continue receiving the lower USD amount,\nwhile a sudden drop rewards them with too many tokens.",[16,998,31],{"id":999},"impact-4",[25,1001,1002],{},"Depositors are systematically overcharged or underpaid relative to the 85% promise, directly impacting collateralization and user trust.",[16,1004,38],{"id":1005},"attack-path-4",[40,1007,1008,1011,1014],{},[43,1009,1010],{},"Oracle stops updating while gold price doubles.",[43,1012,1013],{},"Admin mints GOLD and GBAR to onboard new metal deposits.",[43,1015,1016],{},"_goldOracle.getGoldGbarConversion keeps returning the old USD price, so depositors get only half the GBAR they are due.",[16,1018,55],{"id":1019},"affected-components-4",[57,1021,1022],{},[43,1023,1024],{},"contracts\u002FGOLD.sol:111-127",[16,1026,65],{"id":1027},"code-samples-4",[67,1029,1031],{"className":69,"code":1030,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002FGOLD.sol:111-127\n(,,uint gbarValue) = _goldOracle.getGoldGbarConversion(amount);\nbool success = _gbar.goldValueMint(gbarValue);\nrequire(success, \"Error minting GBAR\");\n\n_mint(to, amount);\n",[74,1032,1033,1038,1043,1048,1053,1057],{"__ignoreMap":72},[77,1034,1035],{"class":79,"line":80},[77,1036,1037],{},"\u002F\u002F contracts\u002FGOLD.sol:111-127\n",[77,1039,1040],{"class":79,"line":86},[77,1041,1042],{},"(,,uint gbarValue) = _goldOracle.getGoldGbarConversion(amount);\n",[77,1044,1045],{"class":79,"line":92},[77,1046,1047],{},"bool success = _gbar.goldValueMint(gbarValue);\n",[77,1049,1050],{"class":79,"line":98},[77,1051,1052],{},"require(success, \"Error minting GBAR\");\n",[77,1054,1055],{"class":79,"line":104},[77,1056,333],{"emptyLinePlaceholder":332},[77,1058,1059],{"class":79,"line":110},[77,1060,1061],{},"_mint(to, amount);\n",[16,1063,129],{"id":1064},"proof-of-concept-poc-4",[67,1066,1068],{"className":132,"code":1067,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:127-136\nawait gold.mintGoldAndGbar(owner.address, 500);\nconst minted = (await gbar.balanceOf(gbarVault.address)).sub(before);\nexpect(minted.toString()).to.equal(calcGbarValue(500n, STALE_PRICE));\n\u002F\u002F mismatches calcGbarValue(..., FRESH_PRICE) when real price is higher\n",[74,1069,1070,1075,1090,1117,1146],{"__ignoreMap":72},[77,1071,1072],{"class":79,"line":80},[77,1073,1074],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:127-136\n",[77,1076,1077,1079,1081,1083,1085,1088],{"class":79,"line":86},[77,1078,207],{"class":147},[77,1080,407],{"class":162},[77,1082,410],{"class":158},[77,1084,413],{"class":162},[77,1086,1087],{"class":151},"500",[77,1089,175],{"class":162},[77,1091,1092,1094,1097,1099,1101,1103,1105,1108,1111,1114],{"class":79,"line":92},[77,1093,148],{"class":147},[77,1095,1096],{"class":151}," minted",[77,1098,155],{"class":147},[77,1100,455],{"class":162},[77,1102,207],{"class":147},[77,1104,210],{"class":162},[77,1106,1107],{"class":158},"balanceOf",[77,1109,1110],{"class":162},"(gbarVault.address)).",[77,1112,1113],{"class":158},"sub",[77,1115,1116],{"class":162},"(before);\n",[77,1118,1119,1121,1124,1126,1128,1130,1132,1134,1136,1138,1140,1142,1144],{"class":79,"line":98},[77,1120,226],{"class":158},[77,1122,1123],{"class":162},"(minted.",[77,1125,933],{"class":158},[77,1127,238],{"class":162},[77,1129,241],{"class":158},[77,1131,163],{"class":162},[77,1133,759],{"class":158},[77,1135,163],{"class":162},[77,1137,1087],{"class":151},[77,1139,196],{"class":147},[77,1141,390],{"class":162},[77,1143,172],{"class":151},[77,1145,770],{"class":162},[77,1147,1148],{"class":79,"line":104},[77,1149,1150],{"class":141},"\u002F\u002F mismatches calcGbarValue(..., FRESH_PRICE) when real price is higher\n",[16,1152,251],{"id":1153},"recommendations-4",[57,1155,1156,1159,1162],{},[43,1157,1158],{},"Check block.timestamp - _goldOracle.lastUpdateTimestamp() before minting and revert if the feed is stale.",[43,1160,1161],{},"Allow the caller to pass in a signed price proof (e.g., Chainlink latest round) so the contract verifies freshness on-chain.",[43,1163,1164],{},"Log the price used per mint for auditability.",[11,1166,1168],{"id":1167},"stakemint-rewards-are-calculated-from-stale-data","stakeMint Rewards Are Calculated From Stale Data",[16,1170,555],{"id":1171},"severity-high-3",[16,1173,23],{"id":1174},"description-5",[25,1176,1177],{},"GOLD.stakeMint() mints GBAR staking rewards based on _goldOracle.getGoldGbarConversion(amount) under the same assumptions as mintGoldAndGbar. When the price feed lags, stakers receive the wrong USD-equivalent reward and the staking\npool balance departs from expectations.",[16,1179,31],{"id":1180},"impact-5",[25,1182,1183],{},"The staking program can either be drained (when oracle price is high and real price is low) or underpay legitimate stakers (when the real price is higher), destabilizing incentives.",[16,1185,38],{"id":1186},"attack-path-5",[40,1188,1189,1192,1195],{},[43,1190,1191],{},"Price feed is stale during a gold spike.",[43,1193,1194],{},"Admin calls stakeMint for a marketing campaign.",[43,1196,1197],{},"Stakers only receive rewards priced at the old lower price.",[16,1199,55],{"id":1200},"affected-components-5",[57,1202,1203,1206],{},[43,1204,1205],{},"contracts\u002FGOLD.sol:130-162",[43,1207,1208],{},"contracts\u002FGBAR.sol:198-218 (called indirectly)",[16,1210,65],{"id":1211},"code-samples-5",[67,1213,1215],{"className":69,"code":1214,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002FGOLD.sol:138-156\n(,,uint gbarValue) = _goldOracle.getGoldGbarConversion(amount);\nbool gbarMintSuccess = _gbar.goldValueMint(gbarValue);\nrequire(gbarMintSuccess, \"Error minting GBAR\");\n\n_mint(address(this), amount);\n_stakeVault.mintStake(amount, staker);\n",[74,1216,1217,1222,1226,1231,1236,1240,1245],{"__ignoreMap":72},[77,1218,1219],{"class":79,"line":80},[77,1220,1221],{},"\u002F\u002F contracts\u002FGOLD.sol:138-156\n",[77,1223,1224],{"class":79,"line":86},[77,1225,1042],{},[77,1227,1228],{"class":79,"line":92},[77,1229,1230],{},"bool gbarMintSuccess = _gbar.goldValueMint(gbarValue);\n",[77,1232,1233],{"class":79,"line":98},[77,1234,1235],{},"require(gbarMintSuccess, \"Error minting GBAR\");\n",[77,1237,1238],{"class":79,"line":104},[77,1239,333],{"emptyLinePlaceholder":332},[77,1241,1242],{"class":79,"line":110},[77,1243,1244],{},"_mint(address(this), amount);\n",[77,1246,1247],{"class":79,"line":116},[77,1248,1249],{},"_stakeVault.mintStake(amount, staker);\n",[16,1251,129],{"id":1252},"proof-of-concept-poc-5",[67,1254,1256],{"className":132,"code":1255,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:138-147\nawait gold.stakeMint(user.address, 250);\nconst minted = (await gbar.balanceOf(gbarVault.address)).sub(before);\nexpect(minted.toString()).to.equal(calcGbarValue(250n, STALE_PRICE));\n",[74,1257,1258,1263,1280,1302],{"__ignoreMap":72},[77,1259,1260],{"class":79,"line":80},[77,1261,1262],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:138-147\n",[77,1264,1265,1267,1269,1272,1275,1278],{"class":79,"line":86},[77,1266,207],{"class":147},[77,1268,407],{"class":162},[77,1270,1271],{"class":158},"stakeMint",[77,1273,1274],{"class":162},"(user.address, ",[77,1276,1277],{"class":151},"250",[77,1279,175],{"class":162},[77,1281,1282,1284,1286,1288,1290,1292,1294,1296,1298,1300],{"class":79,"line":92},[77,1283,148],{"class":147},[77,1285,1096],{"class":151},[77,1287,155],{"class":147},[77,1289,455],{"class":162},[77,1291,207],{"class":147},[77,1293,210],{"class":162},[77,1295,1107],{"class":158},[77,1297,1110],{"class":162},[77,1299,1113],{"class":158},[77,1301,1116],{"class":162},[77,1303,1304,1306,1308,1310,1312,1314,1316,1318,1320,1322,1324,1326,1328],{"class":79,"line":98},[77,1305,226],{"class":158},[77,1307,1123],{"class":162},[77,1309,933],{"class":158},[77,1311,238],{"class":162},[77,1313,241],{"class":158},[77,1315,163],{"class":162},[77,1317,759],{"class":158},[77,1319,163],{"class":162},[77,1321,1277],{"class":151},[77,1323,196],{"class":147},[77,1325,390],{"class":162},[77,1327,172],{"class":151},[77,1329,770],{"class":162},[16,1331,251],{"id":1332},"recommendations-5",[57,1334,1335,1338,1341],{},[43,1336,1337],{},"Share the same freshness guardrails as Issue #4.",[43,1339,1340],{},"Consider averaging prices over multiple recent updates so a single stale value cannot skew rewards.",[43,1342,1343],{},"Record the price used per reward cycle for later reconciliation.",[11,1345,1347],{"id":1346},"gold-withdrawals-never-burn-supply","GOLD Withdrawals Never Burn Supply",[16,1349,555],{"id":1350},"severity-high-4",[16,1352,23],{"id":1353},"description-6",[25,1355,1356],{},"Neither GOLD nor GoldVault.withdrawTo() ever burn tokens when physical gold leaves custody. Withdrawals just transfer GOLD back to the recipient while total supply is unchanged, so a gram that left the vault still has a live token\nin circulation. This breaks the 1:1 mapping between outstanding GOLD and the underlying bullion and makes redemption math impossible.",[16,1358,31],{"id":1359},"impact-6",[25,1361,1362],{},"Vault operators can re-use withdrawn tokens to mint GBAR or sell them while the corresponding metal is gone, turning the system into a fractional-reserve scheme without transparency.",[16,1364,38],{"id":1365},"attack-path-6",[40,1367,1368,1371,1374],{},[43,1369,1370],{},"Owner mints GOLD representing 50 grams and user deposits it into GoldVault.",[43,1372,1373],{},"Owner executes withdrawTo to send the tokens back when releasing the physical bar.",[43,1375,1376],{},"Total supply remains 50, so the same tokens can be resold while the gold is no longer there.",[16,1378,55],{"id":1379},"affected-components-6",[57,1381,1382,1385],{},[43,1383,1384],{},"contracts\u002FGOLD.sol (no burn functionality)",[43,1386,1387],{},"contracts\u002Fvaults\u002FGoldVault.sol:47-84",[16,1389,65],{"id":1390},"code-samples-6",[67,1392,1394],{"className":69,"code":1393,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002Fvaults\u002FGoldVault.sol:64-84\nfunction withdrawTo(address to, uint amount) external onlyOwner nonReentrant {\n    if (amount > GoldToken.balanceOf(address(this))) revert AmountExceedsBalance();\n    GoldToken.transfer(to, amount); \u002F\u002F no burn, supply unchanged\n    emit WithdrawnTo(to, amount);\n}\n",[74,1395,1396,1401,1406,1411,1416,1421],{"__ignoreMap":72},[77,1397,1398],{"class":79,"line":80},[77,1399,1400],{},"\u002F\u002F contracts\u002Fvaults\u002FGoldVault.sol:64-84\n",[77,1402,1403],{"class":79,"line":86},[77,1404,1405],{},"function withdrawTo(address to, uint amount) external onlyOwner nonReentrant {\n",[77,1407,1408],{"class":79,"line":92},[77,1409,1410],{},"    if (amount > GoldToken.balanceOf(address(this))) revert AmountExceedsBalance();\n",[77,1412,1413],{"class":79,"line":98},[77,1414,1415],{},"    GoldToken.transfer(to, amount); \u002F\u002F no burn, supply unchanged\n",[77,1417,1418],{"class":79,"line":104},[77,1419,1420],{},"    emit WithdrawnTo(to, amount);\n",[77,1422,1423],{"class":79,"line":110},[77,1424,125],{},[16,1426,129],{"id":1427},"proof-of-concept-poc-6",[67,1429,1431],{"className":132,"code":1430,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:159-168\nawait gold.mint(owner.address, 50);\nawait gold.approve(goldVault.address, 50);\nawait goldVault.deposit(50);\nconst totalBefore = await gold.totalSupply();\nawait goldVault.withdrawTo(owner.address, 50);\nexpect(await gold.totalSupply()).to.equal(totalBefore); \u002F\u002F still 50 despite physical exit\n",[74,1432,1433,1438,1452,1468,1484,1503,1518],{"__ignoreMap":72},[77,1434,1435],{"class":79,"line":80},[77,1436,1437],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:159-168\n",[77,1439,1440,1442,1444,1446,1448,1450],{"class":79,"line":86},[77,1441,207],{"class":147},[77,1443,407],{"class":162},[77,1445,213],{"class":158},[77,1447,413],{"class":162},[77,1449,503],{"class":151},[77,1451,175],{"class":162},[77,1453,1454,1456,1458,1461,1464,1466],{"class":79,"line":92},[77,1455,207],{"class":147},[77,1457,407],{"class":162},[77,1459,1460],{"class":158},"approve",[77,1462,1463],{"class":162},"(goldVault.address, ",[77,1465,503],{"class":151},[77,1467,175],{"class":162},[77,1469,1470,1472,1475,1478,1480,1482],{"class":79,"line":98},[77,1471,207],{"class":147},[77,1473,1474],{"class":162}," goldVault.",[77,1476,1477],{"class":158},"deposit",[77,1479,163],{"class":162},[77,1481,503],{"class":151},[77,1483,175],{"class":162},[77,1485,1486,1488,1491,1493,1496,1498,1500],{"class":79,"line":104},[77,1487,148],{"class":147},[77,1489,1490],{"class":151}," totalBefore",[77,1492,155],{"class":147},[77,1494,1495],{"class":147}," await",[77,1497,407],{"class":162},[77,1499,235],{"class":158},[77,1501,1502],{"class":162},"();\n",[77,1504,1505,1507,1509,1512,1514,1516],{"class":79,"line":110},[77,1506,207],{"class":147},[77,1508,1474],{"class":162},[77,1510,1511],{"class":158},"withdrawTo",[77,1513,413],{"class":162},[77,1515,503],{"class":151},[77,1517,175],{"class":162},[77,1519,1520,1522,1524,1526,1528,1530,1532,1534,1537],{"class":79,"line":116},[77,1521,226],{"class":158},[77,1523,163],{"class":162},[77,1525,207],{"class":147},[77,1527,407],{"class":162},[77,1529,235],{"class":158},[77,1531,238],{"class":162},[77,1533,241],{"class":158},[77,1535,1536],{"class":162},"(totalBefore); ",[77,1538,1539],{"class":141},"\u002F\u002F still 50 despite physical exit\n",[16,1541,251],{"id":1542},"recommendations-6",[57,1544,1545,1548,1551],{},[43,1546,1547],{},"Add an owner-only burn function in GOLD and call it whenever physical gold is redeemed (either directly in withdrawTo or via a withdrawal workflow).",[43,1549,1550],{},"Track outstanding redemption requests separately and ensure their amounts are removed from total supply.",[43,1552,1553],{},"Publish regular proof-of-reserves matching on-chain supply to audited vault holdings.",[11,1555,1557],{"id":1556},"retrieval-requests-ignore-wallet-balances","Retrieval Requests Ignore Wallet Balances",[16,1559,1561],{"id":1560},"severity-medium","Severity: Medium",[16,1563,23],{"id":1564},"description-7",[25,1566,1567],{},"GBAR.createRetrievalRequest() lets a retrieval guard push any (from, amount) pair into the queue without checking balanceOf(from). Once enough guards confirm it, executeRetrievalRequest() tries to burn the requested amount from the\nuser. If the user’s balance is smaller, _burn reverts with “burn amount exceeds balance”, leaving the request permanently unexecutable because there is no cancellation path.",[16,1569,31],{"id":1570},"impact-7",[25,1572,1573],{},"A single malicious (or careless) guard can brick the retrieval queue for an address, forcing every execution attempt to revert and wasting gas. Operators cannot delete the bad request, so legitimate withdrawals for that user become\nimpossible.",[16,1575,38],{"id":1576},"attack-path-7",[40,1578,1579,1582,1585],{},[43,1580,1581],{},"Guard submits createRetrievalRequest(user, 10_000 GBAR) even though user holds 0.",[43,1583,1584],{},"Guards confirm the request.",[43,1586,1587],{},"Any attempt to execute the request reverts because _burn fails, and the stuck entry cannot be removed.",[16,1589,55],{"id":1590},"affected-components-7",[57,1592,1593],{},[43,1594,1595],{},"contracts\u002FGBAR.sol:453-539",[16,1597,65],{"id":1598},"code-samples-7",[67,1600,1602],{"className":69,"code":1601,"language":71,"meta":72,"style":72},"\u002F\u002F contracts\u002FGBAR.sol:463-481\nfunction createRetrievalRequest(address from, uint amount) external onlyRetrievalGuard nonReentrant {\n    if (from == address(0) || amount == 0) revert ...;\n    retrievalRequests.push(RetrievalRequest({\n        from: from,\n        amount: amount,\n        numConfirmations: 0,\n        executed: false\n    }));\n}\n",[74,1603,1604,1609,1614,1619,1624,1629,1634,1639,1644,1649],{"__ignoreMap":72},[77,1605,1606],{"class":79,"line":80},[77,1607,1608],{},"\u002F\u002F contracts\u002FGBAR.sol:463-481\n",[77,1610,1611],{"class":79,"line":86},[77,1612,1613],{},"function createRetrievalRequest(address from, uint amount) external onlyRetrievalGuard nonReentrant {\n",[77,1615,1616],{"class":79,"line":92},[77,1617,1618],{},"    if (from == address(0) || amount == 0) revert ...;\n",[77,1620,1621],{"class":79,"line":98},[77,1622,1623],{},"    retrievalRequests.push(RetrievalRequest({\n",[77,1625,1626],{"class":79,"line":104},[77,1627,1628],{},"        from: from,\n",[77,1630,1631],{"class":79,"line":110},[77,1632,1633],{},"        amount: amount,\n",[77,1635,1636],{"class":79,"line":116},[77,1637,1638],{},"        numConfirmations: 0,\n",[77,1640,1641],{"class":79,"line":122},[77,1642,1643],{},"        executed: false\n",[77,1645,1646],{"class":79,"line":361},[77,1647,1648],{},"    }));\n",[77,1650,1651],{"class":79,"line":643},[77,1652,125],{},[16,1654,129],{"id":1655},"proof-of-concept-poc-7",[67,1657,1659],{"className":132,"code":1658,"language":134,"meta":72,"style":72},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:170-180\nawait gbar.connect(guardOne).createRetrievalRequest(user.address, parseUnits(\"10\", 6));\nawait gbar.connect(guardOne).confirmRetrievalRequest(0);\nawait gbar.connect(guardTwo).confirmRetrievalRequest(0);\nawait expect(gbar.connect(guardOne).executeRetrievalRequest(0))\n.to.be.revertedWith(\"ERC20: burn amount exceeds balance\"); \u002F\u002F request now stuck forever\n",[74,1660,1661,1666,1698,1718,1737,1759],{"__ignoreMap":72},[77,1662,1663],{"class":79,"line":80},[77,1664,1665],{"class":141},"\u002F\u002F test\u002Fhardhat\u002Faudit.poc.ts:170-180\n",[77,1667,1668,1670,1672,1675,1678,1681,1683,1686,1688,1691,1693,1696],{"class":79,"line":86},[77,1669,207],{"class":147},[77,1671,210],{"class":162},[77,1673,1674],{"class":158},"connect",[77,1676,1677],{"class":162},"(guardOne).",[77,1679,1680],{"class":158},"createRetrievalRequest",[77,1682,1274],{"class":162},[77,1684,1685],{"class":158},"parseUnits",[77,1687,163],{"class":162},[77,1689,1690],{"class":386},"\"10\"",[77,1692,390],{"class":162},[77,1694,1695],{"class":151},"6",[77,1697,770],{"class":162},[77,1699,1700,1702,1704,1706,1708,1711,1713,1716],{"class":79,"line":92},[77,1701,207],{"class":147},[77,1703,210],{"class":162},[77,1705,1674],{"class":158},[77,1707,1677],{"class":162},[77,1709,1710],{"class":158},"confirmRetrievalRequest",[77,1712,163],{"class":162},[77,1714,1715],{"class":151},"0",[77,1717,175],{"class":162},[77,1719,1720,1722,1724,1726,1729,1731,1733,1735],{"class":79,"line":98},[77,1721,207],{"class":147},[77,1723,210],{"class":162},[77,1725,1674],{"class":158},[77,1727,1728],{"class":162},"(guardTwo).",[77,1730,1710],{"class":158},[77,1732,163],{"class":162},[77,1734,1715],{"class":151},[77,1736,175],{"class":162},[77,1738,1739,1741,1743,1745,1747,1749,1752,1754,1756],{"class":79,"line":104},[77,1740,207],{"class":147},[77,1742,516],{"class":158},[77,1744,519],{"class":162},[77,1746,1674],{"class":158},[77,1748,1677],{"class":162},[77,1750,1751],{"class":158},"executeRetrievalRequest",[77,1753,163],{"class":162},[77,1755,1715],{"class":151},[77,1757,1758],{"class":162},"))\n",[77,1760,1761,1764,1767,1769,1772,1774],{"class":79,"line":110},[77,1762,1763],{"class":162},".to.be.",[77,1765,1766],{"class":158},"revertedWith",[77,1768,163],{"class":162},[77,1770,1771],{"class":386},"\"ERC20: burn amount exceeds balance\"",[77,1773,439],{"class":162},[77,1775,1776],{"class":141},"\u002F\u002F request now stuck forever\n",[16,1778,251],{"id":1779},"recommendations-7",[57,1781,1782,1785,1788],{},[43,1783,1784],{},"Add require(balanceOf(from) >= amount) to createRetrievalRequest (or at least to confirm).",[43,1786,1787],{},"Provide a cancellation path so guards can delete or adjust invalid requests.",[43,1789,1790],{},"Consider pulling funds into escrow before confirmations to guarantee executability.",[1792,1793,1794],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":72,"searchDepth":86,"depth":86,"links":1796},[1797,1807,1817,1827,1837,1847,1857,1867],{"id":13,"depth":86,"text":14,"children":1798},[1799,1800,1801,1802,1803,1804,1805,1806],{"id":18,"depth":92,"text":19},{"id":22,"depth":92,"text":23},{"id":30,"depth":92,"text":31},{"id":37,"depth":92,"text":38},{"id":54,"depth":92,"text":55},{"id":64,"depth":92,"text":65},{"id":128,"depth":92,"text":129},{"id":250,"depth":92,"text":251},{"id":265,"depth":86,"text":266,"children":1808},[1809,1810,1811,1812,1813,1814,1815,1816],{"id":269,"depth":92,"text":19},{"id":272,"depth":92,"text":23},{"id":278,"depth":92,"text":31},{"id":284,"depth":92,"text":38},{"id":298,"depth":92,"text":55},{"id":312,"depth":92,"text":65},{"id":366,"depth":92,"text":129},{"id":536,"depth":92,"text":251},{"id":550,"depth":86,"text":551,"children":1818},[1819,1820,1821,1822,1823,1824,1825,1826],{"id":554,"depth":92,"text":555},{"id":558,"depth":92,"text":23},{"id":564,"depth":92,"text":31},{"id":570,"depth":92,"text":38},{"id":584,"depth":92,"text":55},{"id":591,"depth":92,"text":65},{"id":653,"depth":92,"text":129},{"id":773,"depth":92,"text":251},{"id":787,"depth":86,"text":788,"children":1828},[1829,1830,1831,1832,1833,1834,1835,1836],{"id":791,"depth":92,"text":555},{"id":794,"depth":92,"text":23},{"id":800,"depth":92,"text":31},{"id":806,"depth":92,"text":38},{"id":820,"depth":92,"text":55},{"id":827,"depth":92,"text":65},{"id":859,"depth":92,"text":129},{"id":972,"depth":92,"text":251},{"id":986,"depth":86,"text":987,"children":1838},[1839,1840,1841,1842,1843,1844,1845,1846],{"id":990,"depth":92,"text":555},{"id":993,"depth":92,"text":23},{"id":999,"depth":92,"text":31},{"id":1005,"depth":92,"text":38},{"id":1019,"depth":92,"text":55},{"id":1027,"depth":92,"text":65},{"id":1064,"depth":92,"text":129},{"id":1153,"depth":92,"text":251},{"id":1167,"depth":86,"text":1168,"children":1848},[1849,1850,1851,1852,1853,1854,1855,1856],{"id":1171,"depth":92,"text":555},{"id":1174,"depth":92,"text":23},{"id":1180,"depth":92,"text":31},{"id":1186,"depth":92,"text":38},{"id":1200,"depth":92,"text":55},{"id":1211,"depth":92,"text":65},{"id":1252,"depth":92,"text":129},{"id":1332,"depth":92,"text":251},{"id":1346,"depth":86,"text":1347,"children":1858},[1859,1860,1861,1862,1863,1864,1865,1866],{"id":1350,"depth":92,"text":555},{"id":1353,"depth":92,"text":23},{"id":1359,"depth":92,"text":31},{"id":1365,"depth":92,"text":38},{"id":1379,"depth":92,"text":55},{"id":1390,"depth":92,"text":65},{"id":1427,"depth":92,"text":129},{"id":1542,"depth":92,"text":251},{"id":1556,"depth":86,"text":1557,"children":1868},[1869,1870,1871,1872,1873,1874,1875,1876],{"id":1560,"depth":92,"text":1561},{"id":1564,"depth":92,"text":23},{"id":1570,"depth":92,"text":31},{"id":1576,"depth":92,"text":38},{"id":1590,"depth":92,"text":55},{"id":1598,"depth":92,"text":65},{"id":1655,"depth":92,"text":129},{"id":1779,"depth":92,"text":251},"2025-12-09","Security audit of Gold Exchange smart contracts identifying critical vulnerabilities in oracle implementation, minting logic, and economic design.","md","Solidity",{},"\u002Faudits\u002Fgold-exchange-audit",null,{"title":5,"description":1878},"audits\u002Fgold-exchange-audit","audit","6JTpX3zPXtz5XdzmmHgREaoUtX6kpTrViPl1l5EcsGM",1786102994705]