diff --git a/.github/_typos.toml b/.github/_typos.toml index 6234b2c783..d7fc0095f5 100644 --- a/.github/_typos.toml +++ b/.github/_typos.toml @@ -1,4 +1,7 @@ [default.extend-words] TGE = "TGE" TKO = "TKO" -Ethereum = "Ethereum" \ No newline at end of file +Ethereum = "Ethereum" + +[files] +extend-exclude = ["packages/protocol/audit"] \ No newline at end of file diff --git a/.github/workflows/taikoon-ui.yml b/.github/workflows/taikoon-ui.yml new file mode 100644 index 0000000000..24d3617105 --- /dev/null +++ b/.github/workflows/taikoon-ui.yml @@ -0,0 +1,38 @@ +name: Taikoon UI + +on: + push: + branches: [main] + paths: + - "packages/taikoon-ui/**" + pull_request: + paths: + - "packages/taikoon-ui/**" + +jobs: + build: + runs-on: [taiko-runner] + steps: + - name: Cancel previous runs + uses: styfle/cancel-workflow-action@0.12.1 + with: + access_token: ${{ github.token }} + + - name: Checkout repository + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install pnpm dependencies + uses: ./.github/actions/install-pnpm-dependencies + + - name: Check formatting + working-directory: ./packages/taikoon-ui + run: pnpm lint + + - name: Frontend build + working-directory: ./packages/taikoon-ui + run: | + export PUBLIC_WALLETCONNECT_PROJECT_ID="fake_project_id" + export PUBLIC_IPFS_GATEWAY="https://ipfs.io/ipfs/" + pnpm build diff --git a/README.md b/README.md index 40ed82d51f..fc31a296e8 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,9 @@ If you find a bug or have a feature request, please [open an issue](https://gith ## Contributing -Check out [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to contribute. +Check out [CONTRIBUTING.md](./CONTRIBUTING.md) for details on how to contribute. You can also check out our grants cycle at [grants.taiko.xyz](https://grants.taiko.xyz). -You can also check out our grants cycle at [grants.taiko.xyz](https://grants.taiko.xyz). +⚠️ Please refrain from submitting typo/comment-only pull requests with the expectation of receiving TKO airdrops. ## Getting support diff --git a/packages/bridge-ui/package.json b/packages/bridge-ui/package.json index ae8dba9275..291a744891 100644 --- a/packages/bridge-ui/package.json +++ b/packages/bridge-ui/package.json @@ -39,7 +39,7 @@ "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-simple-import-sort": "^12.0.0", - "eslint-plugin-svelte": "^2.35.1", + "eslint-plugin-svelte": "^2.38.0", "ethereum-address": "^0.0.4", "jsdom": "^24.0.0", "lokijs": "^1.5.12", @@ -62,7 +62,7 @@ "dependencies": { "@moralisweb3/common-evm-utils": "^2.26.1", "@wagmi/connectors": "^4.1.18", - "@wagmi/core": "^2.6.9", + "@wagmi/core": "^2.8.0", "@walletconnect/ethereum-provider": "^2.12.2", "@walletconnect/modal": "^2.6.2", "@web3modal/wagmi": "^4.1.11", diff --git a/packages/guardian-prover-health-check-ui/package.json b/packages/guardian-prover-health-check-ui/package.json index e7cda9f20a..cc77aeafc3 100644 --- a/packages/guardian-prover-health-check-ui/package.json +++ b/packages/guardian-prover-health-check-ui/package.json @@ -30,7 +30,7 @@ "daisyui": "^4.10.1", "eslint": "^8.56.0", "eslint-config-prettier": "^9.1.0", - "eslint-plugin-svelte": "^2.35.1", + "eslint-plugin-svelte": "^2.38.0", "postcss": "^8.4.38", "postcss-import": "^16.1.0", "postcss-nesting": "^12.1.0", @@ -47,7 +47,7 @@ }, "type": "module", "dependencies": { - "@wagmi/core": "^2.6.9", + "@wagmi/core": "^2.8.0", "axios": "^1.6.7", "svelte-i18n": "^4.0.0", "viem": "^2.9.16" diff --git a/packages/guardian-prover-health-check/healthchecker/healthchecker.go b/packages/guardian-prover-health-check/healthchecker/healthchecker.go index 461ad4a5b7..dca9eaae8a 100644 --- a/packages/guardian-prover-health-check/healthchecker/healthchecker.go +++ b/packages/guardian-prover-health-check/healthchecker/healthchecker.go @@ -114,7 +114,7 @@ func InitFromConfig(ctx context.Context, h *HealthChecker, cfg *Config) (err err guardianProvers = append(guardianProvers, guardianproverhealthcheck.GuardianProver{ Address: guardianAddress, - ID: guardianId, + ID: new(big.Int).Sub(guardianId, common.Big1), HealthCheckCounter: promauto.NewCounter(prometheus.CounterOpts{ Name: fmt.Sprintf("guardian_prover_%v_health_checks_ops_total", guardianId.Uint64()), Help: "The total number of health checks", diff --git a/packages/protocol/audit/code4rena-2024-03-taiko-final-report.md b/packages/protocol/audit/code4rena-2024-03-taiko-final-report.md new file mode 100644 index 0000000000..4f700ec427 --- /dev/null +++ b/packages/protocol/audit/code4rena-2024-03-taiko-final-report.md @@ -0,0 +1,12983 @@ +--- +sponsor: "Taiko" +slug: "2024-03-taiko" +date: "2024-04-26" +title: "Taiko" +findings: "https://github.com/code-423n4/2024-03-taiko-findings/issues" +contest: 343 +--- + +# Overview + +## About C4 + +Code4rena (C4) is an open organization consisting of security researchers, auditors, developers, and individuals with domain expertise in smart contracts. + +A C4 audit is an event in which community participants, referred to as Wardens, review, audit, or analyze smart contract logic in exchange for a bounty provided by sponsoring projects. + +During the audit outlined in this document, C4 conducted an analysis of the Taiko smart contract system written in Solidity. The audit took place between March 6—March 27 2024. + +## Wardens + +74 Wardens contributed reports to Taiko: + +1. [monrel](https://code4rena.com/@monrel) +2. [Shield](https://code4rena.com/@Shield) ([Viraz](https://code4rena.com/@Viraz), [0xA5DF](https://code4rena.com/@0xA5DF), [Dravee](https://code4rena.com/@Dravee), and [Udsen](https://code4rena.com/@Udsen)) +3. [t0x1c](https://code4rena.com/@t0x1c) +4. [zzebra83](https://code4rena.com/@zzebra83) +5. [MrPotatoMagic](https://code4rena.com/@MrPotatoMagic) +6. [ladboy233](https://code4rena.com/@ladboy233) +7. [joaovwfreire](https://code4rena.com/@joaovwfreire) +8. [alexfilippov314](https://code4rena.com/@alexfilippov314) +9. [Tendency](https://code4rena.com/@Tendency) +10. [Aymen0909](https://code4rena.com/@Aymen0909) +11. [pa6kuda](https://code4rena.com/@pa6kuda) +12. [t4sk](https://code4rena.com/@t4sk) +13. [mojito_auditor](https://code4rena.com/@mojito_auditor) +14. [lightoasis](https://code4rena.com/@lightoasis) +15. [0xleadwizard](https://code4rena.com/@0xleadwizard) +16. [wangxx2026](https://code4rena.com/@wangxx2026) +17. [josephdara](https://code4rena.com/@josephdara) +18. [blockdev](https://code4rena.com/@blockdev) +19. [Sathish9098](https://code4rena.com/@Sathish9098) +20. [Mahi_Vasisth](https://code4rena.com/@Mahi_Vasisth) +21. [imare](https://code4rena.com/@imare) +22. [Limbooo](https://code4rena.com/@Limbooo) +23. [kaveyjoe](https://code4rena.com/@kaveyjoe) +24. [Myd](https://code4rena.com/@Myd) +25. [yongskiws](https://code4rena.com/@yongskiws) +26. [fouzantanveer](https://code4rena.com/@fouzantanveer) +27. [0xepley](https://code4rena.com/@0xepley) +28. [hassanshakeel13](https://code4rena.com/@hassanshakeel13) +29. [popeye](https://code4rena.com/@popeye) +30. [aariiif](https://code4rena.com/@aariiif) +31. [roguereggiant](https://code4rena.com/@roguereggiant) +32. [Fassi_Security](https://code4rena.com/@Fassi_Security) ([bronze_pickaxe](https://code4rena.com/@bronze_pickaxe) and [mxuse](https://code4rena.com/@mxuse)) +33. [albahaca](https://code4rena.com/@albahaca) +34. [DadeKuma](https://code4rena.com/@DadeKuma) +35. [hunter_w3b](https://code4rena.com/@hunter_w3b) +36. [zabihullahazadzoi](https://code4rena.com/@zabihullahazadzoi) +37. [0x11singh99](https://code4rena.com/@0x11singh99) +38. [slvDev](https://code4rena.com/@slvDev) +39. [pfapostol](https://code4rena.com/@pfapostol) +40. [hihen](https://code4rena.com/@hihen) +41. [grearlake](https://code4rena.com/@grearlake) +42. [dharma09](https://code4rena.com/@dharma09) +43. [0xAnah](https://code4rena.com/@0xAnah) +44. [IllIllI](https://code4rena.com/@IllIllI) +45. [iamandreiski](https://code4rena.com/@iamandreiski) +46. [lanrebayode77](https://code4rena.com/@lanrebayode77) +47. [cheatc0d3](https://code4rena.com/@cheatc0d3) +48. [clara](https://code4rena.com/@clara) +49. [JCK](https://code4rena.com/@JCK) +50. [foxb868](https://code4rena.com/@foxb868) +51. [pavankv](https://code4rena.com/@pavankv) +52. [rjs](https://code4rena.com/@rjs) +53. [sxima](https://code4rena.com/@sxima) +54. [Pechenite](https://code4rena.com/@Pechenite) ([Bozho](https://code4rena.com/@Bozho) and [radev_sw](https://code4rena.com/@radev_sw)) +55. [oualidpro](https://code4rena.com/@oualidpro) +56. [LinKenji](https://code4rena.com/@LinKenji) +57. [0xbrett8571](https://code4rena.com/@0xbrett8571) +58. [emerald7017](https://code4rena.com/@emerald7017) +59. [Masamune](https://code4rena.com/@Masamune) +60. [Kalyan-Singh](https://code4rena.com/@Kalyan-Singh) +61. [n1punp](https://code4rena.com/@n1punp) +62. [Auditor2947](https://code4rena.com/@Auditor2947) +63. [SAQ](https://code4rena.com/@SAQ) +64. [SY_S](https://code4rena.com/@SY_S) +65. [SM3_SS](https://code4rena.com/@SM3_SS) +66. [unique](https://code4rena.com/@unique) +67. [0xhacksmithh](https://code4rena.com/@0xhacksmithh) +68. [K42](https://code4rena.com/@K42) +69. [caglankaan](https://code4rena.com/@caglankaan) + +This audit was judged by [0xean](https://code4rena.com/@0xean). + +Final report assembled by PaperParachute. + +# Summary + +The C4 analysis yielded an aggregated total of 19 unique vulnerabilities. Of these vulnerabilities, 5 received a risk rating in the category of HIGH severity and 14 received a risk rating in the category of MEDIUM severity. + +Additionally, C4 analysis included 33 reports detailing issues with a risk rating of LOW severity or non-critical. There were also 28 reports recommending gas optimizations. + +All of the issues presented here are linked back to their original finding. + +# Scope + +The code under review can be found within the [C4 Taiko repository](https://github.com/code-423n4/2024-03-taiko), and is composed of 80 smart contracts written in the Solidity programming language and includes 7442 lines of Solidity code. + +# Severity Criteria + +C4 assesses the severity of disclosed vulnerabilities based on three primary risk categories: high, medium, and low/non-critical. + +High-level considerations for vulnerabilities span the following key areas when conducting assessments: + +- Malicious Input Handling +- Escalation of privileges +- Arithmetic +- Gas use + +For more information regarding the severity criteria referenced throughout the submission review process, please refer to the documentation provided on [the C4 website](https://code4rena.com), specifically our section on [Severity Categorization](https://docs.code4rena.com/awarding/judging-criteria/severity-categorization). + +# High Risk Findings (5) + +## [[H-01] Gas issuance is inflated and will halt the chain or lead to incorrect base fee](https://github.com/code-423n4/2024-03-taiko-findings/issues/276) + +_Submitted by [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/276)_ + + + + + + + + + +The base fee calculation in the `anchor()` function is incorrect. Issuance is over inflated and will either lead to the chain halting or a severely deflated base fee. + +### Proof of Concept + +We calculate the 1559 base fee and compare it to `block.basefee`
+ +```solidity + (basefee, gasExcess) = _calc1559BaseFee(config, _l1BlockId, _parentGasUsed); + if (!skipFeeCheck() && block.basefee != basefee) { + revert L2_BASEFEE_MISMATCH(); + +``` + +But the calculation is incorrect: + + + +```solidity + if (gasExcess > 0) { + // We always add the gas used by parent block to the gas excess + // value as this has already happened + uint256 excess = uint256(gasExcess) + _parentGasUsed; + + // Calculate how much more gas to issue to offset gas excess. + // after each L1 block time, config.gasTarget more gas is issued, + // the gas excess will be reduced accordingly. + // Note that when lastSyncedBlock is zero, we skip this step + // because that means this is the first time calculating the basefee + // and the difference between the L1 height would be extremely big, + // reverting the initial gas excess value back to 0. + uint256 numL1Blocks; + if (lastSyncedBlock > 0 && _l1BlockId > lastSyncedBlock) { + numL1Blocks = _l1BlockId - lastSyncedBlock; + } + + if (numL1Blocks > 0) { + uint256 issuance = numL1Blocks * _config.gasTargetPerL1Block; + excess = excess > issuance ? excess - issuance : 1; + } + + gasExcess_ = uint64(excess.min(type(uint64).max)); + + // The base fee per gas used by this block is the spot price at the + // bonding curve, regardless the actual amount of gas used by this + // block, however, this block's gas used will affect the next + // block's base fee. + basefee_ = Lib1559Math.basefee( + gasExcess_, uint256(_config.basefeeAdjustmentQuotient) * _config.gasTargetPerL1Block + ); + } +``` + +Instead of issuing `_config.gasTargetPerL1Block` for each L1 block we end up issuing `uint256 issuance = (_l1BlockOd - lastSyncedBlock) * _config.gasTargetPerL1Block`. + +`lastSyncedBlock` is only updated every 5 blocks. + + + +```solidity + if (_l1BlockId > lastSyncedBlock + BLOCK_SYNC_THRESHOLD) { + // Store the L1's state root as a signal to the local signal service to + // allow for multi-hop bridging. + ISignalService(resolve("signal_service", false)).syncChainData( + ownerChainId, LibSignals.STATE_ROOT, _l1BlockId, _l1StateRoot + ); + lastSyncedBlock = _l1BlockId; + } +``` + +If `anchor()` is called on 5 consecutive blocks we end up issuing +in total `15 * _config.gasTargetPerL1Block` instead of `5 * _config.gasTargetPerL1Block`. + +When the calculated base fee is compared to the `block.basefee` the following happens: + +- If `block.basefee`reports the correct base fee this will end up halting the chain since they will not match. + +- If `block.basefee` is using the same flawed calculation the chain continues but with a severely reduced and incorrect base fee. + +Here is a simple POC showing the actual issuance compared to the expected issuance. Paste the code into TaikoL1LibProvingWithTiers.t.sol and run `forge test --match-test testIssuance -vv`. + +
+ +```solidity + struct Config { + uint32 gasTargetPerL1Block; + uint8 basefeeAdjustmentQuotient; + } + + function getConfig() public view virtual returns (Config memory config_) { + config_.gasTargetPerL1Block = 15 * 1e6 * 4; + config_.basefeeAdjustmentQuotient = 8; + } + + uint256 lastSyncedBlock = 1; + uint256 gasExcess = 10; + function _calc1559BaseFee( + Config memory _config, + uint64 _l1BlockId, + uint32 _parentGasUsed + ) + private + view + returns (uint256 issuance, uint64 gasExcess_) + { + if (gasExcess > 0) { + uint256 excess = uint256(gasExcess) + _parentGasUsed; + + uint256 numL1Blocks; + if (lastSyncedBlock > 0 && _l1BlockId > lastSyncedBlock) { + numL1Blocks = _l1BlockId - lastSyncedBlock; + } + + if (numL1Blocks > 0) { + issuance = numL1Blocks * _config.gasTargetPerL1Block; + excess = excess > issuance ? excess - issuance : 1; + } + // I have commented out the below basefee calculation + // and return issuance instead to show the actual + // accumulated issuance over 5 L1 blocks. + // nothing else is changed + + //gasExcess_ = uint64(excess.min(type(uint64).max)); + + //basefee_ = Lib1559Math.basefee( + // gasExcess_, uint256(_config.basefeeAdjustmentQuotient) * _config.gasTargetPerL1Block + //); + } + + //if (basefee_ == 0) basefee_ = 1; + } + + function testIssuance() external { + uint256 issuance; + uint256 issuanceAdded; + Config memory config = getConfig(); + for (uint64 x=2; x <= 6 ;x++){ + + (issuanceAdded ,) = _calc1559BaseFee(config, x, 0); + issuance += issuanceAdded; + console2.log("added", issuanceAdded); + } + + uint256 expectedIssuance = config.gasTargetPerL1Block*5; + console2.log("Issuance", issuance); + console2.log("Expected Issuance", expectedIssuance); + + assertEq(expectedIssuance*3, issuance); + +``` + +
+ +### Tools Used + +Foundry, VScode + +### Recommended Mitigation Steps + +Issue exactly `config.gasTargetPerL1Block` for each L1 block. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/276#issuecomment-2031033625):** + +> This is a valid bug report. Fixed in this PR: https://github.com/taikoxyz/taiko-mono/pull/16543 + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/276#issuecomment-2045139998):** + +> I don't see a direct loss of funds here and believe M is the correct severity. +> +> > 2 — Med: Assets not at direct risk, but the function of the protocol or its availability could be impacted, or leak value with a hypothetical attack path with stated assumptions, but external requirements. +> +> > 3 — High: Assets can be stolen/lost/compromised directly (or indirectly if there is a valid attack path that does not have hand-wavy hypotheticals). + +**[0xmonrel (Warden) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/276#issuecomment-2049465072):** + +> A halted chain leads to frozen funds. The chain will progress for a minimum of 2 blocks since the calculation is correct when `lastSyncedBlock =0` and when `_l1BlockID-lastSyncedBlock=1` +> +> After the second block the base fee will still be correct as long as `excess < issuance` for both the inflated and correct calculating since both result in `excess=1` > https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L279-L282 +> +> ```solidity +> if (numL1Blocks > 0) { +> uint256 issuance = numL1Blocks * _config.gasTargetPerL1Block; +> excess = excess > issuance ? excess - issuance : 1; +> } +> ``` +> +> At the block where the base fee is incorrect the chain is halted and funds are locked since the anchor now reverts in perpetuity. +> +> In practice Taiko can easily release all funds by upgrading the contracts but I believe such an intervention should not be considered when evaluating the severity of an issue. From [C4 Supreme Court session, Fall 2023](https://docs.code4rena.com/awarding/judging-criteria/supreme-court-decisions-fall-2023) +> +> > Contract upgradability should never be used as a severity mitigation, i.e. we assume contracts are non-upgradable. +> +> I therefore believe a High is fair here. + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/276#issuecomment-2049679633):** + +> I don't entirely agree since the chain would be halted so soon in its existence, that being said, some amount of funds, albeit small, would likely be lost. @dantaik / @adaki2004 any last comments before leaving as H severity? + +**[adaki2004 (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/276#issuecomment-2049949706):** + +> Agreed, can do! + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/276#issuecomment-2051543094):** + +> Awarding as H, final decision. + +--- + +## [[H-02] Validity and contests bond ca be incorrectly burned for the correct and ultimately verified transition](https://github.com/code-423n4/2024-03-taiko-findings/issues/266) + +_Submitted by [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/266), also found by [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/227)_ + + + + + + + +Both validity and contests bonds can be wrongfully slashed even if the transition ends up being the correct and verified one. + +The issue comes from the fact that the history of the final verified transition is not taken into account. + +Example 1: Validity bond is wrongfully burned: + +1. Bob Proves transition T1 for parent P1 +2. Alice contests and proves T2 for parent P1 with higher tier proof. +3. Guardians steps in to correctly prove T1 for parent P2. + +At step 2 Bob loses his bond and is permanentley written out of the history of P1
+ +```solidity + _ts.validityBond = _tier.validityBond; + _ts.contestBond = 1; + _ts.contester = address(0); + _ts.prover = msg.sender; + _ts.tier = _proof.tier; +``` + +Example 2: Contest bond wrongfully slashed: + +1. Alice proves T1 for parent P1 with SGX +2. Bob contests T1 for parent P1 +3. Alice proves T1 with SGX_ZK parent P1 +4. Guardian steps in to correctly disprove T1 with T2 for parent P1 + +Bob was correct and T1 was ultimately proven false. Bob still loses his contest bond. + +When the guardian overrides the proof they can not pay back Bob's validity or contesting bond. They are only able to pay back a liveness bond
+ +```solidity +if (isTopTier) { + // A special return value from the top tier prover can signal this + // contract to return all liveness bond. + bool returnLivenessBond = blk.livenessBond > 0 && _proof.data.length == 32 + && bytes32(_proof.data) == RETURN_LIVENESS_BOND; + + if (returnLivenessBond) { + tko.transfer(blk.assignedProver, blk.livenessBond); + blk.livenessBond = 0; + } +} +``` + +These funds are now frozen since they are sent to the Guardian contract which has no ability to recover them. + + + +```solidity + uint256 bondToReturn = uint256(ts.validityBond) + blk.livenessBond; + + if (ts.prover != blk.assignedProver) { + bondToReturn -= blk.livenessBond >> 1; + } + + IERC20 tko = IERC20(_resolver.resolve("taiko_token", false)); + tko.transfer(ts.prover, bondToReturn) +``` + +`ts.prover` will be the Guardian since they are the last to prove the block + +### Proof of Concept + +POC for example 1. Paste the below code into the `TaikoL1LibProvingWithTiers.t` file and run `forge test --match-test testProverLoss -vv` + +
+ +```solidity + + function testProverLoss() external{ + giveEthAndTko(Alice, 1e7 ether, 1000 ether); + giveEthAndTko(Carol, 1e7 ether, 1000 ether); + giveEthAndTko(Bob, 1e6 ether, 100 ether); + console2.log("Bob balance:", tko.balanceOf(Bob)); + uint256 bobBalanceBefore = tko.balanceOf(Bob); + vm.prank(Bob, Bob); + + bytes32 parentHash = GENESIS_BLOCK_HASH; + uint256 blockId = 1; + + (TaikoData.BlockMetadata memory meta,) = proposeBlock(Alice, Bob, 1_000_000, 1024); + + console2.log("Bob balance After propose:", tko.balanceOf(Bob)); + mine(1); + + bytes32 blockHash = bytes32(1e10 + blockId); + bytes32 stateRoot = bytes32(1e9 + blockId); + + (, TaikoData.SlotB memory b) = L1.getStateVariables(); + uint64 lastVerifiedBlockBefore = b.lastVerifiedBlockId; + + // Bob proves transition T1 for parent P1 + proveBlock(Bob, Bob, meta, parentHash, blockHash, stateRoot, meta.minTier, ""); + console2.log("Bob balance After proof:", tko.balanceOf(Bob)); + + uint16 minTier = meta.minTier; + + // Higher Tier contests by proving transition T2 for same parent P1 + proveHigherTierProof(meta, parentHash, bytes32(uint256(1)), bytes32(uint256(1)), minTier); + + // Guardian steps in to prove T1 is correct transition for parent P1 + proveBlock( + David, David, meta, parentHash, blockHash, stateRoot, LibTiers.TIER_GUARDIAN, "" + ); + + vm.roll(block.number + 15 * 12); + + vm.warp( + block.timestamp + tierProvider().getTier(LibTiers.TIER_GUARDIAN).cooldownWindow * 60 + + 1 + ); + + vm.roll(block.number + 15 * 12); + vm.warp( + block.timestamp + tierProvider().getTier(LibTiers.TIER_GUARDIAN).cooldownWindow * 60 + + 1 + ); + + // When the correct transition T1 is verified Bob does permantley loses his validitybond + // even though it is the correct transition for the verified parent P1. + verifyBlock(Carol, 1); + parentHash = blockHash; + + (, b) = L1.getStateVariables(); + uint64 lastVerifiedBlockAfter = b.lastVerifiedBlockId; + assertEq(lastVerifiedBlockAfter, lastVerifiedBlockBefore + 1 ); // Verification completed + + uint256 bobBalanceAfter = tko.balanceOf(Bob); + assertLt(bobBalanceAfter, bobBalanceBefore); + + console2.log("Bob Loss:", bobBalanceBefore - bobBalanceAfter); + console2.log("Bob Loss without couting livenessbond:", bobBalanceBefore - bobBalanceAfter - 1e18); // Liveness bond is 1 ETH in tests + } + +``` + +
+ +### Tools Used + +Foundry, VScode + +### Recommended Mitigation Steps + +The simplest solution is to allow the guardian to pay back validity and contest bonds in the same manner as for liveness bonds. This keeps the simple design while allowing bonds to be recovered if a prover or contesters action is ultimately proven correct. + +Guardian will pass in data in `_proof.data` that specifies the address, tiers and bond type that should be refunded. Given that Guardians already can verify any proof this does not increase centralization. + +We also need to not to not recover any reward when we prove with Guardian and `_overrideWithHigherProof()` is called. If the `ts.validityBond` reward is sent to the Guardian it will be locked. Instead we need to keep it in TaikoL1 such that it can be recovered as described above + +```diff ++if (_tier.contestBond != 0){ + unchecked { + if (reward > _tier.validityBond) { + _tko.transfer(msg.sender, reward - _tier.validityBond); + } else { + _tko.transferFrom(msg.sender, address(this), _tier.validityBond - reward); + } + } ++} +``` + +**[dantaik (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/266#issuecomment-2033385962):** + +> This is a valid report but we knew this "flaw" and the current behavior is by design. +> +> - The odd that a valid transition is proven, then contested and overwritten by another proof, then proven again with even a higher tier should be rare, if this happens even once, we should know the second prover is buggy and shall change the tier configuration to remove it. +> - For provers who suffer a loss due to such prover bugs, Taiko foundation may send them compensation to cover there loss. We do not want to handle cover-your-loss payment in the protocol. + +**[adaki2004 (Taiko) confirmed, but disagreed with severity and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/266#issuecomment-2033985576):** + +> This is an attack on the tier system, right ? But the economical disincentives doing so shall be granted by the bonds - not to challenge proofs which we do know are correct, just to make someone lose money as there is no advantage. The challenger would lose even more money - and the correct prover would be refunded by Taiko Foundation. +> +> Severity: medium, (just as: https://github.com/code-423n4/2024-03-taiko-findings/issues/227) + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/266#issuecomment-2045155377):** + +> I am going to leave as H, I think there is a direct loss of funds here. +> +> This comment: +> +> > The challenger would lose even more money +> +> Makes me second guess that slightly, but still think H is correct. + +--- + +## [[H-03] Users will never be able to withdraw their claimed airdrop fully in ERC20Airdrop2.sol contract](https://github.com/code-423n4/2024-03-taiko-findings/issues/245) + +_Submitted by [MrPotatoMagic](https://github.com/code-423n4/2024-03-taiko-findings/issues/245), also found by [Aymen0909](https://github.com/code-423n4/2024-03-taiko-findings/issues/241), [alexfilippov314](https://github.com/code-423n4/2024-03-taiko-findings/issues/203), [pa6kuda](https://github.com/code-423n4/2024-03-taiko-findings/issues/149), and [t4sk](https://github.com/code-423n4/2024-03-taiko-findings/issues/51)_ + +**Context:** +The ERC20Airdrop2.sol contract is for managing Taiko token airdrop for eligible users, but the withdrawal is not immediate and is subject to a withdrawal window. + +Users can claim their tokens within claimStart and claimEnd. Once the claim window is over at claimEnd, they can withdraw their tokens between claimEnd and claimEnd + withdrawalWindow. During this withdrawal period, the tokens unlock linearly i.e. the tokens only become fully withdrawable at claimEnd + withdrawalWindow. + +**Issue:** +The issue is that once the tokens for a user are fully unlocked, the [withdraw()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L88) function cannot be called anymore due to the [ongoingWithdrawals modifier](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L39) having a strict `claimEnd + withdrawalWindow < block.timestamp` check in its second condition. + +**Impact:** +Although the tokens become fully unlocked when block.timestamp = claimEnd + withdrawalWindow, it is extremely difficult or close to impossible for normal users to time this to get their full allocated claim amount. This means that users are always bound to lose certain amount of their eligible claim amount. This lost amount can be small for users who claim closer to claimEnd + withdrawalWindow and higher for those who partially claimed initially or did not claim at all thinking that they would claim once their tokens are fully unlocked. + +### Coded POC + +How to use this POC: + +- Add the POC to `test/team/airdrop/ERC20Airdrop2.t.sol` +- Run the POC using `forge test --match-test testAirdropIssue -vvv` +- The POC demonstrates how alice was only able to claim half her tokens out of her total 100 tokens claimable amount. + +```solidity + function testAirdropIssue() public { + vm.warp(uint64(block.timestamp + 11)); + + vm.prank(Alice, Alice); + airdrop2.claim(Alice, 100, merkleProof); + + // Roll 5 days after + vm.roll(block.number + 200); + vm.warp(claimEnd + 5 days); + + airdrop2.withdraw(Alice); + + console.log("Alice balance:", token.balanceOf(Alice)); + + // Roll 6 days after + vm.roll(block.number + 200); + vm.warp(claimEnd + 11 days); + + vm.expectRevert(ERC20Airdrop2.WITHDRAWALS_NOT_ONGOING.selector); + airdrop2.withdraw(Alice); + } +``` + +### Logs + +```solidity +Logs: + > MockERC20Airdrop @ 0x0000000000000000000000000000000000000000 + proxy : 0xF62849F9A0B5Bf2913b396098F7c7019b51A820a + impl : 0x2e234DAe75C793f67A35089C9d99245E1C58470b + owner : 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + msg.sender : 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38 + this : 0x7FA9385bE102ac3EAc297483Dd6233D62b3e1496 + Alice balance: 50 +``` + +### Recommended Mitigation Steps + +In the [modifier ongoingWithdrawals()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L39), consider adding a buffer window in the second condition that gives users enough time to claim the fully unlocked tokens. + +```solidity + uint256 constant bufferWindow = X mins/hours/days; + + modifier ongoingWithdrawals() { + if (claimEnd > block.timestamp || claimEnd + withdrawalWindow < block.timestamp + bufferWindow) { + revert WITHDRAWALS_NOT_ONGOING(); + } + _; + } +``` + +**[dantaik (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/245#issuecomment-2033388656):** + +> Fixed in https://github.com/taikoxyz/taiko-mono/pull/16596 + +**[adaki2004 (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/245#issuecomment-2037149300):** + +> It is indeed a bug in the flow, while we removed Airdrop2, it is still a confirmed finding on the repo for auditing. + +--- + +## [[H-04] Taiko L1 - Proposer can maliciously cause loss of funds by forcing someone else to pay prover's fee](https://github.com/code-423n4/2024-03-taiko-findings/issues/163) + +_Submitted by [zzebra83](https://github.com/code-423n4/2024-03-taiko-findings/issues/163), also found by [MrPotatoMagic](https://github.com/code-423n4/2024-03-taiko-findings/issues/351), [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/270), [mojito_auditor](https://github.com/code-423n4/2024-03-taiko-findings/issues/250), and [ladboy233](https://github.com/code-423n4/2024-03-taiko-findings/issues/191)_ + + + + + + + +Proposal of new blocks triggers a call to proposeBlock in the libProposing library. In that function, there is this the following block of code: + + if (params.coinbase == address(0)) { + params.coinbase = msg.sender; + } + +This sets the params.coinbase variable set by the caller of the function to be the msg.sender if it was empty. + +As part of the process of proposal, hooks can be called of type AssignmentHook. An assignment hook's onBlockProposed will be triggered as follows: + + // When a hook is called, all ether in this contract will be send to the hook. + // If the ether sent to the hook is not used entirely, the hook shall send the Ether + // back to this contract for the next hook to use. + // Proposers shall choose use extra hooks wisely. + IHook(params.hookCalls[i].hook).onBlockProposed{ value: address(this).balance }( + blk, meta_, params.hookCalls[i].data + ); + +Notice how the meta data is passed to this function. Part of the function of the onBlockProposed is to pay the assigned prover their fee and the payee should be the current proposer of the block. this is done as follows: + + // The proposer irrevocably pays a fee to the assigned prover, either in + // Ether or ERC20 tokens. + if (assignment.feeToken == address(0)) { + // Paying Ether + _blk.assignedProver.sendEther(proverFee, MAX_GAS_PAYING_PROVER); + } else { + // Paying ERC20 tokens + IERC20(assignment.feeToken).safeTransferFrom( + _meta.coinbase, _blk.assignedProver, proverFee + ); + } + +Notice how if the payment is in ERC20 tokens, the payee will be the variable \_meta.coinbase, and like we showed earlier, this can be set to any arbitrary address by the proposer. This can lead to a scenario as such: + +1. proposer A approves the assignmentHook contract to spend a portion of their tokens, the allowance is set higher than the actual fee they will be paying. +2. proposer A proposes a block, and a fee is charged and payed to the assigned prover, but there remains allowance that the assignment hook contract can still use. +3. proposer B proposes a block and sets params.coinbase as the the address of proposer A. +4. proposer A address will be the payee of the fee for the assigned prover for the block proposed by proposer B. + +The scenario above describes how someone can be forced maliciously to pay fees for block proposals by other actors. + +### Recommended Mitigation Steps + +A simple fix to this to ensure the block proposer will always be the msg.sender, as such: + + if (params.coinbase == address(0 || params.coinbase != msg.sender)) { + params.coinbase = msg.sender; + } + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/163#issuecomment-2032257802):** + +> This is a valid bug report. It has been fixed here: https://github.com/taikoxyz/taiko-mono/pull/16327 + +--- + +## [[H-05] Signatures can be replayed in `withdraw()` to withdraw more tokens than the user originally intended.](https://github.com/code-423n4/2024-03-taiko-findings/issues/60) + +_Submitted by [lightoasis](https://github.com/code-423n4/2024-03-taiko-findings/issues/60), also found by [0xleadwizard](https://github.com/code-423n4/2024-03-taiko-findings/issues/277), [wangxx2026](https://github.com/code-423n4/2024-03-taiko-findings/issues/254), [alexfilippov314](https://github.com/code-423n4/2024-03-taiko-findings/issues/204), [ladboy233](https://github.com/code-423n4/2024-03-taiko-findings/issues/178), and [Tendency](https://github.com/code-423n4/2024-03-taiko-findings/issues/121)_ + +Signatures can be replayed in `withdraw()` to withdraw more tokens than the user originally intended. + +### Vulnerability Details + +In the TimelockTokenPool.sol contracts, users can provide a signature to allow someone else to withdraw all their withdrawable tokens on their behalf using their signature. [TimelockTokenPool.sol#L170) ](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L170) + + function withdraw(address _to, bytes memory _sig) external { + if (_to == address(0)) revert INVALID_PARAM(); + bytes32 hash = keccak256(abi.encodePacked("Withdraw unlocked Taiko token to: ", _to)); + @> address recipient = ECDSA.recover(hash, _sig); + _withdraw(recipient, _to); + } + +As seen from above, the signature provided does not include a nonce and this can lead to signature replay attacks. Due to the lack of a nonce, withdraw() can be called multiple times with the same signature. Therefore, if a user provides a signature to withdraw all his withdrawable tokens at one particular time, an attacker can repeatedly call withdraw() with the same signature to withdraw more tokens than the user originally intended. +The vulnerability is similar to [Arbitrum H-01](https://solodit.xyz/issues/h-01-signatures-can-be-replayed-in-castvotewithreasonandparamsbysig-to-use-up-more-votes-than-a-user-intended-code4rena-arbitrum-foundation-arbitrum-foundation-git) where user's signatures could be replayed to use up more votes than a user intended due to a lack of nonce. + +### Recommended Mitigation Steps + +Consider using a nonce or other signature replay protection in the TimelockTokenPool contract. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/60#issuecomment-2032045461):** + +> Valid bug report, trying to fix it in this PR: https://github.com/taikoxyz/taiko-mono/pull/16611/files + +--- + +# Medium Risk Findings (14) + +## [[M-01] There is no slippage check for the eth deposits processing in the `LibDepositing.processDeposits`](https://github.com/code-423n4/2024-03-taiko-findings/issues/321) + +_Submitted by [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/321), also found by [ladboy233](https://github.com/code-423n4/2024-03-taiko-findings/issues/185)_ + + + + + + + + + + + +The `LibDepositing.depositEtherToL2` function is called by the TaikoL1.depositEtherToL2 to deposit ether to the `L2 chain`. The maximum number of `unprocessed eth deposits` are capped at `_config.ethDepositRingBufferSize - 1` as shown here: + +```solidity + unchecked { + return _amount >= _config.ethDepositMinAmount && _amount <= _config.ethDepositMaxAmount + && _state.slotA.numEthDeposits - _state.slotA.nextEthDepositToProcess + < _config.ethDepositRingBufferSize - 1; + } +``` + +The Taiko configuration states that `ethDepositRingBufferSize == 1024`. Hence the maximum unprocessed eth deposits allowed by the taiko L1 contract is `capped at 1023`. + +When the L2 block is proposed by calling the `LibProposing.proposeBlock` function by the TaikoL1 contract, it processes the unprocessed `eth deposits` by calling the `LibDepositing.processDeposits`. But it is allowed to process `at most 32 eth deposits per block` as per the following conditional check in the `processDeposits` function. + +```solidity +deposits_ = new TaikoData.EthDeposit[(numPending.min(_config.ethDepositMaxCountPerBlock)); +``` + +Here the `ethDepositMaxCountPerBlock == 32` as configured in the `TaikoL1.getConfig` function. + +And the `fee amount` for each of the `eth deposits` are calculated as follows: + +```solidity +uint96 fee = uint96(_config.ethDepositMaxFee.min(block.basefee * _config.ethDepositGas)); + +uint96 _fee = deposits_[i].amount > fee ? fee : deposits_[i].amount; + +deposits_[i].amount -= _fee; +``` + +Hence the `deposited eth amount` is deducted by the calculated `_fee amount` for the `eth deposit transaction`. If the basefee of the `L1 block` increases significantly then the maximum fee of `ethDepositMaxFee: 1 ether / 10` will be applied. Thus deducting that amount from the `transferred eth deposit to the recipient in L2`. + +Now let's consider the following scenario: + +1. `nextEthDepositToProcess` is currently `100`. +2. `numEthDeposits` is `1060` currently. +3. The number of proposed L2 blocks required to process 1060th eth deposit is = 1060 - 100 / 32 = 30 L2 blocks. +4. As a result all the `above 30 L2 blocks` will not be proposed in a single L1 block and will require multiple L1 blocks for it. +5. If there is `huge congestion` in the mainnet during this time the `block.basefee` of the subsequent `L1 blocks` would increase. And this could prompt the maximum fee of `_config.ethDepositMaxFee` to be charged on the deposited amount (in the `LibDepositing.processDeposits` function, since subsequent L1 block would have a higher `block.basefee`) thus prompting loss of funds on the recipient. +6. For example let's assume the depositor deposit `1.1 ether` and current gas fee is `0.01 ether`. Hence the recipient expects to receive approximately `1.09 ether` at the time of the deposit on L1. But when the deposit is processed in a subsequent L1 block, if the fee amount increases to the maximum amount of `0.1 ether` then the recipient will only get approximately `1 ether` only. This will cost the recipient a `loss of 0.9 ether`. If there was a slippage check a depositor can set for his eth deposits then the he can prevent excessive gas costs during processing. + +### Proof of Concept + +```solidity + unchecked { + return _amount >= _config.ethDepositMinAmount && _amount <= _config.ethDepositMaxAmount + && _state.slotA.numEthDeposits - _state.slotA.nextEthDepositToProcess + < _config.ethDepositRingBufferSize - 1; + } +``` + + + +```solidity + ethDepositRingBufferSize: 1024, + ethDepositMinCountPerBlock: 8, + ethDepositMaxCountPerBlock: 32, +``` + + + +```solidity + uint96 fee = uint96(_config.ethDepositMaxFee.min(block.basefee * _config.ethDepositGas)); +``` + + + +```solidity + uint96 _fee = deposits_[i].amount > fee ? fee : deposits_[i].amount; +``` + + + +```solidity + deposits_[i].amount -= _fee; +``` + + + +### Tools Used + +VSCode + +### Recommended Mitigation Steps + +Hence it is recommended to add a slippage check for the fee amount of the deposited eth amount in the `LibDepositing.processDeposits` function, since `depositEtherToL2` and `processDepositare` two different transactions with a delay during which the L1 block `basefee` can increase significantly causing loss of funds to the recipient in the form of fee increase. + +**[dantaik (Taiko) acknowledged, but disagreed with severity and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/321#issuecomment-2033375181):** + +> Thank you for the feedback. The current issue is **valid but minor** as we believe users can choose not to deposit Ether using the `depositEtherToL2` function if there are already many deposits pending in the queue. Going forward, the processing of such deposits will likely be moved to the node software directly. + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/321#issuecomment-2045819455):** + +> Agree this is valid, the impact is most likely small, but I think the likelihood of it occurring at some point is relatively high. The user is exposed to non-deterministic behavior that they cannot fully understand ahead of signing a transaction. + +--- + +## [[M-02] The top tier prover can not re-prove](https://github.com/code-423n4/2024-03-taiko-findings/issues/305) + +_Submitted by [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/305), also found by [zzebra83](https://github.com/code-423n4/2024-03-taiko-findings/issues/165) and [Tendency](https://github.com/code-423n4/2024-03-taiko-findings/issues/118)_ + + + + + +In the `LibProving.proveBlock` function the `top tier prover` is allowed to prove a new transition as long as the new transition is different from the previous transition and `assert` conditional checks pass. + +```solidity + if (sameTransition) revert L1_ALREADY_PROVED(); + + if (isTopTier) { + // The top tier prover re-proves. + assert(tier.validityBond == 0); + assert(ts.validityBond == 0 && ts.contestBond == 0 && ts.contester == address(0)); +``` + +But the `assert condition` of this logic is wrong since it checks for the `ts.contestBond == 0` where as it should be `ts.contestBond == 1` since 1 is set as the default value for `ts.contestBond` parameter for gas savings as shown below: + +```solidity + ts_.contestBond = 1; // to save gas +``` + +As a result of the even though code expects the top-tier prover to re-prove a different transition, the transaction will revert. + +### Proof of Concept + +Add the following testcase `test_L1_GuardianProverCanOverwriteIfNotSameProof_test` to the `TaikoL1LibProvingWithTiers.t.sol` test file. + +If you change the ts.contestBond == 0 +to ts.contestBond == 1 in the second `assert` statement of the `LibProving.proveBlock` function, the test will run successfully and transaction execution will succeed. + +
+ +```solidity + function test_L1_GuardianProverCanOverwriteIfNotSameProof_test() external { + giveEthAndTko(Alice, 1e7 ether, 1000 ether); + giveEthAndTko(Carol, 1e7 ether, 1000 ether); + console2.log("Alice balance:", tko.balanceOf(Alice)); + // This is a very weird test (code?) issue here. + // If this line is uncommented, + // Alice/Bob has no balance.. (Causing reverts !!!) + // Current investigations are ongoing with foundry team + giveEthAndTko(Bob, 1e7 ether, 100 ether); + console2.log("Bob balance:", tko.balanceOf(Bob)); + // Bob + vm.prank(Bob, Bob); + + bytes32 parentHash = GENESIS_BLOCK_HASH; + for (uint256 blockId = 1; blockId < conf.blockMaxProposals * 3; blockId++) { + printVariables("before propose"); + (TaikoData.BlockMetadata memory meta,) = proposeBlock(Alice, Bob, 1_000_000, 1024); + //printVariables("after propose"); + mine(1); + + bytes32 blockHash = bytes32(1e10 + blockId); + bytes32 stateRoot = bytes32(1e9 + blockId); + // This proof cannot be verified obviously because of + // blockhash:blockId + proveBlock(Bob, Bob, meta, parentHash, stateRoot, stateRoot, LibTiers.TIER_GUARDIAN, ""); + + // Prove as guardian + proveBlock( + Carol, Carol, meta, parentHash, blockHash, stateRoot, LibTiers.TIER_GUARDIAN, "" + ); + + vm.roll(block.number + 15 * 12); + + uint16 minTier = meta.minTier; + vm.warp(block.timestamp + tierProvider().getTier(LibTiers.TIER_GUARDIAN).cooldownWindow * 60 + 1); + + verifyBlock(Carol, 1); + + parentHash = blockHash; + } + printVariables(""); + } +``` + +
+ +### Tools Used + +VSCode + +### Recommended Mitigation Steps + +Hence recommended to update the `ts.contestBond == 0` in the second `assert` statement to `ts.contestBond == 1` in the `LibProving.proveBlock` function. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/305#issuecomment-2031537557):** + +> This is a valid bug report, it has been fixed already here: https://github.com/taikoxyz/taiko-mono/pull/16543 + +--- + +## [[M-03] retryMessage unable to handle edge cases.](https://github.com/code-423n4/2024-03-taiko-findings/issues/298) + +_Submitted by [josephdara](https://github.com/code-423n4/2024-03-taiko-findings/issues/298), also found by [josephdara](https://github.com/code-423n4/2024-03-taiko-findings/issues/296), [grearlake](https://github.com/code-423n4/2024-03-taiko-findings/issues/314), [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/286), MrPotatoMagic ([1](https://github.com/code-423n4/2024-03-taiko-findings/issues/281), [2](https://github.com/code-423n4/2024-03-taiko-findings/issues/273)), [Aymen0909](https://github.com/code-423n4/2024-03-taiko-findings/issues/242), [ladboy233](https://github.com/code-423n4/2024-03-taiko-findings/issues/182), [iamandreiski](https://github.com/code-423n4/2024-03-taiko-findings/issues/150), [lanrebayode77](https://github.com/code-423n4/2024-03-taiko-findings/issues/107), [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/48), and Fassi_Security ([1](https://github.com/code-423n4/2024-03-taiko-findings/issues/29), [2](https://github.com/code-423n4/2024-03-taiko-findings/issues/26))_ + +The function `retryMessage()` is unable to handle some edge scenarios listed below. + +1. Reverting or refunding a sender when the receiver is banned after the transaction is placed in a `RETRIABLE` state. +2. Message that is suspended after the transaction is placed in a `RETRIABLE` state. + +### Proof of Concept + +A message is set to `RETRIABLE`in the `processMessage` when transfer fails or if the target address does not satisfy some conditions. + +
+ +```solidity +//IN PROCESSMESSAGE + + if (_invokeMessageCall(_message, msgHash, gasLimit)) { + _updateMessageStatus(msgHash, Status.DONE); + } else { + _updateMessageStatus(msgHash, Status.RETRIABLE); + } + + +//_invokeMessageCall() FUNCTION +function _invokeMessageCall( + Message calldata _message, + bytes32 _msgHash, + uint256 _gasLimit + ) + private + returns (bool success_) + { + if (_gasLimit == 0) revert B_INVALID_GAS_LIMIT(); + assert(_message.from != address(this)); + + _storeContext(_msgHash, _message.from, _message.srcChainId); + + if ( + _message.data.length >= 4 // msg can be empty + && bytes4(_message.data) != IMessageInvocable.onMessageInvocation.selector + && _message.to.isContract() + ) { + success_ = false; + } else { + (success_,) = ExcessivelySafeCall.excessivelySafeCall( + _message.to, + _gasLimit, + _message.value, + 64, // return max 64 bytes + _message.data + ); + } + + // Must reset the context after the message call + _resetContext(); + } +``` + +
+ +The issue here is, when the team attempts suspension of a message which is in a `RETRIABLE` state, the code does not block execution. +Same or a banned address. +This is because the `proofReceipt[msgHash]` which handles suspension is not checked. The ` addressBanned[_addr]` is not checked too. + +
+ +```solidity + function retryMessage( + Message calldata _message, + bool _isLastAttempt + ) + external + nonReentrant + whenNotPaused + sameChain(_message.destChainId) + { + // If the gasLimit is set to 0 or isLastAttempt is true, the caller must + // be the message.destOwner. + if (_message.gasLimit == 0 || _isLastAttempt) { + if (msg.sender != _message.destOwner) revert B_PERMISSION_DENIED(); + } + + bytes32 msgHash = hashMessage(_message); + if (messageStatus[msgHash] != Status.RETRIABLE) { + revert B_NON_RETRIABLE(); + } + + // Attempt to invoke the messageCall. + if (_invokeMessageCall(_message, msgHash, gasleft())) { + _updateMessageStatus(msgHash, Status.DONE); + } else if (_isLastAttempt) { + _updateMessageStatus(msgHash, Status.FAILED); + } +``` + +
+ +### Recommended Mitigation Steps + +Recheck necessary details to verify that the transaction is still good to go. +Check the `proofReceipt[msgHash].receivedAt` and the ` addressBanned[_addr]` + +**[adaki2004 (Taiko) disputed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/298#issuecomment-2031829775):** + +> I'd dispute this with an addition (see end sentence). +> +> 2 cases mentioned here: +> +> 1. Reverting or refunding a sender when the receiver is banned after the transaction is placed in a RETRIABLE state. +> +> Intentional to NOT refund sender when he/she is banned. (Tho we might remove the "banAddress", because it confuses a lot of people. The original intention behind banning an address is: NOT be able to call another , very important contract (`message.to`) on behalf of the `Bridge`, like the `SignalService`.) +> +> 2. Message that is suspended after the transaction is placed in a RETRIABLE state. +> Not to refund suspended messages is a feature, it is a failsafe/security mechanism. In such case we need to use it, it would be a severe situation and we do not necessary want to refund (by default) the owner, since it might be a fake message on the destination chain. (That can be one reason - so makes no sense to refund). +> Also suspension would never happen after RETRIABLE. If we suspend message it is between NEW and (DONE or RETRIABLE). +> +> So as we considering removing banning addresses (and not allow `SignalService` to be called) for avoid confusion, but not because it is an issue, but a simplification and to avoid confusion. https://github.com/taikoxyz/taiko-mono/pull/16604 + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/298#issuecomment-2051841623):** + +> Using this issue to aggregate all of the issues around ban list functionality that has since been removed from the sponsors code base. + +_Note: For full discussion, see [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/298)._ + +--- + +## [[M-04] A recalled ERC20 bridge transfer can lock tokens in the bridge](https://github.com/code-423n4/2024-03-taiko-findings/issues/279) + +_Submitted by [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/279), also found by [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/271)_ + + + + + + + +A recalling ERC20 bridge transfer can lock funds in the bridge if the call to mint tokens fail on the source chain. Depending on the Native token logic this could either be a permanent lock or a lock of an unknown period of time. + +Example of how this can happen with the provided USDCAdapter: + +USDC limits the amount of USDC that can be minted on each chain by giving each minter a minting allowance. If the minting allowance is reach minting will revert. If this happens in a recalled message the tokens together with the ETH value is locked. + +### Proof of Concept + +USDC limits the amount of USDC that can be minted on each chain by giving each minter a minting allowance. + +If `_amount <= mintingAllowedAmount` is reached for the `USDCAdapter` tokens can not be minted but since this is a recalled message the funds are stuck. + +Both `onMessageIncovation()` and `onMessageRecalled()` call `_transferToken()` to either mint or release tokens. + + + +```solidity + function _transferTokens( + CanonicalERC20 memory _ctoken, + address _to, + uint256 _amount + ) + private + returns (address token_) + { + if (_ctoken.chainId == block.chainid) { + token_ = _ctoken.addr; + IERC20(token_).safeTransfer(_to, _amount); + } else { + token_ = _getOrDeployBridgedToken(_ctoken); + IBridgedERC20(token_).mint(_to, _amount); + } + } +``` + +A recalled message to bridge USDC L1->L2 will revert when we attempt to mint through the `USDCAdapter` + + + +```solidity + function _mintToken(address _account, uint256 _amount) internal override { + usdc.mint(_account, _amount); + +``` + +On the following condition in the native USDC contract + + + +```solidity + require( + _amount <= mintingAllowedAmount, + "FiatToken: mint amount exceeds minterAllowance" + ); +``` + +Course of events that ends in locked funds: + +1. User bridges USDC from L2->L1 +2. The message is recalled from L1 +3. The USDCAdapter has reached the `mintingAllowedAmount` +4. The recalled message is stuck because minting reverts. The USDC and ETH passed in are both locked. + +### Tools Used + +Foundry, VScode + +### Recommended Mitigation Steps + +Add new functionality in the vault that allows users to send a new message to the destination chain again with new message data if `onMessageRecalls()` can not mint tokens. We give users the ability to redeem for canonical tokens instead of being stuck. + +**[dantaik (Taiko) acknowledged and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/279#issuecomment-2033383461):** + +> Thank you for your feedback. In your example, if the user cannot mint tokens in USDCAdapter by using `recallMessage`, the user can wait and call `recallMessage` again. That's why recallMessage is _retriable_. +> +> There is no perfect solution here, and I personally don't want to make the bridge too complicated by introducing this re-send-another-message feature. +> +> Adding a warning on the bridge UI to show a warning message might be a good solution, something like "USDC on Taiko has reached 95% of its max supply cap, bridging USDC to Taiko may end up your fund becoming unavailable for some time until others bridge USDC away from Taiko". + +**[0xean (Judge) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/279#issuecomment-2049345554):** + +> The sponsor comments simply show their isn't a great solution to the problem, it still represents a loss of user funds (if it goes on forever) or a denial of service and a risk that users should be aware of. +> +> @dontonka / @adaki2004 (Taiko) any last comments here? + +**[adaki2004 (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/279#issuecomment-2049448918):** + +> We are OK with med, no issue. Please proceed accordinlgy - as we dont have: +> +> 1. the perfect solution to the problem +> 2. the intention to fix it ATM - since we wont be using any native tokens anytime soon. +> +> But please proceed the way which is suitable for the wardens better, we appreciate their efforts. (So not questioning the severity) + +--- + +## [[M-05] Bridge watcher can forge arbitrary message and drain bridge](https://github.com/code-423n4/2024-03-taiko-findings/issues/278) + +_Submitted by [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/278), also found by [josephdara](https://github.com/code-423n4/2024-03-taiko-findings/issues/294), [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/221), and [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/47)_ + + + + + +The `bridge_watchdog` role can forge arbitrary messages and drain the bridge of all ETH and tokens. + +### Proof of Concept + +`bridge_watchdog` can call `suspendMessasges()` to suspend and un-suspend a message + + + +```solidity + function suspendMessages( + bytes32[] calldata _msgHashes, + bool _suspend + ) + external + onlyFromOwnerOrNamed("bridge_watchdog") + { + uint64 _timestamp = _suspend ? type(uint64).max : uint64(block.timestamp); + for (uint256 i; i < _msgHashes.length; ++i) { + bytes32 msgHash = _msgHashes[i]; + proofReceipt[msgHash].receivedAt = _timestamp; + emit MessageSuspended(msgHash, _suspend); + } + } +``` + +When this function is called to un-suspend a message we set `proofReceipt[msgHash] = _timestamp`. If the msgHash was not proven before it will now be treated as proven since any `msgHash` with a `timestamp != 0` is treated as proven + + + +```solidity + uint64 receivedAt = proofReceipt[msgHash].receivedAt; + bool isMessageProven = receivedAt != 0 +``` + +`bridge_watchdog` can therefore forge arbitrary messages and have them treated as proven by first suspending them and then un-suspending them. + +`bride_watchdog` is supposed to only be able to ban and suspend messages, in the expected worst case `bridge_watchdog` is limited to DDOSing messages and bans until governance removes the the `bridge_watchdog`. + +With the privilege escalation shown here the role can instead drain the bridge of all ETH and tokens. + +### POC + +Here is a POC showing that we can forge an arbitrary message by suspending and un-suspending a message + +To run this POC first change the following code in Bridge.t.sol so that we use a real signalService + +```diff +register( ++address(addressManager), "signal_service", address(signalService), destChainId +-address(addressManager), "signal_service", address(mockProofSignalService), destChainId +); +``` + +Paste the below code and run into Bridge.t.sol and run `forge test --match-test testWatchdogDrain -vvv` + +
+ +```solidity + function testWatchdogDrain() public { + uint256 balanceBefore = Bob.balance; + IBridge.Message memory message = IBridge.Message({ + id: 0, + from: address(bridge), + srcChainId: uint64(block.chainid), + destChainId: destChainId, + srcOwner: Alice, + destOwner: Alice, + to: Bob, + refundTo: Alice, + value: 10 ether, + fee: 1, + gasLimit: 1_000_000, + data: "", + memo: "" + }); + + + bytes memory proof = hex"00"; + bytes32 msgHash = destChainBridge.hashMessage(message); + + bytes32[] memory msgHashA = new bytes32[](1); + msgHashA[0] = msgHash; + + vm.prank(Alice); + destChainBridge.suspendMessages(msgHashA, true); + + vm.prank(Alice); + destChainBridge.suspendMessages(msgHashA, false); + + vm.chainId(destChainId); + vm.prank(Bob, Bob); + + destChainBridge.processMessage(message, proof); + + IBridge.Status status = destChainBridge.messageStatus(msgHash); + + assertEq(status == IBridge.Status.DONE, true); + console2.log("Bobs Stolen funds", Bob.balance-balanceBefore); + + console2.log("We have successfully processed a message without actually proving it!"); + } + +``` + +
+ +### Tools Used + +Foundry, VScode + +### Recommended Mitigation Steps + +Un-suspended messages should be set to 0 and be proven or re-proven. + +```diff + function suspendMessages( + bytes32[] calldata _msgHashes, + bool _suspend + ) + external + onlyFromOwnerOrNamed("bridge_watchdog") + { ++ uint64 _timestamp = _suspend ? type(uint64).max : 0; + for (uint256 i; i < _msgHashes.length; ++i) { + bytes32 msgHash = _msgHashes[i]; + proofReceipt[msgHash].receivedAt = _timestamp; + emit MessageSuspended(msgHash, _suspend); + } + } +``` + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/278#issuecomment-2031031880):** + +> This is a valid bug report. The bug has been fixed in this PR: https://github.com/taikoxyz/taiko-mono/pull/16545 + +**[0xean (Judge) decreased severity to Medium and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/278#issuecomment-2045135078):** + +> Good report, but I am not sure it qualifies as H severity and most likely should be M. +> +> I think there is a pre-condition here (a malicious watchdog). +> +> > 2 — Med: Assets not at direct risk, but the function of the protocol or its availability could be impacted, or leak value with a hypothetical attack path with stated assumptions, but external requirements. +> +> Agree that if this attack is feasible, it represents privilege escalation. +> +> As pointed out previously: +> +> > Privilege escalation issues are judged by likelihood and impact and their severity is uncapped. + +_Note: For full discussion, see [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/278)._ + +--- + +## [[M-06] First block proposer check in the `LibProposing._isProposerPermitted` function is errorneous](https://github.com/code-423n4/2024-03-taiko-findings/issues/274) + +_Submitted by [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/274), also found by [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/382) and [blockdev](https://github.com/code-423n4/2024-03-taiko-findings/issues/9)_ + + + + + +The `LibProposing.proposeBlock` function calls the `_isProposerPermitted` private function, to ensure if the `proposer is set`. Only that specific address has the permission to propose the block. + +In the `_isProposerPermitted` function, for the first block after the genesis block only the `proposerOne` is allowed to propose the first block as shown below: + +```solidity + address proposerOne = _resolver.resolve("proposer_one", true); + if (proposerOne != address(0) && msg.sender != proposerOne) { + return false; + } +``` + +But the issue here is that when the `msg.sender == proposerOne` the function `does not return true` if the following conditions occur. + +If the `proposer != address(0) && msg.sender != proposer`. In which case even though the `msg.sender == proposerOne` is `true` for the first block the `_isProposerPermitted` will still return `false` thus reverting the block proposer for the first block. + +Hence even though the `proposer_one` is the proposer of the first block the transaction will still revert if the above mentioned conditions occur and the `_isProposerPermitted` returns `false` for the first block after the genesis block. + +Hence this will break the block proposing logic since the proposal of the first block after the genesis block reverts thus not allowing subsequent blocks to be proposed. + +### Proof of Concept + +```solidity + TaikoData.SlotB memory b = _state.slotB; + if (!_isProposerPermitted(b, _resolver)) revert L1_UNAUTHORIZED(); +``` + + + +```solidity + function _isProposerPermitted( + TaikoData.SlotB memory _slotB, + IAddressResolver _resolver + ) + private + view + returns (bool) + { + if (_slotB.numBlocks == 1) { + // Only proposer_one can propose the first block after genesis + address proposerOne = _resolver.resolve("proposer_one", true); + if (proposerOne != address(0) && msg.sender != proposerOne) { + return false; + } + } + + address proposer = _resolver.resolve("proposer", true); + return proposer == address(0) || msg.sender == proposer; + } +``` + + + +### Tools Used + +VSCode + +### Recommended Mitigation Steps + +It is recommended to add logic in the `LibProposing._isProposerPermitted` function to `return true` when the `msg.sender == proposerOne`, for proposing the first block after genesis block. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/274#issuecomment-2031595523):** + +> I think this is a valid bug: fixing it [here](https://github.com/taikoxyz/taiko-mono/pull/16605) + +--- + +## [[M-07] Incorrect \_\_Essential_init() function is used in TaikoToken making snapshooter devoid of calling snapshot()](https://github.com/code-423n4/2024-03-taiko-findings/issues/261) + +_Submitted by [MrPotatoMagic](https://github.com/code-423n4/2024-03-taiko-findings/issues/261), also found by [Limbooo](https://github.com/code-423n4/2024-03-taiko-findings/issues/322), [imare](https://github.com/code-423n4/2024-03-taiko-findings/issues/308), and [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/144)_ + +
+ +The EssentialContract.sol contract is inherited by the TaikoToken contract. This essential contract contains two \_\_Essential_init() functions, one with an owner parameter only (see [here](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L109)) and the other with owner and address manager parameters (see [here](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L95)). + +The issue with the current code is that it uses the [\_\_Essential_init()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L109) function with the owner parameter only. This would cause the [onlyFromOwnerOrNamed("snapshooter")](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52) modifier on the [snapshot](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52) function to not be able to resolve the snapshooter role since the address manager contract was never set during initialization, thus causing a revert. + +Due to this: + +1. Snapshooter role is denied from taking snapshots. +2. Timely snapshots for certain periods could have failed by the snapshooter since they would have required the owner to jump in by the time the issue was realized. +3. Correct/Intended functionality of the protocol is affected i.e. the snapshooter role assigned to an address cannot ever perform its tasks validly. + +### Proof of Concept + +Here is the whole process: + +1. Snapshooter address calls the [snapshot()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52) function. The [onlyFromOwnerOrNamed("snapshooter")](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52) modifier is encountered first. + +```solidity +File: TaikoToken.sol +57: function snapshot() public onlyFromOwnerOrNamed("snapshooter") { +58: _snapshot(); +59: } +``` + +2. In the second condition, the [modifier](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L41) calls the [resolve()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L30) function with the "snapshooter" role as `_name` in order to check if the caller (msg.sender) is indeed the address approved by the owner. + +```solidity +File: EssentialContract.sol +46: modifier onlyFromOwnerOrNamed(bytes32 _name) { +47: if (msg.sender != owner() && msg.sender != resolve(_name, true)) +48: revert RESOLVER_DENIED(); +49: _; +50: } +``` + +3. The [resolve()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L30) function is called which internally calls the function [\_resolve()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L72). In the function \_resolve(), the condition on Line 69 evaluates to true and we revert. This is because the addressManager address was never set during initialization using the [\_\_Essential_init()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L95) function with the owner and address manager parameters. Due to this, the snapshooter address is denied from performing it's allocated tasks. + +```solidity +File: AddressResolver.sol +64: function _resolve( +65: uint64 _chainId, +66: bytes32 _name, +67: bool _allowZeroAddress +68: ) private view returns (address payable addr_) { +69: if (addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); +70: +71: addr_ = payable( +72: IAddressManager(addressManager).getAddress(_chainId, _name) +73: ); +74: +75: if (!_allowZeroAddress && addr_ == address(0)) { +76: revert RESOLVER_ZERO_ADDR(_chainId, _name); +77: } +78: } +``` + +### Recommended Mitigation Steps + +In the [init()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L25) function, consider using the [\_\_Essential_init()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L95) function with the owner and address manager parameters instead of the [\_\_Essential_init()](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L109) function with the owner parameter. This would allow the snapshooter address to proceed with taking snapshots as expected. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/261#issuecomment-2031678339):** + +> This is a valid bug report. The bug is fixed by https://github.com/taikoxyz/taiko-mono/commit/c64ec193c95113a4c33692289e23e8d9fa864073 + +--- + +## [[M-08] Bridged tokens would be lost if sender and receiver are contracts that don't implement fallback/receive](https://github.com/code-423n4/2024-03-taiko-findings/issues/226) + +_Submitted by [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/226), also found by [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/330)_ + +When a bridged token is received on the dest chain, `ERC20Vault.onMessageInvocation()` is being called. +`onMessageInvocation()` always calls `to.sendEther(msg.value)` even when the `msg.value` is zero. +`sendEther()` would attempt to call the contract with the value supplied and empty data. If the `to` address ia a contract that doesn't implement neither the fallback function nor receive then the entire transaction would revert. + +The same issue occurs during recalling the message, if the sender is also a contract that doesn't implement neither a fallback nor receive then the recalling would fail as well. + +### Impact + +Funds would be lost, since the sending can't be finalized and recovering would revert as well. + +While this might be considered a user error when sending a value that's greater than zero (they should've checked that the `to` address implements the receiver), this can't be said about the case where the value is zero - the user won't expect the vault to call the `to` contract with zero value. + +### Proof of Concept + +Add the following PoC to `test\tokenvault\ERC20Vault.t.sol`: + +
+Coded PoC + +```solidity +contract NoFallback{ + // other functions might be implemented here, but neither a fallback nor receive +} +``` + +
+ +```solidity + function test_noFallback() + public + { + vm.startPrank(Alice); + + vm.chainId(destChainId); + + erc20.mint(address(erc20Vault)); + + uint256 amount = 0; + address to = address(new NoFallback()); + + uint256 erc20VaultBalanceBefore = erc20.balanceOf(address(erc20Vault)); + uint256 toBalanceBefore = erc20.balanceOf(to); + + destChainIdBridge.sendReceiveERC20ToERC20Vault( + erc20ToCanonicalERC20(destChainId), + Alice, + to, + amount, + bytes32(0), + address(erc20Vault), + srcChainId, + 0 + ); + + uint256 erc20VaultBalanceAfter = erc20.balanceOf(address(erc20Vault)); + assertEq(erc20VaultBalanceBefore - erc20VaultBalanceAfter, amount); + + uint256 toBalanceAfter = erc20.balanceOf(to); + assertEq(toBalanceAfter - toBalanceBefore, amount); + } + + function test_20Vault_onMessageRecalled_20() public { + Alice = address(new NoFallback()); + erc20.mint(Alice); + + vm.startPrank(Alice); + + uint256 amount = 2 wei; + erc20.approve(address(erc20Vault), amount); + + uint256 aliceBalanceBefore = erc20.balanceOf(Alice); + uint256 erc20VaultBalanceBefore = erc20.balanceOf(address(erc20Vault)); + + IBridge.Message memory _messageToSimulateFail = erc20Vault.sendToken( + ERC20Vault.BridgeTransferOp( + destChainId, address(0), Bob, address(erc20), amount, 1_000_000, 0, Bob, "" + ) + ); + + uint256 aliceBalanceAfter = erc20.balanceOf(Alice); + uint256 erc20VaultBalanceAfter = erc20.balanceOf(address(erc20Vault)); + + assertEq(aliceBalanceBefore - aliceBalanceAfter, amount); + assertEq(erc20VaultBalanceAfter - erc20VaultBalanceBefore, amount); + + // No need to imitate that it is failed because we have a mock SignalService + bridge.recallMessage(_messageToSimulateFail, bytes("")); + + uint256 aliceBalanceAfterRecall = erc20.balanceOf(Alice); + uint256 erc20VaultBalanceAfterRecall = erc20.balanceOf(address(erc20Vault)); + + // Release -> original balance + assertEq(aliceBalanceAfterRecall, aliceBalanceBefore); + assertEq(erc20VaultBalanceAfterRecall, erc20VaultBalanceBefore); + } +``` + +
+ +Output: + +``` + +Failing tests: +Encountered 1 failing test in test/tokenvault/ERC20Vault.t.sol:TestERC20Vault +[FAIL. Reason: ETH_TRANSFER_FAILED()] test_20Vault_receive_erc20_canonical_to_dest_chain_transfers_from_canonical_token() (gas: 201153) + + +Failing tests: +Encountered 1 failing test in test/tokenvault/ERC20Vault.t.sol:TestERC20Vault +[FAIL. Reason: ETH_TRANSFER_FAILED()] test_20Vault_onMessageRecalled_20() +``` + +
+ +### Recommended Mitigation Steps + +- Don't call `sendEther()` when the value is zero + - Or modify `sendEther()` to return when the value is zero +- Find a solution for cases when the value is non-zero + - This one is a bit more complicated, one way might be to allow the sender to request the ERC20 token while giving up on the ETH + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/226#issuecomment-2079065682):** + +> We have change the sendEther function such that if the amount is 0, there is no further action and the sendEther function simply returns. +> +> If if default and receive functions are both unimplemented on the destination chain for the to address, then the owner can fail the message with retryMessage({..., \_lastAttemp=true}); >or use failMessage(...) , then on the source chain, the owner can call recallMessage to get back his tokens. +> +> At the end of the day, the user must trust the dapp that use our Bridge to set the right message parameters. + +--- + +## [[M-09] LibProposing:proposeBlock allows blocks with a zero parentMetaHash to be proposed after the genesis block and avoid parent block verification](https://github.com/code-423n4/2024-03-taiko-findings/issues/218) + +_Submitted by [joaovwfreire](https://github.com/code-423n4/2024-03-taiko-findings/issues/218)_ + + + + + + + +The proposeBlock at the LibProposing library has the following check to ensure the proposed block has the correct parentMetaHash set: + +```solidity +function proposeBlock( + TaikoData.State storage _state, + TaikoData.Config memory _config, + IAddressResolver _resolver, + bytes calldata _data, + bytes calldata _txList + ) + internal + returns (TaikoData.BlockMetadata memory meta_, TaikoData.EthDeposit[] memory deposits_) + { + ... +if (params.parentMetaHash != 0 && parentMetaHash != params.parentMetaHash) { + revert L1_UNEXPECTED_PARENT(); + } + ... + } +``` + +However, there are no sanity checks to ensure params.parentMetaHash is not zero outside of the genesis block. + +### Impact + +Malicious proposers can propose new blocks without any parentMetaHash. +This can induce a maliciously-generated block to be artificially contested as the final block relies on data held by the meta\_ variable. +Snippet 1: + +```solidity +TaikoData.Block memory blk = TaikoData.Block({ + metaHash: keccak256(abi.encode(meta_)), +... +}) +``` + +This also generates issues for independent provers, as they may not utilize the proposed block's data to attempt to prove it and utilize the correct parentMetaHash, which will make the LibProving:proveBlock call revert with an L1_BLOCK_MISTATCH error: + +```solidity +function proveBlock + ... + if (blk.blockId != _meta.id || blk.metaHash != keccak256(abi.encode(_meta))) { + revert L1_BLOCK_MISMATCH(); + } + ... +} +``` + +Also, according to the documentation, [ If the parent block hash is incorrect, the winning transition won't be used for block verification, and the prover will forfeit their validity bond entirely.](https://taiko.mirror.xyz/Z4I5ZhreGkyfdaL5I9P0Rj0DNX4zaWFmcws-0CVMJ2A#:~:text=If%20the%20parent%20block%20hash%20is%20incorrect%2C%20the%20winning%20transition%20won%27t%20be%20used%20for%20block%20verification%2C%20and%20the%20prover%20will%20forfeit%20their%20validity%20bond%20entirely) If a maliciously proposed block with zero parent block hash is contested and a higher-tier prover ends up proving the proposed block, then he/she loses its own validity bond. + +### Proof of Concept + +The test suite contains the TaikoL1TestBase:proposeBlock that creates new block proposals with a zero parentMetaHash. This is called multiple times at tests like test_L1_verifying_multiple_blocks_once and test_L1_multiple_blocks_in_one_L1_block at the TaikoL1.t.sol test file, demonstrating the lack of reversion if the parentMetaHash is not zero outside of the genesis block. + +### Recommended Mitigation Steps + +Make sure to check the parentMetaHash value is not zero if it isn't at the genesis block, otherwise users are going to be able to wrongly induce contestations. + +**[adaki2004 (Taiko) confirmed](https://github.com/code-423n4/2024-03-taiko-findings/issues/218#issuecomment-2033993978)** + +--- + +## [[M-10] The decision to return the liveness bond depends solely on the last guardian](https://github.com/code-423n4/2024-03-taiko-findings/issues/205) + +_Submitted by [alexfilippov314](https://github.com/code-423n4/2024-03-taiko-findings/issues/205), also found by [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/248)_ + + + + + +### Vulnerability details + +The `GuardianProver` contract is a multisig that might contest any proof in some exceptional cases (bugs in the prover or verifier). To contest a proof, a predefined number of guardians should approve a hash of the message that includes `_meta` and `_tran`. + +```solidity +function approve( + TaikoData.BlockMetadata calldata _meta, + TaikoData.Transition calldata _tran, + TaikoData.TierProof calldata _proof +) + external + whenNotPaused + nonReentrant + returns (bool approved_) +{ + if (_proof.tier != LibTiers.TIER_GUARDIAN) revert INVALID_PROOF(); + + bytes32 hash = keccak256(abi.encode(_meta, _tran)); + approved_ = approve(_meta.id, hash); + + if (approved_) { + deleteApproval(hash); + ITaikoL1(resolve("taiko", false)).proveBlock(_meta.id, abi.encode(_meta, _tran, _proof)); + } + + emit GuardianApproval(msg.sender, _meta.id, _tran.blockHash, approved_); +} +``` + +The issue arises from the fact that the approved message doesn't include the `_proof`. It means that the last approving guardian can provide any desired value in the `_proof`. The data from the `_proof` is used to determine whether it is necessary to return the liveness bond to the assigned prover or not: + +```solidity +if (isTopTier) { + // A special return value from the top tier prover can signal this + // contract to return all liveness bond. + bool returnLivenessBond = blk.livenessBond > 0 && _proof.data.length == 32 + && bytes32(_proof.data) == RETURN_LIVENESS_BOND; + + if (returnLivenessBond) { + tko.transfer(blk.assignedProver, blk.livenessBond); + blk.livenessBond = 0; + } +} +``` + +As a result, the last guardian can solely decide whether to return the liveness bond to the assigned prover or not. + +### Impact + +The decision to return the liveness bond depends solely on the last guardian. + +### Recommended Mitigation Steps + +Consider including the `_proof` in the approved message. + +```solidity +bytes32 hash = keccak256(abi.encode(_meta, _tran, _proof)); +``` + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/205#issuecomment-2079069856):** + +> Now guardian provers must also agree on whether liveness bond should be returned bytes32(\_proof.data) == LibStrings.H_RETURN_LIVENESS_BOND, so the hash they sign is now: +> +> bytes32 hash = keccak256(abi.encode(\_meta, \_tran, \_proof.data)); +> +> rather than the previous code: +> +> bytes32 hash = keccak256(abi.encode(\_meta, \_tran)); + +--- + +## [[M-11] Proposers would choose to avoid higher tier by exploiting non-randomness of parameter used in getMinTier()](https://github.com/code-423n4/2024-03-taiko-findings/issues/172) + +_Submitted by [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/172), also found by [Mahi_Vasisth](https://github.com/code-423n4/2024-03-taiko-findings/issues/54)_ + +The issue exists for both `MainnetTierProvider.sol` and `TestnetTierProvider.sol`. For this report, we shall concentrate only on describing it via `MainnetTierProvider.sol`. + +The proving tier is chosen by the [getMinTier()](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol#L66-L70) function which accepts a `_rand` param. + +```js + File: contracts/L1/tiers/MainnetTierProvider.sol + + 66: function getMinTier(uint256 _rand) public pure override returns (uint16) { + 67: // 0.1% require SGX + ZKVM; all others require SGX + 68: @---> if (_rand % 1000 == 0) return LibTiers.TIER_SGX_ZKVM; + 69: else return LibTiers.TIER_SGX; + 70: } +``` + +If `_rand % 1000 == 0`, a costlier tier `TIER_SGX_ZKVM` is used instead of the cheaper `TIER_SGX`. The `_rand` param is passed in the form of `meta_.difficulty` [which is calculated inside](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibProposing.sol#L199-L209) `proposeBlock()`: + +```js + File: contracts/L1/libs/LibProposing.sol + + 199: // Following the Merge, the L1 mixHash incorporates the + 200: // prevrandao value from the beacon chain. Given the possibility + 201: // of multiple Taiko blocks being proposed within a single + 202: // Ethereum block, we choose to introduce a salt to this random + 203: // number as the L2 mixHash. + 204: @---> meta_.difficulty = keccak256(abi.encodePacked(block.prevrandao, b.numBlocks, block.number)); + 205: + 206: // Use the difficulty as a random number + 207: meta_.minTier = ITierProvider(_resolver.resolve("tier_provider", false)).getMinTier( + 208: @---> uint256(meta_.difficulty) + 209: ); +``` + +As can be seen, all the parameters used in L204 to calculate `meta_.difficulty` can be known in advance and hence a proposer can choose not to propose when `meta_.difficulty` modulus 1000 equals zero, because in such cases it will cost him more to afford the proof (sgx + zk proof in this case). + +### Impact + +Since the proposer will now wait for the next or any future block to call `proposeBlock()` instead of the current costlier one, **transactions will now take longer to finalilze**. + +If `_rand` were truly random, it would have been an even playing field in all situations as the proposer wouldn't be able to pick & choose since he won't know in advance which tier he might get. We would then truly have: + +```js + 67: // 0.1% require SGX + ZKVM; all others require SGX +``` + +### Recommended Mitigation Steps + +Consider using VRF like solutions to make `_rand` truly random. + +**[dantaik (Taiko) acknowledged and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/172#issuecomment-2032346577):** + +> This is a very well known issue. +> +> Using VRF creates a third party dependency which may be a bigger risk for a Based rollup. We'll monitor how this plays out and mitigate the issue later. + +**[adaki2004 (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/172#issuecomment-2034096641):** + +> Eventually we will have only 1 (1 "aggregated ZK multiproof") proof tier, which will be the default/min too. (Maybe keeping guardian for a while to be as a failsafe, but that one also cannot be "picked" with thispseudoe random calculation). +> Also Taiko foundation will run a proposer node, so in case noone is willing to propose to avoid fees, we will, regardless of cost - at least until we reach the 1 tier maturity. + +**[genesiscrew (Warden) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/172#issuecomment-2048545898):** + +> Considering this report and the responses from the sponsors, I am unable to see how this would impact the function of the protocol in such a way that would deem it a medium risk. I personally think this is informational. The report states proving will take longer because it assumes all proposers will want to avoid paying fees because they can predict the block difficulty. I find that a bit of a stretch. + +**[adaki2004 (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/172#issuecomment-2049215839):** + +> Not the proving but the liveness (proposing) would take longer as provers would deny to grant signatures to prove blocks - which's evaluation i happening during `proposeBlock`. +> +> But at least +2 years post mainnet taiko foundation is commited to `proposeBlock` every X time intervals (even if not breaking even) to keep the liveness and get over this. +> +> And as stated, by the time hopefully this minTier() will vanish in that time - hopefully even in months after launch (not years) when ZK is cheap enough. So for now we would say it is a known issue, we are aware of. + +**[t0x1c (Warden) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/172#issuecomment-2051225141):** + +> Thank you for the inputs. From what I see, this is being acknowledged by the sponsor as a valid issue which is known to the team. +> Also important to note that it wasn't mentioned in the list of C4 "known issues" section on the audit page, so should qualify as a Medium. + +**[adaki2004 (Taiko) commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/172#issuecomment-2051231358):** + +> Can accept medium. + +--- + +## [[M-12] Invocation delays are not honoured when protocol unpauses](https://github.com/code-423n4/2024-03-taiko-findings/issues/170) + +_Submitted by [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/170)_ + + + + + +**_Context:_** The protocol has `pause()` and [unpause()](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/EssentialContract.sol#L78) functions inside `EssentialContract.sol` which are tracked throughout the protocol via the modifiers [whenPaused](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/EssentialContract.sol#L53) and [whenNotPaused](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/EssentialContract.sol#L58). + +**_Issue:_** Various delays and time lapses throughout the protocol ignore the effect of such pauses. The example in focus being that of `processMessage()` which does not take into account the pause duration while [checking invocationDelay and invocationExtraDelay](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L233-L258). One impact of this is that it allows a non-preferred executor to front run a preferredExecutor, after an unpause. + +```js + File: contracts/bridge/Bridge.sol + + 233: @---> (uint256 invocationDelay, uint256 invocationExtraDelay) = getInvocationDelays(); + 234: + 235: if (!isMessageProven) { + 236: if (!_proveSignalReceived(signalService, msgHash, _message.srcChainId, _proof)) { + 237: revert B_NOT_RECEIVED(); + 238: } + 239: + 240: receivedAt = uint64(block.timestamp); + 241: + 242: if (invocationDelay != 0) { + 243: proofReceipt[msgHash] = ProofReceipt({ + 244: receivedAt: receivedAt, + 245: preferredExecutor: _message.gasLimit == 0 ? _message.destOwner : msg.sender + 246: }); + 247: } + 248: } + 249: + 250: if (invocationDelay != 0 && msg.sender != proofReceipt[msgHash].preferredExecutor) { + 251: // If msg.sender is not the one that proved the message, then there + 252: // is an extra delay. + 253: unchecked { + 254: invocationDelay += invocationExtraDelay; + 255: } + 256: } + 257: + 258: @---> if (block.timestamp >= invocationDelay + receivedAt) { +``` + +### Description & Impact + +Consider the following flow: + +- Assumption: `invocationDelay = 60 minutes` and `invocationExtraDelay = 30 minutes`. +- A message is sent. +- First call to `processMessage()` occurred at `t` where it was proven by Bob i.e. its `receivedAt = t`. Bob is marked as the `preferredExecutor`. +- Preferred executor should be able to call `processMessage()` at `t+60` while a non-preferred executor should be able to call it only at `t+90` due to the code logic on [L250](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L250). +- At `t+55`, protocol is paused. +- At `t+100`, protocol is unpaused. +- **_Impact:_** The 30-minute time window advantage which the preferred executor had over the non-preferred one is now lost to him. [L258](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L258) now considers the invocation delays to have passed and hence the non-preferred executor can immediately call `processMessage()` by front-running Bob and hence pocketing the reward of `message.fee` on [L98](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L298). + +```js + File: contracts/bridge/Bridge.sol + + 293: // Refund the processing fee + 294: if (msg.sender == refundTo) { + 295: refundTo.sendEther(_message.fee + refundAmount); + 296: } else { + 297: // If sender is another address, reward it and refund the rest + 298: @---> msg.sender.sendEther(_message.fee); + 299: refundTo.sendEther(refundAmount); + 300: } +``` + +Similar behaviour where the paused time is ignored by the protocol can be witnessed in: + +- [recallMessage()](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L187-L189) which similarly uses `invocationDelay`. However, no `invocationExtraDelay` is used there. +- [TimelockTokenPool.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/TimelockTokenPool.sol) for: + +```js + // If non-zero, indicates the start time for the recipient to receive + // tokens, subject to an unlocking schedule. + uint64 grantStart; + // If non-zero, indicates the time after which the token to be received + // will be actually non-zero + uint64 grantCliff; + // If non-zero, specifies the total seconds required for the recipient + // to fully own all granted tokens. + uint32 grantPeriod; + // If non-zero, indicates the start time for the recipient to unlock + // tokens. + uint64 unlockStart; + // If non-zero, indicates the time after which the unlock will be + // actually non-zero + uint64 unlockCliff; + // If non-zero, specifies the total seconds required for the recipient + // to fully unlock all owned tokens. + uint32 unlockPeriod; +``` + +- [TaikoData.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoData.sol) for: + +```js + // The max period in seconds that a blob can be reused for DA. + uint24 blobExpiry; +``` + +### Recommended Mitigation Steps + +Introduce a new variable which keeps track of how much time has already been spent in the valid wait window before a pause happened. Also track the last unpause timestamp (similar to how it is done in [pauseProving()](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoL1.sol#L111) and [unpausing](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoL1.sol#L124) mechanisms). +Also refer my other recommendation under the report titled: _"Incorrect calculations for cooldownWindow and provingWindow could cause a state transition to spend more than expected time in these windows"_. That will help fix the issue without any further leaks. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/170#issuecomment-2032338122):** + +> This is a valid bug report, fixing in https://github.com/taikoxyz/taiko-mono/pull/16612 +> +> TimelockTokenPool.sol will not have a similar fix as the risk is very managable. Blob caching/sharing is disabled, so no fix for it as well. + +--- + +## [[M-13] Taiko SGX Attestation - Improper validation in certchain decoding](https://github.com/code-423n4/2024-03-taiko-findings/issues/168) + +_Submitted by [zzebra83](https://github.com/code-423n4/2024-03-taiko-findings/issues/168)_ + + + + + +As part of of its ZK proof setup, Taiko leverages SGX provers. it also enables remote SGX attestation and this is possible via leveraging code from Automata, which provides a modular attestation layer extending machine-level trust to Ethereum via the AutomataDcapV3Attestation repo, which is in scope of this audit. + +Anyone with SGX hardware can register their instance to be an SGX prover in the Taiko Network via calling the registerInstance function in SgxVerifier.sol. This is why attestation is critical to prove the reliability and trustworthiness of the SGX prover. + +The attestation process of SGX provers is a multi fold process, and starts with calling the verifyParsedQuote function in AutomataDcapV3Attestation.sol. One of the steps involves decoding the certchain provided by the SGX prover, as seen below: + + // Step 4: Parse Quote CertChain + IPEMCertChainLib.ECSha256Certificate[] memory parsedQuoteCerts; + TCBInfoStruct.TCBInfo memory fetchedTcbInfo; + { + // 536k gas + parsedQuoteCerts = new IPEMCertChainLib.ECSha256Certificate[](3); + for (uint256 i; i < 3; ++i) { + bool isPckCert = i == 0; // additional parsing for PCKCert + bool certDecodedSuccessfully; + // todo! move decodeCert offchain + (certDecodedSuccessfully, parsedQuoteCerts[i]) = pemCertLib.decodeCert( + authDataV3.certification.decodedCertDataArray[i], isPckCert + ); + if (!certDecodedSuccessfully) { + return (false, retData); + } + } + } + +after this step is executed, a number of other steps are done including: + +Step 5: basic PCK and TCB check +Step 6: Verify TCB Level +Step 7: Verify cert chain for PCK +Step 8: Verify the local attestation sig and qe report sig + +The decoding of the certchain happens through the EMCertChainLib lib, and this involves a number of steps, one of which is to validate the decoded notBefore and notAfter tags of the certificate: + + { + uint256 notBeforePtr = der.firstChildOf(tbsPtr); + uint256 notAfterPtr = der.nextSiblingOf(notBeforePtr); + bytes1 notBeforeTag = der[notBeforePtr.ixs()]; + bytes1 notAfterTag = der[notAfterPtr.ixs()]; + if ( + (notBeforeTag != 0x17 && notBeforeTag == 0x18) + || (notAfterTag != 0x17 && notAfterTag != 0x18) + ) { + return (false, cert); + } + cert.notBefore = X509DateUtils.toTimestamp(der.bytesAt(notBeforePtr)); + cert.notAfter = X509DateUtils.toTimestamp(der.bytesAt(notAfterPtr)); + } + +These fields determine the time format, whether the notBeforePtr and notAfterPtr are in UTC or generalized time, and are used to ensure consistency in timestamps used to determine the validity period of the certificate. + +However the validation can fail because the logic above is faulty, as it will allow the attestor to pass in any value for the notBefore tag, indeeed the condition of: + + (notBeforeTag != 0x17 && notBeforeTag == 0x18) + +will allow the attestor to pass in any beforetag because the condition will always be false. + +Consider if we pass an invalid tag of 0x10: + +1. notBeforeTag != 0x17 is True. +2. notBeforeTag == 0x18 is False. +3. full condition is False. + +I believe the original intention was to ensure the beforeTag is strictly 0x17 or 0x18, just as with the afterTag. Because of this oversight, a malicious attestor could pass in any notBefore Tag as part of their certificate. + +This issue requires attention given the significance of the attestation process of SGX provers within Taiko's ZK setup. The whole point of attestation is to prove the SGX provers are secure, untampered, and trustworthy, and improper validation related to certificate validity periods can have unforeseen consequences. + +### Recommended Mitigation Steps + +Update the condition as below: + + if ( + (notBeforeTag != 0x17 && notBeforeTag != 0x18) + || (notAfterTag != 0x17 && notAfterTag != 0x18) + ) { + return (false, cert); + +**[smtmfft (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/168#issuecomment-2033492460):** + +> I think this is a valid catch, already submitted a fix. + +--- + +## [[M-14] Malicious caller of `processMessage()` can pocket the fee while forcing `excessivelySafeCall()` to fail](https://github.com/code-423n4/2024-03-taiko-findings/issues/97) + +_Submitted by [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/97), also found by [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/223) and [ladboy233](https://github.com/code-423n4/2024-03-taiko-findings/issues/180)_ + +The logic inside function `processMessage()` [provides a reward to the msg.sender](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L298) if they are not the `refundTo` address. However this reward or `_message.fee` is awarded even if the `_invokeMessageCall()` on [L282](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L282) fails and the message goes into a `RETRIABLE` state. In the retriable state, it has to be called by someone again and the current `msg.sender` has no obligation to be the one to call it. + +This logic can be gamed by a malicious user using the **63/64th rule specified in** [EIP-150](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-150.md). + +```js + File: contracts/bridge/Bridge.sol + + 278: // Use the specified message gas limit if called by the owner, else + 279: // use remaining gas + 280: @---> uint256 gasLimit = msg.sender == _message.destOwner ? gasleft() : _message.gasLimit; + 281: + 282: @---> if (_invokeMessageCall(_message, msgHash, gasLimit)) { + 283: _updateMessageStatus(msgHash, Status.DONE); + 284: } else { + 285: @---> _updateMessageStatus(msgHash, Status.RETRIABLE); + 286: } + 287: } + 288: + 289: // Determine the refund recipient + 290: address refundTo = + 291: _message.refundTo == address(0) ? _message.destOwner : _message.refundTo; + 292: + 293: // Refund the processing fee + 294: if (msg.sender == refundTo) { + 295: refundTo.sendEther(_message.fee + refundAmount); + 296: } else { + 297: // If sender is another address, reward it and refund the rest + 298: @---> msg.sender.sendEther(_message.fee); + 299: refundTo.sendEther(refundAmount); + 300: } +``` + +### Description + +The `_invokeMessageCall()` on [L282](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L282) internally calls `excessivelySafeCall()` on [L497](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L497). When `excessivelySafeCall()` makes an external call, only 63/64th of the gas is used by it. Thus the following scenario can happen: + +- Malicious user notices that [L285-L307](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L285-L307) uses approx 165_000 gas. + +- He also notices that [L226-L280](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol#L226-L280) uses approx 94_000 gas. + +- He calculates that he must provide approximately a minimum of `94000 + (64 * 165000) = 10_654_000` gas so that the function execution does not revert anywhere. + +- Meanwhile, a message owner has message which has a `_message.gasLimit` of 11_000_000. This is so because the `receive()` function of the contract receiving ether is expected to consume gas in this range due to its internal calls & transactions. The owner expects at least 10_800_000 of gas would be used up and hence has provided some extra buffer. + +- Note that **any message** that has a processing requirement of greater than `63 * 165000 = 10_395_000` gas can now become a target of the malicious user. + +- Malicious user now calls `processMessage()` with a specific gas figure. Let's use an example figure of `{gas: 10_897_060}`. This means only `63/64 * (10897060 - 94000) = 10_634_262` is forwarded to `excessivelySafeCall()` and `1/64 * (10897060 - 94000) = 168_797` will be kept back which is enough for executing the remaining lines of code L285-L307. Note that since `(10897060 - 94000) = 10_803_060` which is less than the message owner's provided `_message.gasLimit` of `11_000_000`, what actually gets considered is only `10_803_060`. + +- The external call reverts inside `receive()` due to out of gas error (since 10_634_262 < 10_800_000) and hence `_success` is set to `false` on [L44](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol#L44). + +- The remaining L285-L307 are executed and the malicious user receives his reward. + +- The message goes into `RETRIABLE` state now and someone will need to call `retryMessage()` later on. + +A different bug report titled **_"No incentive for message non-owners to retryMessage()"_** has also been raised which highlights the incentivization scheme of `retryMessage()`. + +### Impact + +- Protocol can be gamed by a user to gain rewards while additionaly saving money by providing the least possible gas. + +- There is no incentive for any external user now to ever provide more than `{gas: 10_897_060}` (approx figure). + +### Proof of Concept + +Apply the following patch to add the test inside `protocol/test/bridge/Bridge.t.sol` and run via `forge test -vv --mt test_t0x1c_gasManipulation` to see it pass: + +
+ +```diff +diff --git a/packages/protocol/test/bridge/Bridge.t.sol b/packages/protocol/test/bridge/Bridge.t.sol +index 6b7dca6..ce77ce2 100644 +--- a/packages/protocol/test/bridge/Bridge.t.sol ++++ b/packages/protocol/test/bridge/Bridge.t.sol +@@ -1,11 +1,19 @@ + // SPDX-License-Identifier: MIT + pragma solidity 0.8.24; + + import "../TaikoTest.sol"; + ++contract ToContract { ++ receive() external payable { ++ uint someVar; ++ for(uint loop; loop < 86_990; ++loop) ++ someVar += 1e18; ++ } ++} ++ + // A contract which is not our ErcXXXTokenVault + // Which in such case, the sent funds are still recoverable, but not via the + // onMessageRecall() but Bridge will send it back + contract UntrustedSendMessageRelayer { + function sendMessage( + address bridge, +@@ -115,12 +123,71 @@ contract BridgeTest is TaikoTest { + register(address(addressManager), "bridge", address(destChainBridge), destChainId); + + register(address(addressManager), "taiko", address(uint160(123)), destChainId); + vm.stopPrank(); + } + ++ ++ function test_t0x1c_gasManipulation() public { ++ //**************** SETUP ********************** ++ ToContract toContract = new ToContract(); ++ IBridge.Message memory message = IBridge.Message({ ++ id: 0, ++ from: address(bridge), ++ srcChainId: uint64(block.chainid), ++ destChainId: destChainId, ++ srcOwner: Alice, ++ destOwner: Alice, ++ to: address(toContract), ++ refundTo: Alice, ++ value: 1000, ++ fee: 1000, ++ gasLimit: 11_000_000, ++ data: "", ++ memo: "" ++ }); ++ // Mocking proof - but obviously it needs to be created in prod ++ // corresponding to the message ++ bytes memory proof = hex"00"; ++ ++ bytes32 msgHash = destChainBridge.hashMessage(message); ++ ++ vm.chainId(destChainId); ++ skip(13 hours); ++ assertEq(destChainBridge.messageStatus(msgHash) == IBridge.Status.NEW, true); ++ uint256 carolInitialBalance = Carol.balance; ++ ++ uint256 snapshot = vm.snapshot(); ++ //**************** SETUP ENDS ********************** ++ ++ ++ ++ //**************** NORMAL USER ********************** ++ console.log("\n**************** Normal User ****************"); ++ vm.prank(Carol, Carol); ++ destChainBridge.processMessage(message, proof); ++ ++ assertEq(destChainBridge.messageStatus(msgHash) == IBridge.Status.DONE, true); ++ assertEq(Carol.balance, carolInitialBalance + 1000, "Carol balance mismatch"); ++ if (destChainBridge.messageStatus(msgHash) == IBridge.Status.DONE) ++ console.log("message status = DONE"); ++ ++ ++ ++ //**************** MALICIOUS USER ********************** ++ vm.revertTo(snapshot); ++ console.log("\n**************** Malicious User ****************"); ++ vm.prank(Carol, Carol); ++ destChainBridge.processMessage{gas: 10_897_060}(message, proof); // @audit-info : specify gas to force failure of excessively safe external call ++ ++ assertEq(destChainBridge.messageStatus(msgHash) == IBridge.Status.RETRIABLE, true); // @audit : message now in RETRIABLE state. Carol receives the fee. ++ assertEq(Carol.balance, carolInitialBalance + 1000, "Carol balance mismatched"); ++ if (destChainBridge.messageStatus(msgHash) == IBridge.Status.RETRIABLE) ++ console.log("message status = RETRIABLE"); ++ } ++ + function test_Bridge_send_ether_to_to_with_value() public { + IBridge.Message memory message = IBridge.Message({ + id: 0, + from: address(bridge), + srcChainId: uint64(block.chainid), + destChainId: destChainId, +``` + +
+ +### Tools Used + +Foundry + +### Recommended Mitigation Steps + +Reward the `msg.sender` (provided it's a _non-refundTo_ address) with `_message.fee` only if `_invokeMessageCall()` returns `true`. Additionally, it is advisable to release this withheld reward after a successful `retryMessage()` to that function's caller. + +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/97#issuecomment-2032446424):** + +> Fixed in https://github.com/taikoxyz/taiko-mono/pull/16613 +> +> I don't think paying fees only when `_invokeMessageCall` returns true is a good idea as this will require the relayer to simulate all transactions without guaranteed reward. + +--- + +# Low Risk and Non-Critical Issues + +For this audit, 33 reports were submitted by wardens detailing low risk and non-critical issues. The [report highlighted below](https://github.com/code-423n4/2024-03-taiko-findings/issues/335) by **MrPotatoMagic** received the top score from the judge. + +_The following wardens also submitted reports: [Shield](https://github.com/code-423n4/2024-03-taiko-findings/issues/255), [Sathish9098](https://github.com/code-423n4/2024-03-taiko-findings/issues/120), [rjs](https://github.com/code-423n4/2024-03-taiko-findings/issues/372), [zabihullahazadzoi](https://github.com/code-423n4/2024-03-taiko-findings/issues/366), [JCK](https://github.com/code-423n4/2024-03-taiko-findings/issues/357), [cheatc0d3](https://github.com/code-423n4/2024-03-taiko-findings/issues/355), [DadeKuma](https://github.com/code-423n4/2024-03-taiko-findings/issues/343), [0x11singh99](https://github.com/code-423n4/2024-03-taiko-findings/issues/338), [monrel](https://github.com/code-423n4/2024-03-taiko-findings/issues/329), [slvDev](https://github.com/code-423n4/2024-03-taiko-findings/issues/326), [grearlake](https://github.com/code-423n4/2024-03-taiko-findings/issues/318), [Masamune](https://github.com/code-423n4/2024-03-taiko-findings/issues/311), [imare](https://github.com/code-423n4/2024-03-taiko-findings/issues/304), [josephdara](https://github.com/code-423n4/2024-03-taiko-findings/issues/300), [t0x1c](https://github.com/code-423n4/2024-03-taiko-findings/issues/265), [sxima](https://github.com/code-423n4/2024-03-taiko-findings/issues/235), [joaovwfreire](https://github.com/code-423n4/2024-03-taiko-findings/issues/217), [alexfilippov314](https://github.com/code-423n4/2024-03-taiko-findings/issues/209), [pfapostol](https://github.com/code-423n4/2024-03-taiko-findings/issues/195), [ladboy233](https://github.com/code-423n4/2024-03-taiko-findings/issues/188), [hihen](https://github.com/code-423n4/2024-03-taiko-findings/issues/176), [Pechenite](https://github.com/code-423n4/2024-03-taiko-findings/issues/160), [clara](https://github.com/code-423n4/2024-03-taiko-findings/issues/151), [pa6kuda](https://github.com/code-423n4/2024-03-taiko-findings/issues/148), [albahaca](https://github.com/code-423n4/2024-03-taiko-findings/issues/146), [foxb868](https://github.com/code-423n4/2024-03-taiko-findings/issues/140), [Myd](https://github.com/code-423n4/2024-03-taiko-findings/issues/125), [t4sk](https://github.com/code-423n4/2024-03-taiko-findings/issues/49), [Fassi_Security](https://github.com/code-423n4/2024-03-taiko-findings/issues/28), [oualidpro](https://github.com/code-423n4/2024-03-taiko-findings/issues/20), [Kalyan-Singh](https://github.com/code-423n4/2024-03-taiko-findings/issues/15), and [n1punp](https://github.com/code-423n4/2024-03-taiko-findings/issues/11)._ + +## [L-01] Consider initializing ContextUpgradeable contract by calling \_\_Context_init() in TaikoToken.sol + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L25) + +ContextUpgradeable is not initialized in TaikoToken.sol contract. This contract is used in ERC20PermitUpgradeable which is used in ERC20VotesUpgradeable. But neither contract initializes this Context contract when the contracts themselves are intialized. + +In TaikoToken.sol [here](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L25), we can see that the below \_\_Context_init() function is not called. + +```solidity +File: ContextUpgradeable.sol +18: function __Context_init() internal onlyInitializing { +19: } +20: +21: function __Context_init_unchained() internal onlyInitializing { +22: } +``` + +## [L-02] \_\_ERC1155Receiver_init() not initialized in ERC1155Vault + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L29) + +Consider initializing these functions in an init() function in the ERC1155Vault contract. + +```solidity +File: ERC1155ReceiverUpgradeable.sol +14: function __ERC1155Receiver_init() internal onlyInitializing { +15: } +16: +17: function __ERC1155Receiver_init_unchained() internal onlyInitializing { +18: } +``` + +## [L-03] If amountUnlocked in TimelockTokenPool is less than 1e18, rounding down occurs + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L197) + +If amountUnlocked is less than 1e18, round down occurs. This is not a problem since grants will usually be dealing with way higher values and thus higher unlocking. But this would be a problem for team members or advisors getting maybe 10 taiko or less (in case price of taiko is high). So the more frequent the withdrawing there might be chances of losing tokens due to round down. + +```solidity +File: TimelockTokenPool.sol +198: uint128 _amountUnlocked = amountUnlocked / 1e18; // divide first +``` + +## [L-04] sendSignal() calls can be spammed by attacker to relayer + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L63) + +Since the function is external, an attacker can continuously spam signals to the offchain relayer which is always listening to signals. This would be more cost efficient on Taiko where fees are cheap. + +The signals could also be used to mess with the relayer service i.e. by sending a the same signal early by frontrunning a user's bytes32 signal \_parameter. + +```solidity +File: SignalService.sol +68: function sendSignal(bytes32 _signal) external returns (bytes32) { +69: return _sendSignal(msg.sender, _signal, _signal); +70: } +``` + +## [L-05] Add "Zero if owner will process themself" comment to gasLimit instead of fee + +In the current code, the preferredExecutor for executing bridged transactions is determined by whether the gasLimit is 0 or not and not the fee. + +```solidity +File: IBridge.sol +38: // Processing fee for the relayer. Zero if owner will process themself. +39: uint256 fee; +40: // gasLimit to invoke on the destination chain. +41: uint256 gasLimit; +``` + +## [L-06] Bridge integration issues with swapping protocols + +Cross-chain swapping could not occur on chains having long invocation delays since deadline of the swap might expire and become outdated. Consider having custom delays for dapps looking to use bridge. + +```solidity +File: Bridge.sol +459: /// the transactor is not the preferredExecutor who proved this message. +460: function getInvocationDelays() +461: public +462: view +463: virtual +464: returns (uint256 invocationDelay_, uint256 invocationExtraDelay_) +465: { +466: if ( +467: block.chainid == 1 // Ethereum mainnet +468: ) { +469: // For Taiko mainnet +470: // 384 seconds = 6.4 minutes = one ethereum epoch +471: return (1 hours, 384 seconds); +472: } else if ( +473: block.chainid == 2 || // Ropsten +474: block.chainid == 4 || // Rinkeby +475: block.chainid == 5 || // Goerli +476: block.chainid == 42 || // Kovan +477: block.chainid == 17_000 || // Holesky +478: block.chainid == 11_155_111 // Sepolia +479: ) { +480: // For all Taiko public testnets +481: return (30 minutes, 384 seconds); +482: } else if (block.chainid >= 32_300 && block.chainid <= 32_400) { +483: // For all Taiko internal devnets +484: return (5 minutes, 384 seconds); +485: } else { +486: // This is a Taiko L2 chain where no deleys are applied. +487: return (0, 0); +488: } +489: } +``` + +## [L-07] sendMessage() does not check if STATUS is equal to NEW + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L115) + +Adding a sanity check would be good to avoid being able to call message that is not in the STATUS = NEW state. This would ensure retriable, recalls and failed txns cannot be repeated again. + +```solidity +File: Bridge.sol +119: function sendMessage( +120: Message calldata _message +121: ) +122: external +123: payable +124: override +125: nonReentrant +126: whenNotPaused +127: returns (bytes32 msgHash_, Message memory message_) +128: { +129: // Ensure the message owner is not null. +130: if ( +131: _message.srcOwner == address(0) || _message.destOwner == address(0) +132: ) { +133: revert B_INVALID_USER(); +134: } +135: +136: // Check if the destination chain is enabled. +137: (bool destChainEnabled, ) = isDestChainEnabled(_message.destChainId); +138: +139: // Verify destination chain and to address. +140: if (!destChainEnabled) revert B_INVALID_CHAINID(); +141: if (_message.destChainId == block.chainid) { +142: revert B_INVALID_CHAINID(); +143: } +144: +145: // Ensure the sent value matches the expected amount. +146: +148: uint256 expectedAmount = _message.value + _message.fee; +149: if (expectedAmount != msg.value) revert B_INVALID_VALUE(); +150: +151: message_ = _message; +152: +153: // Configure message details and send signal to indicate message sending. +154: message_.id = nextMessageId++; +155: message_.from = msg.sender; +156: message_.srcChainId = uint64(block.chainid); +157: +158: msgHash_ = hashMessage(message_); +159: +160: ISignalService(resolve("signal_service", false)).sendSignal(msgHash_); +161: emit MessageSent(msgHash_, message_); +162: } +``` + +## [L-08] Protocol does not refund extra ETH but implements strict check + +[See spec here](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L105) + +The IBridge.sol contract specifies that extra ETH provided when sending a message is refunded back to the user. This currently does not happen since the code implements strict equality check. Using strict equality is better but pointing out the spec described, which would either be followed in the code implemented or the spec should be described properly in the IBridge.sol contract. + +```solidity +File: Bridge.sol +146: uint256 expectedAmount = _message.value + _message.fee; +147: if (expectedAmount != msg.value) revert B_INVALID_VALUE(); +``` + +## [L-09] If a message is suspended before processMessage() is called, the ERC20 tokens on the source chain and Ether are not refunded. + +If a message is suspended before processMessage() is called, the status of the message remains new and the ERC20 tokens on the source and the Ether is locked as well. If the message will never be unsuspended, consider refunding the tokens to the user. + +```solidity +File: Bridge.sol +287: if (block.timestamp >= invocationDelay + receivedAt) { +288: // If the gas limit is set to zero, only the owner can process the message. +289: if (_message.gasLimit == 0 && msg.sender != _message.destOwner) { +290: revert B_PERMISSION_DENIED(); +291: } +``` + +## [L-10] User loses all Ether if their address is blacklisted on canonical token + +When recalls are made on the source chain using the function recallMessage(), it calls the onMessageRecalled() function on the ERC20Vault contract. The onMessageRecalled() function transfers the ERC20 tokens back to the user along with any Ether that was supplied. + +The issue is with this dual transfer where both ERC20 tokens are Ether are transferred to the user in the same call. If the user is blacklisted on the canonical token, the whole call reverts, causing the Ether to be stuck in the Bridge contract. + +To understand this, let's consider a simple example: + +1. User bridges ERC20 canonical tokens and Ether from chain A to chain B. +2. The message call on the destination chain B goes into RETRIABLE status if it fails for the first time. (**Note: User can only process after invocation delay**). +3. On multiple retries after a while, the user decides to make a last attempt, on which the call fails and goes into FAILED status. +4. During this time on chain B, the user was blacklisted on the ERC20 canonical token on the source chain. +5. When the failure signal is received by the source chain A from chain B, the user calls recallMessage() on chain A only to find out that although the blacklist is only for the canonical ERC20 token, the Ether is stuck as well. + +## [L-11] onMessageInvocation checks in \_invokeMessageCall() can be bypassed to call arbitrary function from Bridge contract + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L490) + +The if block requires the data to be greater than equal to 4 bytes, equal to the onMessageInvocation selector and last but not the least for the target address to be a contract. + +What an attacker could do to bypass this expected spec is to pre-compute an address for the destination chain and pass it in `_message.to`. He can pass gasLimit = 0 from source to only allow him to process the message on the destination. + +On the destination chain, the attacker can deploy his pre-computed contract address and call processMessage() with it from the constructor. For a chain (L2s/L3s) with no invocation delays, the proving + executing of the message data would go through in one single call. + +When we arrive at the isContract check below on the `_message.to` address, we evaluate to false since the size of the contract during construction is 0. Due to this, the attacker can validly bypass the onMessageInvocation selector that is a requirement/single source of tx origination by the protocol for all transactions occurring from the bridge contract. This breaks a core invariant of the protocol. + +```solidity +File: Bridge.sol +513: if ( +514: _message.data.length >= 4 && // msg can be empty +515: bytes4(_message.data) != +516: IMessageInvocable.onMessageInvocation.selector && +517: _message.to.isContract() +518: ) { +519: success_ = false; +520: } else { +521: (success_, ) = ExcessivelySafeCall.excessivelySafeCall( +522: _message.to, +523: _gasLimit, +524: _message.value, +525: 64, // return max 64 bytes +526: _message.data +527: ); +528: } +``` + +## [L-12] Consider reading return value from snapshot() function + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52) + +The snapshot() function returns a uint256 snapshotId. These ids if retrieved earlier can make the devs life easier when taking multiple timely snapshots. + +```solidity +File: TaikoToken.sol +54: function snapshot() public onlyFromOwnerOrNamed("snapshooter") { +55: _snapshot(); +56: } +``` + +## [L-13] One off error in block sync threshold check to sync chain data + +The check should be \_l1BlockId >= lastSyncedBlock + BLOCK_SYNC_THRESHOLD since threshold is the minimum threshold. + +```solidity +File: TaikoL2.sol +150: if (_l1BlockId > lastSyncedBlock + BLOCK_SYNC_THRESHOLD) { +151: // Store the L1's state root as a signal to the local signal service to +152: // allow for multi-hop bridging. +153: ISignalService(resolve("signal_service", false)).syncChainData( +154: ownerChainId, +155: LibSignals.STATE_ROOT, +156: _l1BlockId, +157: _l1StateRoot +158: ); +``` + +Same issue here: + +```solidity +File: LibVerifying.sol +240: if (_lastVerifiedBlockId > lastSyncedBlock + _config.blockSyncThreshold) { +241: signalService.syncChainData( +242: _config.chainId, LibSignals.STATE_ROOT, _lastVerifiedBlockId, _stateRoot +243: ); +244: } +``` + +## [L-14] One-off error when evaluating deposits to process with the ring buffer size + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L141) + +When calculating the deposits to process, we do not want to overwrite existing slots. This is why the last check/condition is implemented. + +The issue with the condition is that it is one-off by the max size the ring bugger allows. Since + 1 is already added, make the check < into <= to work to it's full capacity. + +```solidity +File: LibDepositing.sol +148: unchecked { +149: +150: return +151: _amount >= _config.ethDepositMinAmount && +152: _amount <= _config.ethDepositMaxAmount && +153: _state.slotA.numEthDeposits - +154: _state.slotA.nextEthDepositToProcess < +155: _config.ethDepositRingBufferSize - 1; +156: } +``` + +## [R-01] Consider implementing changeBridgedToken() and btokenBlacklist for ERC721Vault and ERC1155Vault + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L29) + +Both vaults are currently missing these two functions. Implementing them is not required but it would be good as a safety net for high-valued NFT collections in emergency scenarios that could arise. + +## [R-02] Instead of passing an empty string for the data parameter in NFT vaults on token transfers, allow users to supply data + +Allow users to supply the data parameter when transferring tokens from vault to them to ensure any off-chain compatibility/functionality can be built. + +```solidity +File: ERC1155Vault.sol +227: function _transferTokens( +228: CanonicalNFT memory ctoken, +229: address to, +230: uint256[] memory tokenIds, +231: uint256[] memory amounts +232: ) private returns (address token) { +233: if (ctoken.chainId == block.chainid) { +234: // Token lives on this chain +235: token = ctoken.addr; +236: +237: IERC1155(token).safeBatchTransferFrom( +238: address(this), +239: to, +240: tokenIds, +241: amounts, +242: "" +243: ); +``` + +## [R-03] Use named imports to improve readability of the code and avoid polluting the global namespace + +```solidity +File: LibAddress.sol +4: import "@openzeppelin/contracts/utils/Address.sol"; +5: import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +6: import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +7: import "@openzeppelin/contracts/interfaces/IERC1271.sol"; +8: import "../thirdparty/nomad-xyz/ExcessivelySafeCall.sol"; +``` + +## [N-01] Avoid hardcoding data in BridgedERC1155 + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L52) + +Instead of hardcoding the data, place it in a constant variable and assign the variables here for better maintainability. + +```solidity +File: BridgedERC1155.sol +53: LibBridgedToken.validateInputs(_srcToken, _srcChainId, "foo", "foo"); +``` + +## [N-02] Missing source()/canonical() function on BridgedERC115 contract + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L52) + +The BridgedERC1155 contract should implement a similar function to source()/canonical() as done in the other two vaults. This would better for external dapps to retrieve the data much easily. + +## [N-03] Using unchecked arithmetic in for loops is handled by solc compiler 0.8.22 onwards + +```solidity +File: MerkleTrie.sol +205: function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory proof_) { +206: uint256 length = _proof.length; +207: proof_ = new TrieNode[](length); +208: for (uint256 i = 0; i < length;) { +209: proof_[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) }); +210: +211: unchecked { +212: ++i; +213: } +214: } +215: } +``` + +## [N-04] Typo in comment in Bytes.sol + +Use rather instead of rathern. + +```solidity +File: Bytes.sol +93: /// @notice Slices a byte array with a given starting index up to the end of the original byte +94: /// array. Returns a new array rathern than a pointer to the original. +``` + +## [N-05] Incorrect comment regarding gasLimit in processMessage() + +As confirmed with the sponsor, the comment above the gasLimit variable should be inversed i.e. use gasLeft is called by owner, else gasLimit + +```solidity +File: Bridge.sol +307: } else { +308: // Use the specified message gas limit if called by the owner, else +309: // use remaining gas +310: +311: uint256 gasLimit = msg.sender == _message.destOwner +312: ? gasleft() +313: : _message.gasLimit; +``` + +## [N-06] Use require instead of assert + +Use require instead of assert to avoid Panic error, see solidity docs [here](https://docs.soliditylang.org/en/v0.8.25/control-structures.html#panic-via-assert-and-error-via-require). + +```solidity +File: Bridge.sol +503: function _invokeMessageCall( +504: Message calldata _message, +505: bytes32 _msgHash, +506: uint256 _gasLimit +507: ) private returns (bool success_) { +508: if (_gasLimit == 0) revert B_INVALID_GAS_LIMIT(); +509: assert(_message.from != address(this)); +``` + +## [N-07] Incorrect natspec comment for proveMessageReceived() + +Correct first comment on Line 394 to "msgHash has been received" + +```solidity +File: Bridge.sol +394: /// @notice Checks if a msgHash has failed on its destination chain. +395: /// @param _message The message. +396: /// @param _proof The merkle inclusion proof. +397: /// @return true if the message has failed, false otherwise. +398: function proveMessageReceived( +399: Message calldata _message, +400: bytes calldata _proof +401: ) public view returns (bool) { +``` + +## [N-08] Missing address(0) check for USDC in USDCAdapter + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L38) + +It is important to implement this check in init() functions since they can only be called once. + +```solidity +File: USDCAdapter.sol +38: function init(address _owner, address _addressManager, IUSDC _usdc) external initializer { +39: __Essential_init(_owner, _addressManager); +40: +41: usdc = _usdc; +42: } +``` + +## [N-09] srcToken and srcChainId is not updated on old token after migration through changeBridgedToken() + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L73) + +When a token is migrated to another token, the old token still points towards the same srcToken and srcChainId as the new token since they are not updated through changeBridgedToken(). + +Due to this external dapps integrating and using these values as reference could run into potential issues. Consider clearing them or changing them to some placeholder data representing the src token and chainId but with a prefix. + +```solidity +File: BridgedERC20.sol +123: function canonical() public view returns (address, uint256) { +124: return (srcToken, srcChainId); +125: } +``` + +## [N-10] MerkleClaimable does not check if claimStart is less than claimEnd + +```solidity +File: MerkleClaimable.sol +90: function _setConfig(uint64 _claimStart, uint64 _claimEnd, bytes32 _merkleRoot) private { +91: +92: claimStart = _claimStart; +93: claimEnd = _claimEnd; +94: merkleRoot = _merkleRoot; +95: } +``` + +## [N-11] Consider reading return value from snapshot() function + +[Link](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52) + +The snapshot() function returns a uint256 snapshotId. These ids if retrieved earlier can make the devs life easier when taking multiple timely snapshots. + +```solidity +File: TaikoToken.sol +54: function snapshot() public onlyFromOwnerOrNamed("snapshooter") { +55: _snapshot(); +56: } +``` + +## [N-12] Guardian proof that is never fully approved by minGuardians is never deleted + +A guardian proof hashs is only deleted if it has been approved by min number of guardians in the approval bits. In case it is not, the approval for the hash remains and is not deleted. + +```solidity +File: GuardianProver.sol +50: if (approved_) { +51: deleteApproval(hash); +52: ITaikoL1(resolve("taiko", false)).proveBlock(_meta.id, abi.encode(_meta, _tran, _proof)); +53: } +``` + +## [N-13] Consider making the TIMELOCK_ADMIN_ROLE undergo a delay when transferring the admin role + +The admin is allowed to skip the delay in operations. But the delay should not be skipped when the role is being transferred. + +```solidity +File: TaikoTimelockController.sol +25: function getMinDelay() public view override returns (uint256) { +26: return hasRole(TIMELOCK_ADMIN_ROLE, msg.sender) ? 0 : super.getMinDelay(); +27: } +``` + +**[dantaik (Taiko) confirmed commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/335#issuecomment-2036565025):** + +> Many of the above are fixed in https://github.com/taikoxyz/taiko-mono/pull/16627/files: + +--- + +# Gas Optimizations + +For this audit, 28 reports were submitted by wardens detailing gas optimizations. The [report highlighted below](https://github.com/code-423n4/2024-03-taiko-findings/issues/344) by **DadeKuma** received the top score from the judge. + +_The following wardens also submitted reports: [0x11singh99](https://github.com/code-423n4/2024-03-taiko-findings/issues/375), [dharma09](https://github.com/code-423n4/2024-03-taiko-findings/issues/354), [zabihullahazadzoi](https://github.com/code-423n4/2024-03-taiko-findings/issues/353), [0xAnah](https://github.com/code-423n4/2024-03-taiko-findings/issues/348), [slvDev](https://github.com/code-423n4/2024-03-taiko-findings/issues/325), [hunter_w3b](https://github.com/code-423n4/2024-03-taiko-findings/issues/292), [pfapostol](https://github.com/code-423n4/2024-03-taiko-findings/issues/196), [MrPotatoMagic](https://github.com/code-423n4/2024-03-taiko-findings/issues/189), [hihen](https://github.com/code-423n4/2024-03-taiko-findings/issues/174), [albahaca](https://github.com/code-423n4/2024-03-taiko-findings/issues/134), [Sathish9098](https://github.com/code-423n4/2024-03-taiko-findings/issues/117), [IllIllI](https://github.com/code-423n4/2024-03-taiko-findings/issues/74), [Auditor2947](https://github.com/code-423n4/2024-03-taiko-findings/issues/378), [rjs](https://github.com/code-423n4/2024-03-taiko-findings/issues/371), [SAQ](https://github.com/code-423n4/2024-03-taiko-findings/issues/367), [SY_S](https://github.com/code-423n4/2024-03-taiko-findings/issues/362), [SM3_SS](https://github.com/code-423n4/2024-03-taiko-findings/issues/360), [cheatc0d3](https://github.com/code-423n4/2024-03-taiko-findings/issues/341), [clara](https://github.com/code-423n4/2024-03-taiko-findings/issues/339), [pavankv](https://github.com/code-423n4/2024-03-taiko-findings/issues/333), [unique](https://github.com/code-423n4/2024-03-taiko-findings/issues/331), [sxima](https://github.com/code-423n4/2024-03-taiko-findings/issues/234), [0xhacksmithh](https://github.com/code-423n4/2024-03-taiko-findings/issues/194), [K42](https://github.com/code-423n4/2024-03-taiko-findings/issues/193), [Pechenite](https://github.com/code-423n4/2024-03-taiko-findings/issues/159), [oualidpro](https://github.com/code-423n4/2024-03-taiko-findings/issues/19), and [caglankaan](https://github.com/code-423n4/2024-03-taiko-findings/issues/7)._ + +### Gas Optimizations + +| Id | Title | Instances | Gas Saved | +| :----------------------------------------------------------------------------------------------------------: | :----------------------------------------------------------------------------------------------- | :-------: | --------: | +| [[G-01]](#g-01-use-arrayunsafeaccess-to-avoid-repeated-array-length-checks) | Use `Array.unsafeAccess` to avoid repeated array length checks | 80 | 168,000 | +| [[G-02]](#g-02-state-variables-can-be-packed-into-fewer-storage-slots) | State variables can be packed into fewer storage slots | 2 | 40,000 | +| [[G-03]](#g-03-structs-can-be-packed-into-fewer-storage-slots) | Structs can be packed into fewer storage slots | 3 | 60,000 | +| [[G-04]](#g-04-multiple-mappings-that-share-an-id-can-be-combined-into-a-single-mapping-of-id--struct) | Multiple `mapping`s that share an ID can be combined into a single `mapping` of ID / `struct` | 1 | 20,084 | +| [[G-05]](#g-05-use-of-memory-instead-of-storage-for-structarray-state-variables) | Use of `memory` instead of `storage` for struct/array state variables | 2 | 12,600 | +| [[G-06]](#g-06-state-variables-access-within-a-loop) | State variables access within a loop | 4 | 1,060 | +| [[G-07]](#g-07-unused-non-constant-state-variables-waste-gas) | Unused non-constant state variables waste gas | 2 | - | +| [[G-08]](#g-08-state-variables-only-set-in-the-constructor-should-be-declared-immutable) | State variables only set in the constructor should be declared `immutable` | 2 | 40,000 | +| [[G-09]](#g-09-cache-state-variables-with-stack-variables) | Cache state variables with stack variables | 17 | 4,400 | +| [[G-10]](#g-10-modifiers-order-should-be-changed) | Modifiers order should be changed | 5 | - | +| [[G-11]](#g-11-low-level-call-can-be-optimized-with-assembly) | Low level `call` can be optimized with assembly | 1 | 248 | +| [[G-12]](#g-12-use-of-memory-instead-of-calldata-for-immutable-arguments) | Use of `memory` instead of `calldata` for immutable arguments | 116 | 41,658 | +| [[G-13]](#g-13-avoid-updating-storage-when-the-value-hasnt-changed) | Avoid updating storage when the value hasn't changed | 12 | 8,400 | +| [[G-14]](#g-14-use-of-emit-inside-a-loop) | Use of `emit` inside a loop | 4 | 4,104 | +| [[G-15]](#g-15-use-uint2561uint2562-instead-of-truefalse-to-save-gas-for-changes) | Use `uint256(1)/uint256(2)` instead of `true/false` to save gas for changes | 10 | 170,000 | +| [[G-16]](#g-16-shortcircuit-rules-can-be-be-used-to-optimize-some-gas-usage) | Shortcircuit rules can be be used to optimize some gas usage | 1 | 2,100 | +| [[G-17]](#g-17-cache-multiple-accesses-of-a-mappingarray) | Cache multiple accesses of a mapping/array | 13 | 672 | +| [[G-18]](#g-18-redundant-state-variable-getters) | Redundant state variable getters | 2 | - | +| [[G-19]](#g-19-using-private-for-constants-saves-gas) | Using `private` for constants saves gas | 14 | 117,684 | +| [[G-20]](#g-20-require-or-revert-statements-that-check-input-arguments-should-be-at-the-top-of-the-function) | require() or revert() statements that check input arguments should be at the top of the function | 4 | - | +| [[G-21]](#g-21-consider-activating-via-ir-for-deploying) | Consider activating `via-ir` for deploying | - | - | +| [[G-22]](#g-22-function-calls-should-be-cached-instead-of-re-calling-the-function) | Function calls should be cached instead of re-calling the function | 12 | - | +| [[G-23]](#g-23-functions-that-revert-when-called-by-normal-users-can-be-payable) | Functions that revert when called by normal users can be `payable` | 37 | 777 | +| [[G-24]](#g-24-caching-global-variables-is-more-expensive-than-using-the-actual-variable) | Caching global variables is more expensive than using the actual variable | 1 | 12 | +| [[G-25]](#g-25-add-unchecked-blocks-for-subtractions-where-the-operands-cannot-underflow) | Add `unchecked` blocks for subtractions where the operands cannot underflow | 7 | 595 | +| [[G-26]](#g-26-add-unchecked-blocks-for-divisions-where-the-operands-cannot-overflow) | Add `unchecked` blocks for divisions where the operands cannot overflow | 13 | 2,067 | +| [[G-27]](#g-27-empty-blocks-should-be-removed-or-emit-something) | Empty blocks should be removed or emit something | 1 | 4,006 | +| [[G-28]](#g-28-usage-of-uintsints-smaller-than-32-bytes-256-bits-incurs-overhead) | Usage of `uints`/`ints` smaller than 32 bytes (256 bits) incurs overhead | 322 | 1,932 | +| [[G-29]](#g-29-stack-variable-cost-less-while-used-in-emitting-event) | Stack variable cost less while used in emitting event | 7 | 63 | +| [[G-30]](#g-30-redundant-event-fields-can-be-removed) | Redundant `event` fields can be removed | 1 | 358 | +| [[G-31]](#g-31-using-pre-instead-of-post-incrementsdecrements) | Using pre instead of post increments/decrements | 7 | 5 | +| [[G-32]](#g-32--costs-less-gas-than) | `>=`/`<=` costs less gas than `>`/`<` | 130 | 390 | +| [[G-33]](#g-33-internal-functions-only-called-once-can-be-inlined-to-save-gas) | `internal` functions only called once can be inlined to save gas | 20 | 400 | +| [[G-34]](#g-34-inline-modifiers-that-are-only-used-once-to-save-gas) | Inline `modifiers` that are only used once, to save gas | 5 | - | +| [[G-35]](#g-35-private-functions-only-called-once-can-be-inlined-to-save-gas) | `private` functions only called once can be inlined to save gas | 41 | 820 | +| [[G-36]](#g-36-use-multiple-revert-checks-to-save-gas) | Use multiple revert checks to save gas | 37 | 74 | +| [[G-37]](#g-37-abiencode-is-less-efficient-than-abiencodepacked-for-non-address-arguments) | `abi.encode()` is less efficient than `abi.encodepacked()` for non-address arguments | 16 | 80 | +| [[G-38]](#g-38-unused-named-return-variables-without-optimizer-waste-gas) | Unused named return variables without optimizer waste gas | 20 | 54 | +| [[G-39]](#g-39-consider-pre-calculating-the-address-of-addressthis-to-save-gas) | Consider pre-calculating the address of `address(this)` to save gas | 40 | - | +| [[G-40]](#g-40-consider-using-soladys-fixedpointmathlib) | Consider using Solady's `FixedPointMathLib` | 4 | - | +| [[G-41]](#g-41-reduce-deployment-costs-by-tweaking-contracts-metadata) | Reduce deployment costs by tweaking contracts' metadata | 86 | - | +| [[G-42]](#g-42-emitting-constants-wastes-gas) | Emitting constants wastes gas | 4 | 32 | +| [[G-43]](#g-43-update-openzeppelin-dependency-to-save-gas) | Update OpenZeppelin dependency to save gas | 54 | - | +| [[G-44]](#g-44-function-names-can-be-optimized) | Function names can be optimized | 56 | 1,232 | +| [[G-45]](#g-45-avoid-zero-transfers-calls) | Avoid zero transfers calls | 10 | - | +| [[G-46]](#g-46-using-delete-instead-of-setting-mappingstruct-to-0-saves-gas) | Using `delete` instead of setting mapping/struct to 0 saves gas | 10 | 50 | +| [[G-47]](#g-47-using-bool-for-storage-incurs-overhead) | Using `bool` for storage incurs overhead | 10 | 1,000 | +| [[G-48]](#g-48-mappings-are-cheaper-to-use-than-storage-arrays) | Mappings are cheaper to use than storage arrays | 36 | 75,600 | +| [[G-49]](#g-49-bytes-constants-are-more-efficient-than-string-constants) | Bytes constants are more efficient than string constants | 5 | 1,890 | +| [[G-50]](#g-50-constructors-can-be-marked-payable) | Constructors can be marked `payable` | 3 | 63 | +| [[G-51]](#g-51-inverting-the-if-condition-wastes-gas) | Inverting the `if` condition wastes gas | 2 | 6 | +| [[G-52]](#g-52-long-revert-strings) | Long revert strings | 27 | 720 | +| [[G-53]](#g-53-nesting-if-statements-that-use--saves-gas) | Nesting `if` statements that use `&&` saves gas | 23 | 690 | +| [[G-54]](#g-54-counting-down-when-iterating-saves-gas) | Counting down when iterating, saves gas | 45 | 270 | +| [[G-55]](#g-55-do-while-is-cheaper-than-for-loops-when-the-initial-check-can-be-skipped) | `do-while` is cheaper than `for`-loops when the initial check can be skipped | 49 | - | +| [[G-56]](#g-56-lack-of-unchecked-in-loops) | Lack of `unchecked` in loops | 39 | 2,340 | +| [[G-57]](#g-57-uint-comparison-with-zero-can-be-cheaper) | `uint` comparison with zero can be cheaper | 15 | 60 | +| [[G-58]](#g-58-use-assembly-to-check-for-address0) | Use assembly to check for `address(0)` | 74 | 444 | +| [[G-59]](#g-59-use-scratch-space-for-building-calldata-with-assembly) | Use scratch space for building calldata with assembly | 333 | 73,260 | +| [[G-60]](#g-60-use-assembly-to-write-hashes) | Use assembly to write hashes | 25 | 3,000 | +| [[G-61]](#g-61-use-assembly-to-validate-msgsender) | Use assembly to validate `msg.sender` | 17 | 204 | +| [[G-62]](#g-62-use-assembly-to-write-address-storage-values) | Use assembly to write `address` storage values | 18 | 1,332 | +| [[G-63]](#g-63-use-assembly-to-emit-an-event) | Use assembly to emit an `event` | 55 | 2,090 | + +Total: 2012 instances over 63 issues with an estimate of **866,926 gas** saved. + +--- + +## Gas Optimizations + +--- + +### [G-01] Use `Array.unsafeAccess` to avoid repeated array length checks + +When using storage arrays, solidity adds an internal lookup of the array's length (a **Gcoldsload 2100 gas**) to ensure it doesn't read past the array's end. + +It's possible to avoid this lookup by using `Array.unsafeAccess` in cases where the length has already been checked. + +_There are 80 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +81: if (_serialNumIsRevoked[index][serialNumBatch[i]]) { + +84: _serialNumIsRevoked[index][serialNumBatch[i]] = true; + +96: if (!_serialNumIsRevoked[index][serialNumBatch[i]]) { + +99: delete _serialNumIsRevoked[index][serialNumBatch[i]]; + +192: EnclaveIdStruct.TcbLevel memory tcb = enclaveId.tcbLevels[i]; + +215: TCBInfoStruct.TCBLevelObj memory current = tcb.tcbLevels[i]; + +241: if (pckCpuSvns[i] < tcbCpuSvns[i]) { + +263: issuer = certs[i]; + +265: issuer = certs[i + 1]; + +268: certRevoked = _serialNumIsRevoked[uint256(IPEMCertChainLib.CRL.ROOT)][certs[i] +269: .serialNumber]; + +270: } else if (certs[i].isPck) { + +271: certRevoked = _serialNumIsRevoked[uint256(IPEMCertChainLib.CRL.PCK)][certs[i] +272: .serialNumber]; + +280: block.timestamp > certs[i].notBefore && block.timestamp < certs[i].notAfter; + +286: certs[i].tbsCertificate, certs[i].signature, issuer.pubKey + +424: (certDecodedSuccessfully, parsedQuoteCerts[i]) = pemCertLib.decodeCert( + +425: authDataV3.certification.decodedCertDataArray[i], isPckCert +``` + +[[81](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L81), [84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L84), [96](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L96), [99](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L99), [192](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L192), [215](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L215), [241](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L241), [263](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L263), [265](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L265), [268-269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L268-L269), [270](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L270), [271-272](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L271-L272), [280](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L280), [286](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L286), [424](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L424), [425](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L425)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +91: bytes32 msgHash = _msgHashes[i]; + +92: proofReceipt[msgHash].receivedAt = _timestamp; +``` + +[[91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L91), [92](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L92)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +236: inputs[j % 255] = blockhash(j); +``` + +[[236](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L236)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +105: hop = hopProofs[i]; +``` + +[[105](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L105)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +48: if (_op.amounts[i] == 0) revert VAULT_INVALID_AMOUNT(); + +252: BridgedERC1155(_op.token).burn(_user, _op.tokenIds[i], _op.amounts[i]); + +273: id: _op.tokenIds[i], + +274: amount: _op.amounts[i], +``` + +[[48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L48), [252](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L252), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L273), [274](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L274)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +35: if (_op.amounts[i] != 0) revert VAULT_INVALID_AMOUNT(); + +171: IERC721(token_).safeTransferFrom(address(this), _to, _tokenIds[i]); + +176: BridgedERC721(token_).mint(_to, _tokenIds[i]); + +198: BridgedERC721(_op.token).burn(_user, _op.tokenIds[i]); + +211: t.safeTransferFrom(_user, address(this), _op.tokenIds[i]); +``` + +[[35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L35), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L171), [176](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L176), [198](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L198), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L211)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +105: uint256 idx = _ids[i]; + +107: if (instances[idx].addr == address(0)) revert SGX_INVALID_INSTANCE(); + +109: emit InstanceDeleted(idx, instances[idx].addr); + +111: delete instances[idx]; + +211: if (addressRegistered[_instances[i]]) revert SGX_ALREADY_ATTESTED(); + +213: addressRegistered[_instances[i]] = true; + +215: if (_instances[i] == address(0)) revert SGX_INVALID_INSTANCE(); + +217: instances[nextInstanceId] = Instance(_instances[i], validSince); + +218: ids[i] = nextInstanceId; + +220: emit InstanceAdded(nextInstanceId, _instances[i], address(0), validSince); +``` + +[[105](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L105), [107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L107), [109](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L109), [111](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L111), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L211), [213](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L213), [215](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L215), [217](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L217), [218](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L218), [220](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L220)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +62: (success, certs[i], increment) = _removeHeadersAndFooters(input); + +245: contentStr = LibString.concat(contentStr, split[i]); + +367: cpusvns[i] = cpusvn; +``` + +[[62](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L62), [245](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L245), [367](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L367)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +334: bytes1 char = self[off + i]; + +336: decoded = uint8(BASE32_HEX_TABLE[uint256(uint8(char)) - 0x30]); +``` + +[[334](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L334), [336](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L336)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +141: if (decipher[i] != 0xff) { + +153: if (decipher[3 + paddingLen + i] != bytes1(sha256ExplicitNullParam[i])) { + +159: if (decipher[3 + paddingLen + i] != bytes1(sha256ImplicitNullParam[i])) { + +175: if (decipher[5 + paddingLen + digestAlgoWithParamLen + i] != _sha256[i]) { + +274: if (decipher[i] != 0xff) { + +284: if (decipher[3 + paddingLen + i] != bytes1(sha1Prefix[i])) { + +291: if (decipher[3 + paddingLen + sha1Prefix.length + i] != _sha1[i]) { +``` + +[[141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L141), [153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L153), [159](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L159), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L175), [274](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L274), [284](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L284), [291](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L291)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +60: timestamp += uint256(monthDays[i - 1]) * 86_400; // Days in seconds +``` + +[[60](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L60)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +173: if (_tierFees[i].tier == _tierId) return _tierFees[i].fee; +``` + +[[173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L173)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +87: uint256 data = _state.ethDeposits[j % _config.ethDepositRingBufferSize]; + +88: deposits_[i] = TaikoData.EthDeposit({ + +93: uint96 _fee = deposits_[i].amount > fee ? fee : deposits_[i].amount; + +101: deposits_[i].amount -= _fee; +``` + +[[87](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L87), [88](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L88), [93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L93), [101](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L101)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +245: if (uint160(prevHook) >= uint160(params.hookCalls[i].hook)) { + +253: IHook(params.hookCalls[i].hook).onBlockProposed{ value: address(this).balance }( + +254: blk, meta_, params.hookCalls[i].data + +257: prevHook = params.hookCalls[i].hook; +``` + +[[245](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L245), [253](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L253), [254](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L254), [257](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L257)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +75: delete guardianIds[guardians[i]]; + +81: address guardian = _newGuardians[i]; + +84: if (guardianIds[guardian] != 0) revert INVALID_GUARDIAN_SET(); + +88: guardianIds[guardian] = guardians.length; +``` + +[[75](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L75), [81](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L81), [84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L84), [88](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L88)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +60: IERC721(token).safeTransferFrom(vault, user, tokenIds[i]); +``` + +[[60](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L60)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +154: uint256 digits = uint256(uint8(bytes1(encoded[i]))); + +282: quoteCerts[i] = Base64.decode(string(quoteCerts[i])); +``` + +[[154](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L154), [282](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L282)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +47: out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256)); + +60: if (b[i] != 0) { + +67: out_[j] = b[i++]; +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L47), [60](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L60), [67](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L67)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +86: TrieNode memory currentNode = proof[i]; + +118: value_ = RLPReader.readBytes(currentNode.decoded[TREE_RADIX]); + +134: uint8 branchKey = uint8(key[currentKeyIndex]); + +135: RLPReader.RLPItem memory nextNode = currentNode.decoded[branchKey]; + +141: uint8 prefix = uint8(path[0]); + +171: value_ = RLPReader.readBytes(currentNode.decoded[1]); + +188: currentNodeID = _getNodeID(currentNode.decoded[1]); + +209: proof_[i] = TrieNode({ encoded: _proof[i], decoded: RLPReader.readList(_proof[i]) }); + +244: for (; shared_ < max && _a[shared_] == _b[shared_];) { +``` + +[[86](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L86), [118](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L118), [134](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L134), [135](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L135), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L141), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L171), [188](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L188), [209](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L209), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L244)] + +
+ +--- + +### [G-02] State variables can be packed into fewer storage slots + +Each slot saved can avoid an extra Gsset (**20000 gas**). Reads and writes (if two variables that occupy the same slot are written by the same function) will have a cheaper gas consumption. + +_There are 2 instances of this issue._ + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +// @audit Can save 1 storage slot (from 7 to 6) +// @audit Consider using the following order: +/* + * mapping(bytes32 => bool) _trustedUserMrEnclave (32) + * mapping(bytes32 => bool) _trustedUserMrSigner (32) + * mapping(uint256 => mapping(bytes => bool)) _serialNumIsRevoked (32) + * mapping(string => TCBInfoStruct.TCBInfo) tcbInfo (32) + * EnclaveIdStruct.EnclaveId qeIdentity (20) + * bool _checkLocalEnclaveReport (1) + * address owner (20) +*/ +22: contract AutomataDcapV3Attestation is IAttestation { +``` + +[[22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L22)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +// @audit Can save 1 storage slot (from 6 to 5) +// @audit Consider using the following order: +/* + * mapping(address => uint256) claimedAmount (32) + * mapping(address => uint256) withdrawnAmount (32) + * uint256[] __gap (32) + * address token (20) + * uint64 withdrawalWindow (8) + * address vault (20) +*/ +12: contract ERC20Airdrop2 is MerkleClaimable { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L12)] + +--- + +### [G-03] Structs can be packed into fewer storage slots + +Each slot saved can avoid an extra Gsset (**20000 gas**) for the first setting of the struct. Subsequent reads as well as writes have smaller gas savings. + +_There are 3 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/L1/TaikoData.sol + +// @audit Can save 1 storage slot (from 8 to 7) +// @audit Consider using the following order: +/* + * uint256 ethDepositRingBufferSize (32) + * uint256 ethDepositGas (32) + * uint256 ethDepositMaxFee (32) + * uint96 livenessBond (12) + * uint96 ethDepositMinAmount (12) + * uint64 chainId (8) + * uint96 ethDepositMaxAmount (12) + * uint64 blockMaxProposals (8) + * uint64 blockRingBufferSize (8) + * uint32 blockMaxGasLimit (4) + * uint64 maxBlocksToVerifyPerProposal (8) + * uint64 ethDepositMinCountPerBlock (8) + * uint64 ethDepositMaxCountPerBlock (8) + * uint24 blockMaxTxListBytes (3) + * uint24 blobExpiry (3) + * bool blobAllowedForDA (1) + * bool blobReuseEnabled (1) + * uint8 blockSyncThreshold (1) +*/ +10: struct Config { +11: // --------------------------------------------------------------------- +12: // Group 1: General configs +13: // --------------------------------------------------------------------- +14: // The chain ID of the network where Taiko contracts are deployed. +15: uint64 chainId; +16: // --------------------------------------------------------------------- +17: // Group 2: Block level configs +18: // --------------------------------------------------------------------- +19: // The maximum number of proposals allowed in a single block. +20: uint64 blockMaxProposals; +21: // Size of the block ring buffer, allowing extra space for proposals. +22: uint64 blockRingBufferSize; +23: // The maximum number of verifications allowed when a block is proposed. +24: uint64 maxBlocksToVerifyPerProposal; +25: // The maximum gas limit allowed for a block. +26: uint32 blockMaxGasLimit; +27: // The maximum allowed bytes for the proposed transaction list calldata. +28: uint24 blockMaxTxListBytes; +29: // The max period in seconds that a blob can be reused for DA. +30: uint24 blobExpiry; +31: // True if EIP-4844 is enabled for DA +32: bool blobAllowedForDA; +33: // True if blob can be reused +34: bool blobReuseEnabled; +35: // --------------------------------------------------------------------- +36: // Group 3: Proof related configs +37: // --------------------------------------------------------------------- +38: // The amount of Taiko token as a prover liveness bond +39: uint96 livenessBond; +40: // --------------------------------------------------------------------- +41: // Group 4: ETH deposit related configs +42: // --------------------------------------------------------------------- +43: // The size of the ETH deposit ring buffer. +44: uint256 ethDepositRingBufferSize; +45: // The minimum number of ETH deposits allowed per block. +46: uint64 ethDepositMinCountPerBlock; +47: // The maximum number of ETH deposits allowed per block. +48: uint64 ethDepositMaxCountPerBlock; +49: // The minimum amount of ETH required for a deposit. +50: uint96 ethDepositMinAmount; +51: // The maximum amount of ETH allowed for a deposit. +52: uint96 ethDepositMaxAmount; +53: // The gas cost for processing an ETH deposit. +54: uint256 ethDepositGas; +55: // The maximum fee allowed for an ETH deposit. +56: uint256 ethDepositMaxFee; +57: // The max number of L2 blocks that can stay unsynced on L1 (a value of zero disables +58: // syncing) +59: uint8 blockSyncThreshold; +60: } + +// @audit Can save 1 storage slot (from 7 to 6) +// @audit Consider using the following order: +/* + * bytes32 extraData (32) + * bytes32 blobHash (32) + * bytes32 parentMetaHash (32) + * HookCall[] hookCalls (32) + * address assignedProver (20) + * uint24 txListByteOffset (3) + * uint24 txListByteSize (3) + * bool cacheBlobForReuse (1) + * address coinbase (20) +*/ +78: struct BlockParams { +79: address assignedProver; +80: address coinbase; +81: bytes32 extraData; +82: bytes32 blobHash; +83: uint24 txListByteOffset; +84: uint24 txListByteSize; +85: bool cacheBlobForReuse; +86: bytes32 parentMetaHash; +87: HookCall[] hookCalls; +88: } +``` + +[[10-60](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L10-L60), [78-88](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L78-L88)] + +```solidity +File: packages/protocol/contracts/signal/ISignalService.sol + +// @audit Can save 1 storage slot (from 5 to 4) +// @audit Consider using the following order: +/* + * bytes32 rootHash (32) + * bytes[] accountProof (32) + * bytes[] storageProof (32) + * uint64 chainId (8) + * uint64 blockId (8) + * CacheOption cacheOption (1) +*/ +20: struct HopProof { +21: uint64 chainId; +22: uint64 blockId; +23: bytes32 rootHash; +24: CacheOption cacheOption; +25: bytes[] accountProof; +26: bytes[] storageProof; +27: } +``` + +[[20-27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L20-L27)] + +
+ +--- + +### [G-04] Multiple `mapping`s that share an ID can be combined into a single `mapping` of ID / `struct` + +This can avoid a Gsset (**20000 Gas**) per mapping combined. Reads and writes will also be cheaper when a function requires both values as they both can fit in the same storage slot. + +Finally, if both fields are accessed in the same function, this can save **~42 gas** per access due to not having to recalculate the key's `keccak256` hash (Gkeccak256 - **30 Gas**) and that calculation's associated stack operations. + +_There is 1 instance of this issue._ + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +// @audit consider merging _trustedUserMrEnclave, _trustedUserMrSigner +39: mapping(bytes32 enclave => bool trusted) private _trustedUserMrEnclave; +40: mapping(bytes32 signer => bool trusted) private _trustedUserMrSigner; +``` + +[[39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L39)] + +--- + +### [G-05] Use of `memory` instead of `storage` for struct/array state variables + +When fetching data from `storage`, using the `memory` keyword to assign it to a variable reads all fields of the struct/array and incurs a Gcoldsload (**2100 gas**) for each field. + +This can be avoided by declaring the variable with the `storage` keyword and caching the necessary fields in stack variables. + +The `memory` keyword should only be used if the entire struct/array is being returned or passed to a function that requires `memory`, or if it is being read from another `memory` array/struct. + +_There are 2 instances of this issue._ + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +180: EnclaveIdStruct.EnclaveId memory enclaveId = qeIdentity; +``` + +[[180](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L180)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +171: CanonicalERC20 memory ctoken = bridgedToCanonical[btokenOld_]; +``` + +[[171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L171)] + +--- + +### [G-06] State variables access within a loop + +State variable reads and writes are more expensive than local variable reads and writes. Therefore, it is recommended to replace state variable reads and writes within loops with a local variable. Gas savings should be multiplied by the average loop length. + +_There are 4 instances of this issue._ + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +// @audit nextInstanceId +218: ids[i] = nextInstanceId; +``` + +[[218](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L218)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +// @audit guardians +87: guardians.push(guardian); + +// @audit guardians +88: guardianIds[guardian] = guardians.length; + +// @audit minGuardians +135: if (count == minGuardians) return true; +``` + +[[87](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L87), [88](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L88), [135](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L135)] + +--- + +### [G-07] Unused non-constant state variables waste gas + +If the variable is assigned a non-zero value, saves Gsset (20000 gas). If it's assigned a zero value, saves Gsreset (2900 gas). + +If the variable remains unassigned, there is no gas savings unless the variable is public, in which case the compiler-generated non-payable getter deployment cost is saved. + +If the state variable is overriding an interface's public function, mark the variable as constant or immutable so that it does not use a storage slot. + +_There are 2 instances of this issue._ + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +56: mapping(address btoken => CanonicalNFT canonical) public bridgedToCanonical; + +59: mapping(uint256 chainId => mapping(address ctoken => address btoken)) public canonicalToBridged; +``` + +[[56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L56), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L59)] + +--- + +### [G-08] State variables only set in the constructor should be declared `immutable` + +Accessing state variables within a function involves an SLOAD operation, but `immutable` variables can be accessed directly without the need of it, thus reducing gas costs. As these state variables are assigned only in the constructor, consider declaring them `immutable`. + +_There are 2 instances of this issue._ + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +52: address public owner; +``` + +[[52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L52)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +18: address private ES256VERIFIER; +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L18)] + +--- + +### [G-09] Cache state variables with stack variables + +Caching of a state variable replaces each Gwarmaccess (**100 gas**) with a cheaper stack read. Other less obvious fixes/optimizations include having local memory caches of state variable structs, or having local caches of state variable contracts/addresses. + +_There are 17 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +// @audit addressManager on line 83 +81: if (addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); +``` + +[[81](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L81)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +// @audit state on lines 67, 70 +69: if (!state.slotB.provingPaused) { + +// @audit state on line 94 +96: LibVerifying.verifyBlocks(state, config, this, maxBlocksToVerify); + +// @audit state on line 151 +154: ts_ = state.transitions[slot][blk_.verifiedTransitionId]; + +// @audit state on line 181 +182: b_ = state.slotB; +``` + +[[69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L69), [96](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L96), [154](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L154), [182](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L182)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +// @audit nextTxId on line 53 +43: if (txId != nextTxId) revert XCO_INVALID_TX_ID(); +``` + +[[43](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L43)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +// @audit gasExcess on line 265 +262: if (gasExcess > 0) { + +// @audit lastSyncedBlock on line 275 +276: numL1Blocks = _l1BlockId - lastSyncedBlock; +``` + +[[262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L262), [276](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L276)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +// @audit sharedVault on line 219 +220: IERC20(costToken).safeTransferFrom(_recipient, sharedVault, costToWithdraw); +``` + +[[220](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L220)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +// @audit migratingAddress on line 63 +61: if (msg.sender == migratingAddress) { + +// @audit migratingAddress on line 80 +80: emit MigratedTo(migratingAddress, _account, _amount); +``` + +[[61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L61), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L80)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +// @audit nextInstanceId on lines 218, 220, 222 +217: instances[nextInstanceId] = Instance(_instances[i], validSince); +``` + +[[217](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L217)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +// @audit version on line 95 +92: ++version; + +// @audit guardians on lines 74, 87, 88 +77: delete guardians; + +// @audit version on line 116 +119: uint256 _approval = _approvals[version][_hash]; +``` + +[[92](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L92), [77](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L77), [119](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L119)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +// @audit token on line 63 +71: IVotes(token).delegateBySig(delegatee, nonce, expiry, v, r, s); +``` + +[[71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L71)] + +```solidity +File: packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol + +// @audit usdc on line 48 +49: usdc.burn(_amount); +``` + +[[49](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L49)] + +
+ +--- + +### [G-10] Modifiers order should be changed + +According to solidity docs, modifiers are executed in the order they are presented, so the order can be improved to avoid unnecessary `SLOAD`s and/or external calls by prioritizing cheaper modifiers first. + +_There are 5 instances of this issue._ + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +155: function recallMessage( +156: Message calldata _message, +157: bytes calldata _proof +158: ) +159: external +160: nonReentrant +161: whenNotPaused +162: sameChain(_message.srcChainId) + +217: function processMessage( +218: Message calldata _message, +219: bytes calldata _proof +220: ) +221: external +222: nonReentrant +223: whenNotPaused +224: sameChain(_message.destChainId) + +310: function retryMessage( +311: Message calldata _message, +312: bool _isLastAttempt +313: ) +314: external +315: nonReentrant +316: whenNotPaused +317: sameChain(_message.destChainId) +``` + +[[155-162](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L155-L162), [217-224](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L217-L224), [310-317](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L310-L317)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +75: function proveBlock( +76: uint64 _blockId, +77: bytes calldata _input +78: ) +79: external +80: nonReentrant +81: whenNotPaused +82: whenProvingNotPaused + +100: function verifyBlocks(uint64 _maxBlocksToVerify) +101: external +102: nonReentrant +103: whenNotPaused +104: whenProvingNotPaused +``` + +[[75-82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L75-L82), [100-104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L100-L104)] + +--- + +### [G-11] Low level `call` can be optimized with assembly + +`returnData` is copied to memory even if the variable is not utilized: the proper way to handle this is through a low level assembly call. + +```solidity +// before +(bool success,) = payable(receiver).call{gas: gas, value: value}(""); + +//after +bool success; +assembly { + success := call(gas, receiver, value, 0, 0, 0, 0) +} +``` + +_There is 1 instance of this issue._ + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +50: (bool success,) = address(this).call(txdata); +``` + +[[50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L50)] + +--- + +### [G-12] Use of `memory` instead of `calldata` for immutable arguments + +Consider refactoring the function arguments from `memory` to `calldata` when they are immutable, as `calldata` is cheaper. + +_There are 116 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +// @audit quoteEnclaveReport +175: function _verifyQEReportWithIdentity(V3Struct.EnclaveReport memory quoteEnclaveReport) + +// @audit pck, tcb +206: function _checkTcbLevels( +207: IPEMCertChainLib.PCKCertificateField memory pck, +208: TCBInfoStruct.TCBInfo memory tcb + +// @audit pckCpuSvns, tcbCpuSvns +229: function _isCpuSvnHigherOrGreater( +230: uint256[] memory pckCpuSvns, +231: uint8[] memory tcbCpuSvns + +// @audit certs +248: function _verifyCertChain(IPEMCertChainLib.ECSha256Certificate[] memory certs) + +// @audit pckCertPubKey, signedQuoteData, authDataV3, qeEnclaveReport +303: function _enclaveReportSigVerification( +304: bytes memory pckCertPubKey, +305: bytes memory signedQuoteData, +306: V3Struct.ECDSAQuoteV3AuthData memory authDataV3, +307: V3Struct.EnclaveReport memory qeEnclaveReport +``` + +[[175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L175), [206-208](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L206-L208), [229-231](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L229-L231), [248](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L248), [303-307](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L303-L307)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +// @audit _config +252: function _calc1559BaseFee( +253: Config memory _config, +254: uint64 _l1BlockId, +255: uint32 _parentGasUsed +``` + +[[252-255](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L252-L255)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +// @audit _sig +61: function isValidSignature( +62: address _addr, +63: bytes32 _hash, +64: bytes memory _sig +``` + +[[61-64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L61-L64)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +// @audit _hop +206: function _verifyHopProof( +207: uint64 _chainId, +208: address _app, +209: bytes32 _signal, +210: bytes32 _value, +211: HopProof memory _hop, +212: address _signalService + +// @audit _hop +271: function _cacheChainData( +272: HopProof memory _hop, +273: uint64 _chainId, +274: uint64 _blockId, +275: bytes32 _signalRoot, +276: bool _isFullProof, +277: bool _isLastHop +``` + +[[206-212](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L206-L212), [271-277](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L271-L277)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +// @audit _sig +168: function withdraw(address _to, bytes memory _sig) external { + +// @audit _grant +235: function _getAmountOwned(Grant memory _grant) private view returns (uint128) { + +// @audit _grant +267: function _validateGrant(Grant memory _grant) private pure { +``` + +[[168](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L168), [235](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L235), [267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L267)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +// @audit _symbol, _name +38: function init( +39: address _owner, +40: address _addressManager, +41: address _srcToken, +42: uint256 _srcChainId, +43: string memory _symbol, +44: string memory _name +``` + +[[38-44](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L38-L44)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +// @audit _symbol, _name +52: function init( +53: address _owner, +54: address _addressManager, +55: address _srcToken, +56: uint256 _srcChainId, +57: uint8 _decimals, +58: string memory _symbol, +59: string memory _name +``` + +[[52-59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L52-L59)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +// @audit _symbol, _name +31: function init( +32: address _owner, +33: address _addressManager, +34: address _srcToken, +35: uint256 _srcChainId, +36: string memory _symbol, +37: string memory _name +``` + +[[31-37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L31-L37)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +// @audit _op +240: function _handleMessage( +241: address _user, +242: BridgeTransferOp memory _op + +// @audit _ctoken +303: function _deployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) { +``` + +[[240-242](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L240-L242), [303](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L303)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +// @audit ctoken +407: function _deployBridgedToken(CanonicalERC20 memory ctoken) private returns (address btoken) { +``` + +[[407](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L407)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +// @audit _tokenIds +160: function _transferTokens( +161: CanonicalNFT memory _ctoken, +162: address _to, +163: uint256[] memory _tokenIds + +// @audit _op +187: function _handleMessage( +188: address _user, +189: BridgeTransferOp memory _op + +// @audit _ctoken +240: function _deployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) { +``` + +[[160-163](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L160-L163), [187-189](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L187-L189), [240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L240)] + +```solidity +File: packages/protocol/contracts/tokenvault/LibBridgedToken.sol + +// @audit _symbol, _name +11: function validateInputs( +12: address _srcToken, +13: uint256 _srcChainId, +14: string memory _symbol, +15: string memory _name + +// @audit _name +28: function buildName( +29: string memory _name, +30: uint256 _srcChainId + +// @audit _symbol +39: function buildSymbol(string memory _symbol) internal pure returns (string memory) { +``` + +[[11-15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L11-L15), [28-30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L28-L30), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L39)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +// @audit _instances +195: function _addInstances( +196: address[] memory _instances, +197: bool instantValid +``` + +[[195-197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L195-L197)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +// @audit pemChain +40: function splitCertificateChain( +41: bytes memory pemChain, +42: uint256 size + +// @audit der +74: function decodeCert( +75: bytes memory der, +76: bool isPckCert + +// @audit pemData +216: function _removeHeadersAndFooters(string memory pemData) + +// @audit input +252: function _trimBytes( +253: bytes memory input, +254: uint256 expectedLength + +// @audit der +269: function _findPckTcbInfo( +270: bytes memory der, +271: uint256 tbsPtr, +272: uint256 tbsParentPtr + +// @audit der +341: function _findTcb( +342: bytes memory der, +343: uint256 oidPtr +``` + +[[40-42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L40-L42), [74-76](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L74-L76), [216](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L216), [252-254](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L252-L254), [269-272](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L269-L272), [341-343](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L341-L343)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol + +// @audit der +47: function root(bytes memory der) internal pure returns (uint256) { + +// @audit der +56: function rootOfBitStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + +// @audit der +66: function rootOfOctetStringAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + +// @audit der +77: function nextSiblingOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { + +// @audit der +87: function firstChildOf(bytes memory der, uint256 ptr) internal pure returns (uint256) { + +// @audit der +111: function bytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + +// @audit der +121: function allBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + +// @audit der +131: function bytes32At(bytes memory der, uint256 ptr) internal pure returns (bytes32) { + +// @audit der +141: function uintAt(bytes memory der, uint256 ptr) internal pure returns (uint256) { + +// @audit der +154: function uintBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + +// @audit der +165: function keccakOfBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { + +// @audit der +169: function keccakOfAllBytesAt(bytes memory der, uint256 ptr) internal pure returns (bytes32) { + +// @audit der +179: function bitstringAt(bytes memory der, uint256 ptr) internal pure returns (bytes memory) { + +// @audit der +187: function _readNodeLength(bytes memory der, uint256 ix) private pure returns (uint256) { +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L47), [56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L56), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L66), [77](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L77), [87](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L87), [111](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L111), [121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L121), [131](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L131), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L141), [154](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L154), [165](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L165), [169](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L169), [179](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L179), [187](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L187)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +// @audit self +16: function keccak( +17: bytes memory self, +18: uint256 offset, +19: uint256 len + +// @audit self, other +39: function compare(bytes memory self, bytes memory other) internal pure returns (int256) { + +// @audit self, other +56: function compare( +57: bytes memory self, +58: uint256 offset, +59: uint256 len, +60: bytes memory other, +61: uint256 otheroffset, +62: uint256 otherlen + +// @audit self, other +116: function equals( +117: bytes memory self, +118: uint256 offset, +119: bytes memory other, +120: uint256 otherOffset, +121: uint256 len + +// @audit self, other +138: function equals( +139: bytes memory self, +140: uint256 offset, +141: bytes memory other, +142: uint256 otherOffset + +// @audit self, other +160: function equals( +161: bytes memory self, +162: uint256 offset, +163: bytes memory other + +// @audit self, other +178: function equals(bytes memory self, bytes memory other) internal pure returns (bool) { + +// @audit self +188: function readUint8(bytes memory self, uint256 idx) internal pure returns (uint8 ret) { + +// @audit self +198: function readUint16(bytes memory self, uint256 idx) internal pure returns (uint16 ret) { + +// @audit self +211: function readUint32(bytes memory self, uint256 idx) internal pure returns (uint32 ret) { + +// @audit self +224: function readBytes32(bytes memory self, uint256 idx) internal pure returns (bytes32 ret) { + +// @audit self +237: function readBytes20(bytes memory self, uint256 idx) internal pure returns (bytes20 ret) { + +// @audit self +255: function readBytesN( +256: bytes memory self, +257: uint256 idx, +258: uint256 len + +// @audit self +284: function substring( +285: bytes memory self, +286: uint256 offset, +287: uint256 len + +// @audit self +320: function base32HexDecodeWord( +321: bytes memory self, +322: uint256 off, +323: uint256 len + +// @audit a, b +371: function compareBytes(bytes memory a, bytes memory b) internal pure returns (bool) { +``` + +[[16-19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L16-L19), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L39), [56-62](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L56-L62), [116-121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L116-L121), [138-142](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L138-L142), [160-163](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L160-L163), [178](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L178), [188](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L188), [198](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L198), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L211), [224](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L224), [237](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L237), [255-258](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L255-L258), [284-287](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L284-L287), [320-323](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L320-L323), [371](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L371)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +// @audit _s, _e, _m +43: function pkcs1Sha256( +44: bytes32 _sha256, +45: bytes memory _s, +46: bytes memory _e, +47: bytes memory _m + +// @audit _data, _s, _e, _m +191: function pkcs1Sha256Raw( +192: bytes memory _data, +193: bytes memory _s, +194: bytes memory _e, +195: bytes memory _m + +// @audit _s, _e, _m +212: function pkcs1Sha1( +213: bytes20 _sha1, +214: bytes memory _s, +215: bytes memory _e, +216: bytes memory _m + +// @audit _data, _s, _e, _m +307: function pkcs1Sha1Raw( +308: bytes memory _data, +309: bytes memory _s, +310: bytes memory _e, +311: bytes memory _m +``` + +[[43-47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L43-L47), [191-195](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L191-L195), [212-216](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L212-L216), [307-311](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L307-L311)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SHA1.sol + +// @audit data +11: function sha1(bytes memory data) internal pure returns (bytes20 ret) { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SHA1.sol#L11)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +// @audit tbs, signature, publicKey +24: function verifyAttStmtSignature( +25: bytes memory tbs, +26: bytes memory signature, +27: PublicKey memory publicKey, +28: Algorithm alg + +// @audit tbs, signature, publicKey +54: function verifyCertificateSignature( +55: bytes memory tbs, +56: bytes memory signature, +57: PublicKey memory publicKey, +58: CertSigAlgorithm alg + +// @audit tbs, signature, publicKey +79: function verifyRS256Signature( +80: bytes memory tbs, +81: bytes memory signature, +82: bytes memory publicKey + +// @audit tbs, signature, publicKey +96: function verifyRS1Signature( +97: bytes memory tbs, +98: bytes memory signature, +99: bytes memory publicKey + +// @audit tbs, signature, publicKey +113: function verifyES256Signature( +114: bytes memory tbs, +115: bytes memory signature, +116: bytes memory publicKey +``` + +[[24-28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L24-L28), [54-58](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L54-L58), [79-82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L79-L82), [96-99](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L96-L99), [113-116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L113-L116)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +// @audit x509Time +8: function toTimestamp(bytes memory x509Time) internal pure returns (uint256) { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L8)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoGovernor.sol + +// @audit _description +48: function propose( +49: address[] memory _targets, +50: uint256[] memory _values, +51: bytes[] memory _calldatas, +52: string memory _description + +// @audit _description +69: function propose( +70: address[] memory _targets, +71: uint256[] memory _values, +72: string[] memory _signatures, +73: bytes[] memory _calldatas, +74: string memory _description +``` + +[[48-52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L48-L52), [69-74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L69-L74)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +// @audit _blk, _data +62: function onBlockProposed( +63: TaikoData.Block memory _blk, +64: TaikoData.BlockMetadata memory _meta, +65: bytes memory _data + +// @audit _assignment +137: function hashAssignment( +138: ProverAssignment memory _assignment, +139: address _taikoL1Address, +140: bytes32 _blobHash + +// @audit _tierFees +164: function _getProverFee( +165: TaikoData.TierFee[] memory _tierFees, +166: uint16 _tierId +``` + +[[62-65](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L62-L65), [137-140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L137-L140), [164-166](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L164-L166)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +// @audit _config +67: function processDeposits( +68: TaikoData.State storage _state, +69: TaikoData.Config memory _config, +70: address _feeRecipient + +// @audit _config +122: function canDepositEthToL2( +123: TaikoData.State storage _state, +124: TaikoData.Config memory _config, +125: uint256 _amount +``` + +[[67-70](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L67-L70), [122-125](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L122-L125)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +// @audit _config +287: function isBlobReusable( +288: TaikoData.State storage _state, +289: TaikoData.Config memory _config, +290: bytes32 _blobHash + +// @audit _slotB +299: function _isProposerPermitted( +300: TaikoData.SlotB memory _slotB, +301: IAddressResolver _resolver +``` + +[[287-290](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L287-L290), [299-301](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L299-L301)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +// @audit _config +91: function proveBlock( +92: TaikoData.State storage _state, +93: TaikoData.Config memory _config, +94: IAddressResolver _resolver, +95: TaikoData.BlockMetadata memory _meta, +96: TaikoData.Transition memory _tran, +97: TaikoData.TierProof memory _proof + +// @audit _tran +269: function _createTransition( +270: TaikoData.State storage _state, +271: TaikoData.Block storage _blk, +272: TaikoData.Transition memory _tran, +273: uint64 slot + +// @audit _tran, _proof, _tier +350: function _overrideWithHigherProof( +351: TaikoData.TransitionState storage _ts, +352: TaikoData.Transition memory _tran, +353: TaikoData.TierProof memory _proof, +354: ITierProvider.Tier memory _tier, +355: IERC20 _tko, +356: bool _sameTransition + +// @audit _tier +401: function _checkProverPermission( +402: TaikoData.State storage _state, +403: TaikoData.Block storage _blk, +404: TaikoData.TransitionState storage _ts, +405: uint32 _tid, +406: ITierProvider.Tier memory _tier +``` + +[[91-97](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L91-L97), [269-273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L269-L273), [350-356](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L350-L356), [401-406](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L401-L406)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +// @audit _config +23: function getTransition( +24: TaikoData.State storage _state, +25: TaikoData.Config memory _config, +26: uint64 _blockId, +27: bytes32 _parentHash + +// @audit _config +52: function getBlock( +53: TaikoData.State storage _state, +54: TaikoData.Config memory _config, +55: uint64 _blockId +``` + +[[23-27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L23-L27), [52-55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L52-L55)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +// @audit _config +224: function _syncChainData( +225: TaikoData.Config memory _config, +226: IAddressResolver _resolver, +227: uint64 _lastVerifiedBlockId, +228: bytes32 _stateRoot + +// @audit _config +245: function _isConfigValid(TaikoData.Config memory _config) private view returns (bool) { +``` + +[[224-228](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L224-L228), [245](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L245)] + +```solidity +File: packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol + +// @audit _calldata +25: function excessivelySafeCall( +26: address _target, +27: uint256 _gas, +28: uint256 _value, +29: uint16 _maxCopy, +30: bytes memory _calldata +``` + +[[25-30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol#L25-L30)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/Bytes.sol + +// @audit _bytes +15: function slice( +16: bytes memory _bytes, +17: uint256 _start, +18: uint256 _length + +// @audit _bytes +91: function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { + +// @audit _bytes +102: function toNibbles(bytes memory _bytes) internal pure returns (bytes memory) { + +// @audit _bytes, _other +149: function equal(bytes memory _bytes, bytes memory _other) internal pure returns (bool) { +``` + +[[15-18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L15-L18), [91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L91), [102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L102), [149](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L149)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +// @audit quote +21: function parseInput( +22: bytes memory quote, +23: address pemCertLibAddr + +// @audit v3Quote +62: function validateParsedInput(V3Struct.ParsedV3QuoteStruct memory v3Quote) + +// @audit rawEnclaveReport +133: function parseEnclaveReport(bytes memory rawEnclaveReport) + +// @audit encoded +152: function littleEndianDecode(bytes memory encoded) private pure returns (uint256 decoded) { + +// @audit rawHeader +165: function parseAndVerifyHeader(bytes memory rawHeader) + +// @audit rawAuthData +203: function parseAuthDataAndVerifyCertType( +204: bytes memory rawAuthData, +205: address pemCertLibAddr + +// @audit enclaveReport +244: function packQEReport(V3Struct.EnclaveReport memory enclaveReport) + +// @audit certBytes +267: function parseCerificationChainBytes( +268: bytes memory certBytes, +269: address pemCertLibAddr +``` + +[[21-23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L21-L23), [62](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L62), [133](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L133), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L152), [165](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L165), [203-205](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L203-L205), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L244), [267-269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L267-L269)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +// @audit _in +35: function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) { + +// @audit _in +102: function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) { + +// @audit _in +128: function readBytes(bytes memory _in) internal pure returns (bytes memory out_) { + +// @audit _in +135: function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) { + +// @audit _in +144: function _decodeLength(RLPItem memory _in) +``` + +[[35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L35), [102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L102), [128](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L128), [135](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L135), [144](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L144)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +// @audit _in +13: function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) { +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L13)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +// @audit _key, _value +50: function verifyInclusionProof( +51: bytes memory _key, +52: bytes memory _value, +53: bytes[] memory _proof, +54: bytes32 _root + +// @audit _key +68: function get( +69: bytes memory _key, +70: bytes[] memory _proof, +71: bytes32 _root + +// @audit _proof +205: function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory proof_) { + +// @audit _node +227: function _getNodePath(TrieNode memory _node) private pure returns (bytes memory nibbles_) { + +// @audit _a, _b +235: function _getSharedNibbleLength( +236: bytes memory _a, +237: bytes memory _b +``` + +[[50-54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L50-L54), [68-71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L68-L71), [205](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L205), [227](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L227), [235-237](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L235-L237)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol + +// @audit _key, _value +19: function verifyInclusionProof( +20: bytes memory _key, +21: bytes memory _value, +22: bytes[] memory _proof, +23: bytes32 _root + +// @audit _key +38: function get( +39: bytes memory _key, +40: bytes[] memory _proof, +41: bytes32 _root + +// @audit _key +54: function _getSecureKey(bytes memory _key) private pure returns (bytes memory hash_) { +``` + +[[19-23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol#L19-L23), [38-41](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol#L38-L41), [54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol#L54)] + +
+ +--- + +### [G-13] Avoid updating storage when the value hasn't changed + +If the old value is equal to the new value, not re-storing the value will avoid a Gsreset (**2900 gas**), potentially at the expense of a Gcoldsload (**2100 gas**) or a Gwarmaccess (**100 gas**) + +_There are 12 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +// @audit _trustedUserMrSigner +65: function setMrSigner(bytes32 _mrSigner, bool _trusted) external onlyOwner { + +// @audit _trustedUserMrEnclave +69: function setMrEnclave(bytes32 _mrEnclave, bool _trusted) external onlyOwner { + +// @audit tcbInfo +103: function configureTcbInfoJson( + +// @audit qeIdentity +114: function configureQeIdentityJson(EnclaveIdStruct.EnclaveId calldata qeIdentityInput) +``` + +[[65](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L65), [69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L69), [103](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L103), [114](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L114)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +// @audit messageStatus +515: function _updateMessageStatus(bytes32 _msgHash, Status _status) private { +``` + +[[515](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L515)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +// @audit __addresses +38: function setAddress( +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L38)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +// @audit customConfig +25: function setConfigAndExcess( +``` + +[[25](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L25)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +// @audit snapshooter +80: function setSnapshoter(address _snapshooter) external onlyOwner { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L80)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +// @audit migratingAddress, migratingInbound +36: function changeMigrationStatus( +``` + +[[36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L36)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +// @audit btokenBlacklist, bridgedToCanonical, canonicalToBridged +148: function changeBridgedToken( +``` + +[[148](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L148)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +// @audit guardianIds, minGuardians +53: function setGuardians( +``` + +[[53](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L53)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +// @audit claimStart, claimEnd, merkleRoot +90: function _setConfig(uint64 _claimStart, uint64 _claimEnd, bytes32 _merkleRoot) private { +``` + +[[90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L90)] + +
+ +--- + +### [G-14] Use of `emit` inside a loop + +Emitting an event inside a loop performs a `LOG` op N times, where N is the loop length. Consider refactoring the code to emit the event only once at the end of loop. Gas savings should be multiplied by the average loop length. + +_There are 4 instances of this issue._ + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +93: emit MessageSuspended(msgHash, _suspend); +``` + +[[93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L93)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +109: emit InstanceDeleted(idx, instances[idx].addr); + +220: emit InstanceAdded(nextInstanceId, _instances[i], address(0), validSince); +``` + +[[109](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L109), [220](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L220)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +198: emit BlockVerified({ +199: blockId: blockId, +200: assignedProver: blk.assignedProver, +201: prover: ts.prover, +202: blockHash: blockHash, +203: stateRoot: stateRoot, +204: tier: ts.tier, +205: contestations: ts.contestations +206: }); +``` + +[[198-206](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L198-L206)] + +--- + +### [G-15] Use `uint256(1)/uint256(2)` instead of `true/false` to save gas for changes + +Use `uint256(1)` and `uint256(2)` for `true`/`false` to avoid a Gsset (20000 gas) when changing from `false` to `true`, after having been `true` in the past. See [source](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/58f635312aa21f947cae5f8578638a85aa2519f5/contracts/security/ReentrancyGuard.sol#L23-L27). + +_There are 10 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +38: bool private _checkLocalEnclaveReport; + +39: mapping(bytes32 enclave => bool trusted) private _trustedUserMrEnclave; + +40: mapping(bytes32 signer => bool trusted) private _trustedUserMrSigner; + +47: mapping(uint256 idx => mapping(bytes serialNum => bool revoked)) private _serialNumIsRevoked; +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L38), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L39), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L40), [47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L47)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +42: mapping(address addr => bool banned) public addressBanned; +``` + +[[42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L42)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +21: mapping(address addr => bool authorized) public isAuthorized; +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L21)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +14: bool public migratingInbound; +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L14)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +52: mapping(address btoken => bool blacklisted) public btokenBlacklist; +``` + +[[52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L52)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +55: mapping(address instanceAddress => bool alreadyAttested) public addressRegistered; +``` + +[[55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L55)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +12: mapping(bytes32 hash => bool claimed) public isClaimed; +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L12)] + +
+ +--- + +### [G-16] Shortcircuit rules can be be used to optimize some gas usage + +Some conditions may be reordered to save an `SLOAD` (**2100 gas**), as we avoid reading state variables when the first part of the condition fails (with `&&`), or succeeds (with `||`). + +_There is 1 instance of this issue._ + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +// @audit switch with this condition +// ctx.from != owner() || ctx.srcChainId != ownerChainId +46: if (ctx.srcChainId != ownerChainId || ctx.from != owner()) { +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L46)] + +--- + +### [G-17] Cache multiple accesses of a mapping/array + +Consider using a local `storage` or `calldata` variable when accessing a mapping/array value multiple times. + +This can be useful to avoid recalculating the mapping hash and/or the array offsets. + +_There are 13 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +// @audit _serialNumIsRevoked on line 81 +84: _serialNumIsRevoked[index][serialNumBatch[i]] = true; + +// @audit _serialNumIsRevoked[index] on line 96 +99: delete _serialNumIsRevoked[index][serialNumBatch[i]]; + +// @audit _serialNumIsRevoked[uint256(IPEMCertChainLib.CRL.PCK)] on line 268 +271: certRevoked = _serialNumIsRevoked[uint256(IPEMCertChainLib.CRL.PCK)][certs[i] +272: .serialNumber]; +``` + +[[84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L84), [99](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L99), [271-272](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L271-L272)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +// @audit proofReceipt on lines 168, 184 +190: delete proofReceipt[msgHash]; +``` + +[[190](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L190)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +// @audit __addresses on line 47 +49: __addresses[_chainId][_name] = _newAddress; +``` + +[[49](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L49)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +// @audit state.transitions on line 154 +154: ts_ = state.transitions[slot][blk_.verifiedTransitionId]; +``` + +[[154](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L154)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +// @audit topBlockId on line 247 +248: topBlockId[_chainId][_kind] = _blockId; +``` + +[[248](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L248)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +// @audit recipients on line 137 +142: recipients[_recipient].grant = _grant; +``` + +[[142](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L142)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +// @audit canonicalToBridged on line 168 +189: canonicalToBridged[_ctoken.chainId][_ctoken.addr] = _btokenNew; + +// @audit bridgedToCanonical on line 358 +359: ctoken_ = bridgedToCanonical[_token]; +``` + +[[189](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L189), [359](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L359)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +// @audit instances on lines 107, 109 +111: delete instances[idx]; + +// @audit instances on lines 235, 236 +237: && block.timestamp <= instances[id].validSince + INSTANCE_EXPIRY; +``` + +[[111](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L111), [237](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L237)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +// @audit _approvals on line 116 +119: uint256 _approval = _approvals[version][_hash]; +``` + +[[119](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L119)] + +
+ +--- + +### [G-18] Redundant state variable getters + +Getters for public state variables are automatically generated with public variables, so there is no need to code them manually, as it adds an unnecessary overhead. + +_There are 2 instances of this issue._ + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +200: function getBlockHash(uint64 _blockId) public view returns (bytes32) { +201: if (_blockId >= block.number) return 0; +202: if (_blockId + 256 >= block.number) return blockhash(_blockId); +203: return l2Hashes[_blockId]; +204: } +``` + +[[200-204](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L200-L204)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +43: function getConfig() public view override returns (Config memory) { +44: return customConfig; +45: } +``` + +[[43-45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L43-L45)] + +--- + +### [G-19] Using `private` for constants saves gas + +Saves deployment gas due to the compiler not having to create non-payable getter functions for deployment calldata, not having to store the bytes of the value outside of where it's used, and not adding another entry to the method ID table. + +_There are 14 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +35: uint8 public constant BLOCK_SYNC_THRESHOLD = 5; +``` + +[[35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L35)] + +```solidity +File: packages/protocol/contracts/libs/Lib4844.sol + +10: address public constant POINT_EVALUATION_PRECOMPILE_ADDRESS = address(0x0A); + +13: uint32 public constant FIELD_ELEMENTS_PER_BLOB = 4096; + +16: uint256 public constant BLS_MODULUS = +17: 52_435_875_175_126_190_479_447_740_508_185_965_837_690_552_500_527_637_822_603_658_699_938_581_184_513; +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L10), [13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L13), [16-17](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L16-L17)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +47: bytes4 public constant ERC1155_INTERFACE_ID = 0xd9b67a26; + +50: bytes4 public constant ERC721_INTERFACE_ID = 0x80ac58cd; + +53: uint256 public constant MAX_TOKEN_PER_TXN = 10; +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L47), [50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L50), [53](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L53)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +30: uint64 public constant INSTANCE_EXPIRY = 180 days; + +34: uint64 public constant INSTANCE_VALIDITY_DELAY = 1 days; +``` + +[[30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L30), [34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L34)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +38: uint256 public constant MAX_GAS_PAYING_PROVER = 50_000; +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L38)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +21: uint256 public constant MAX_BYTES_PER_BLOB = 4096 * 32; +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L21)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +20: bytes32 public constant RETURN_LIVENESS_BOND = keccak256("RETURN_LIVENESS_BOND"); + +23: bytes32 public constant TIER_OP = bytes32("tier_optimistic"); +``` + +[[20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L20), [23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L23)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +11: uint256 public constant MIN_NUM_GUARDIANS = 5; +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L11)] + +
+ +--- + +### [G-20] require() or revert() statements that check input arguments should be at the top of the function + +Checks that can be performed earlier should come before checks that involve state variables, function calls, and calculations. By doing these checks first, the function is able to revert before wasting a Gcoldsload (_2100 gas_) in a function that may ultimately revert. + +_There are 4 instances of this issue._ + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +// @audit expensive op on line 103 +105: if (_addressManager == address(0)) revert ZERO_ADDR_MANAGER(); +``` + +[[105](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L105)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +// @audit expensive op on line 120 +121: if (_taikoToken == address(0)) revert INVALID_PARAM(); + +// @audit expensive op on line 120 +124: if (_costToken == address(0)) revert INVALID_PARAM(); + +// @audit expensive op on line 120 +127: if (_sharedVault == address(0)) revert INVALID_PARAM(); +``` + +[[121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L121), [124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L124), [127](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L127)] + +--- + +### [G-21] Consider activating `via-ir` for deploying + +The IR-based code generator was developed to make code generation more performant by enabling optimization passes that can be applied across functions. + +It is possible to activate the IR-based code generator through the command line by using the flag `--via-ir` or by including the option `{"viaIR": true}`. + +Keep in mind that compiling with this option may take longer. However, you can simply test it before deploying your code. If you find that it provides better performance, you can add the `--via-ir` flag to your deploy command. + +--- + +### [G-22] Function calls should be cached instead of re-calling the function + +Consider caching the result instead of re-calling the function when possible. Note: this also includes casts, which cost between 42-46 gas, depending on the type. + +_There are 12 instances of this issue._ + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +// @audit blockhash(parentId) is duplicated on line 157 +154: l2Hashes[parentId] = blockhash(parentId); +``` + +[[154](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L154)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +// @audit der.nextSiblingOf(tbsPtr) is duplicated on line 111, 112, 127, 144, 157, 186 +104: tbsPtr = der.nextSiblingOf(tbsPtr); + +// @audit der.firstChildOf(tbsPtr) is duplicated on line 130, 147, 161, 193, 194 +115: uint256 issuerPtr = der.firstChildOf(tbsPtr); + +// @audit der.firstChildOf(issuerPtr) is duplicated on line 117 +116: issuerPtr = der.firstChildOf(issuerPtr); + +// @audit der.firstChildOf(subjectPtr) is duplicated on line 149 +148: subjectPtr = der.firstChildOf(subjectPtr); + +// @audit der.nextSiblingOf(sigPtr) is duplicated on line 176 +167: sigPtr = der.nextSiblingOf(sigPtr); + +// @audit _trimBytes(der.bytesAt(sigPtr), 32) is duplicated on line 177 +174: bytes memory sigX = _trimBytes(der.bytesAt(sigPtr), 32); + +// @audit der.bytesAt(sigPtr) is duplicated on line 177 +174: bytes memory sigX = _trimBytes(der.bytesAt(sigPtr), 32); + +// @audit der.nextSiblingOf(extnValueOidPtr) is duplicated on line 318 +312: uint256 pceidPtr = der.nextSiblingOf(extnValueOidPtr); + +// @audit bytes2(svnValueBytes) is duplicated on line 360 +359: ? uint16(bytes2(svnValueBytes)) / 256 +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L104), [115](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L115), [116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L116), [148](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L148), [167](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L167), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L174), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L174), [312](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L312), [359](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L359)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +// @audit MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) is duplicated on line 86 +78: ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) + +// @audit MemoryPointer.unwrap(_in.ptr) is duplicated on line 86 +78: ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) +``` + +[[78](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L78), [78](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L78)] + +--- + +### [G-23] Functions that revert when called by normal users can be `payable` + +If a function modifier such as `onlyOwner` is used, the function will revert if a normal user tries to pay the function. + +Marking the function as `payable` will lower the gas for legitimate callers, as the compiler will not include checks for whether a payment was provided. + +The extra opcodes avoided are: + +`CALLVALUE(2), DUP1(3), ISZERO(3), PUSH2(3), JUMPI(10), PUSH1(3), DUP1(3), REVERT(0), JUMPDEST(1), POP(2)` + +which cost an average of about 21 gas per call to the function, in addition to the extra deployment cost. + +_There are 37 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +65: function setMrSigner(bytes32 _mrSigner, bool _trusted) external onlyOwner { + +69: function setMrEnclave(bytes32 _mrEnclave, bool _trusted) external onlyOwner { + +73: function addRevokedCertSerialNum( +74: uint256 index, +75: bytes[] calldata serialNumBatch +76: ) +77: external +78: onlyOwner + +88: function removeRevokedCertSerialNum( +89: uint256 index, +90: bytes[] calldata serialNumBatch +91: ) +92: external +93: onlyOwner + +103: function configureTcbInfoJson( +104: string calldata fmspc, +105: TCBInfoStruct.TCBInfo calldata tcbInfoInput +106: ) +107: public +108: onlyOwner + +114: function configureQeIdentityJson(EnclaveIdStruct.EnclaveId calldata qeIdentityInput) +115: external +116: onlyOwner + +122: function toggleLocalReportCheck() external onlyOwner { +``` + +[[65](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L65), [69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L69), [73-78](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L73-L78), [88-93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L88-L93), [103-108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L103-L108), [114-116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L114-L116), [122](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L122)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +82: function suspendMessages( +83: bytes32[] calldata _msgHashes, +84: bool _suspend +85: ) +86: external +87: onlyFromOwnerOrNamed("bridge_watchdog") + +101: function banAddress( +102: address _addr, +103: bool _ban +104: ) +105: external +106: onlyFromOwnerOrNamed("bridge_watchdog") +107: nonReentrant +``` + +[[82-87](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L82-L87), [101-107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L101-L107)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +38: function setAddress( +39: uint64 _chainId, +40: bytes32 _name, +41: address _newAddress +42: ) +43: external +44: virtual +45: onlyOwner +``` + +[[38-45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L38-L45)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +58: function __AddressResolver_init(address _addressManager) internal virtual onlyInitializing { +``` + +[[58](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L58)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +95: function __Essential_init( +96: address _owner, +97: address _addressManager +98: ) +99: internal +100: virtual +101: onlyInitializing + +114: function _authorizeUpgrade(address) internal virtual override onlyOwner { } + +116: function _authorizePause(address) internal virtual onlyOwner { } +``` + +[[95-101](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L95-L101), [114](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L114), [116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L116)] + +```solidity +File: packages/protocol/contracts/L1/TaikoToken.sol + +47: function burn(address _from, uint256 _amount) public onlyOwner { + +52: function snapshot() public onlyFromOwnerOrNamed("snapshooter") { +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L47), [52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L52)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +60: function __CrossChainOwned_init( +61: address _owner, +62: address _addressManager, +63: uint64 _ownerChainId +64: ) +65: internal +66: virtual +67: onlyInitializing +``` + +[[60-67](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L60-L67)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +163: function withdraw( +164: address _token, +165: address _to +166: ) +167: external +168: onlyFromOwnerOrNamed("withdrawer") +169: nonReentrant +170: whenNotPaused +``` + +[[163-170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L163-L170)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +25: function setConfigAndExcess( +26: Config memory _newConfig, +27: uint64 _newGasExcess +28: ) +29: external +30: virtual +31: onlyOwner +``` + +[[25-31](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L25-L31)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +56: function authorize(address _addr, bool _authorize) external onlyOwner { +``` + +[[56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L56)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +135: function grant(address _recipient, Grant memory _grant) external onlyOwner { + +150: function void(address _recipient) external onlyOwner { +``` + +[[135](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L135), [150](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L150)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +66: function mint( +67: address _to, +68: uint256 _tokenId, +69: uint256 _amount +70: ) +71: public +72: nonReentrant +73: whenNotPaused +74: onlyFromNamed("erc1155_vault") + +83: function mintBatch( +84: address _to, +85: uint256[] memory _tokenIds, +86: uint256[] memory _amounts +87: ) +88: public +89: nonReentrant +90: whenNotPaused +91: onlyFromNamed("erc1155_vault") + +100: function burn( +101: address _account, +102: uint256 _tokenId, +103: uint256 _amount +104: ) +105: public +106: nonReentrant +107: whenNotPaused +108: onlyFromNamed("erc1155_vault") +``` + +[[66-74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L66-L74), [83-91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L83-L91), [100-108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L100-L108)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +80: function setSnapshoter(address _snapshooter) external onlyOwner { + +85: function snapshot() external onlyOwnerOrSnapshooter { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L80), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L85)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +36: function changeMigrationStatus( +37: address _migratingAddress, +38: bool _migratingInbound +39: ) +40: external +41: nonReentrant +42: whenNotPaused +43: onlyFromOwnerOrNamed("erc20_vault") +``` + +[[36-43](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L36-L43)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +54: function mint( +55: address _account, +56: uint256 _tokenId +57: ) +58: public +59: nonReentrant +60: whenNotPaused +61: onlyFromNamed("erc721_vault") + +69: function burn( +70: address _account, +71: uint256 _tokenId +72: ) +73: public +74: nonReentrant +75: whenNotPaused +76: onlyFromNamed("erc721_vault") +``` + +[[54-61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L54-L61), [69-76](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L69-L76)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +148: function changeBridgedToken( +149: CanonicalERC20 calldata _ctoken, +150: address _btokenNew +151: ) +152: external +153: nonReentrant +154: whenNotPaused +155: onlyOwner +``` + +[[148-155](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L148-L155)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +90: function addInstances(address[] calldata _instances) +91: external +92: onlyOwner + +100: function deleteInstances(uint256[] calldata _ids) +101: external +102: onlyFromOwnerOrNamed("rollup_watchdog") + +139: function verifyProof( +140: Context calldata _ctx, +141: TaikoData.Transition calldata _tran, +142: TaikoData.TierProof calldata _proof +143: ) +144: external +145: onlyFromNamed("taiko") +``` + +[[90-92](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L90-L92), [100-102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L100-L102), [139-145](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L139-L145)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +53: function setGuardians( +54: address[] memory _newGuardians, +55: uint8 _minGuardians +56: ) +57: external +58: onlyOwner +59: nonReentrant +``` + +[[53-59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L53-L59)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +45: function setConfig( +46: uint64 _claimStart, +47: uint64 _claimEnd, +48: bytes32 _merkleRoot +49: ) +50: external +51: onlyOwner + +56: function __MerkleClaimable_init( +57: uint64 _claimStart, +58: uint64 _claimEnd, +59: bytes32 _merkleRoot +60: ) +61: internal +62: onlyInitializing +``` + +[[45-51](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L45-L51), [56-62](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L56-L62)] + +
+ +--- + +### [G-24] Caching global variables is more expensive than using the actual variable + +It's better to not cache global variables, as their direct usage is cheaper (e.g. `msg.sender`). + +_There is 1 instance of this issue._ + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +93: address taikoL1Address = msg.sender; +``` + +[[93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L93)] + +--- + +### [G-25] Add `unchecked` blocks for subtractions where the operands cannot underflow + +There are some checks to avoid an underflow, so it's safe to use `unchecked` to have some gas savings. + +_There are 7 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +// @audit check on line 275 +276: numL1Blocks = _l1BlockId - lastSyncedBlock; +``` + +[[276](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L276)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +// @audit check on line 257 +264: return _amount * uint64(block.timestamp - _start) / _period; +``` + +[[264](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L264)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +// @audit check on line 262 +265: uint256 lengthDiff = n - expectedLength; +``` + +[[265](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L265)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +// @audit check on line 90 +93: mask = ~(2 ** (8 * (32 - shortest + idx)) - 1); +``` + +[[93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L93)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/Bytes.sol + +// @audit check on line 92 +95: return slice(_bytes, _start, _bytes.length - _start); +``` + +[[95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L95)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +// @audit check on line 166 +190: uint256 lenOfStrLen = prefix - 0xb7; + +// @audit check on line 223 +236: uint256 lenOfListLen = prefix - 0xf7; +``` + +[[190](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L190), [236](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L236)] + +
+ +--- + +### [G-26] Add `unchecked` blocks for divisions where the operands cannot overflow + +`uint` divisions can't overflow, while `int` divisions can overflow only in [one specific case](https://docs.soliditylang.org/en/latest/types.html#division). + +Consider adding an `unchecked` block to have some [gas savings](https://gist.github.com/DadeKuma/3bc597338ae774b8b3bd43280d55271f). + +_There are 13 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +215: ethDepositMaxFee: 1 ether / 10, +``` + +[[215](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L215)] + +```solidity +File: packages/protocol/contracts/L2/Lib1559Math.sol + +28: return _ethQty(_gasExcess, _adjustmentFactor) / LibFixedPointMath.SCALING_FACTOR +29: / _adjustmentFactor; + +28: return _ethQty(_gasExcess, _adjustmentFactor) / LibFixedPointMath.SCALING_FACTOR + +41: uint256 input = _gasExcess * LibFixedPointMath.SCALING_FACTOR / _adjustmentFactor; +``` + +[[28-29](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L28-L29), [28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L28), [41](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L41)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +197: uint128 _amountUnlocked = amountUnlocked / 1e18; // divide first + +264: return _amount * uint64(block.timestamp - _start) / _period; +``` + +[[197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L197), [264](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L264)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +359: ? uint16(bytes2(svnValueBytes)) / 256 +``` + +[[359](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L359)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoGovernor.sol + +124: return 1_000_000_000 ether / 10_000; // 0.01% of Taiko Token +``` + +[[124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L124)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +262: || _config.ethDepositMaxFee > type(uint96).max / _config.ethDepositMaxCountPerBlock +``` + +[[262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L262)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +117: uint256 timeBasedAllowance = balance +118: * (block.timestamp.min(claimEnd + withdrawalWindow) - claimEnd) / withdrawalWindow; +``` + +[[117-118](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L117-L118)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +155: uint256 upperDigit = digits / 16; +``` + +[[155](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L155)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +39: while (_len / i != 0) { + +47: out_[i] = bytes1(uint8((_len / (256 ** (lenLen - i))) % 256)); +``` + +[[39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L39), [47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L47)] + +
+ +--- + +### [G-27] Empty blocks should be removed or emit something + +Some functions don't have a body: consider commenting why, or add some logic. Otherwise, refactor the code and remove these functions. + +_There is 1 instance of this issue._ + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +70: receive() external payable { } +``` + +[[70](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L70)] + +--- + +### [G-28] Usage of `uints`/`ints` smaller than 32 bytes (256 bits) incurs overhead + +Citing the [documentation](https://docs.soliditylang.org/en/latest/internals/layout_in_storage.html): + +> When using elements that are smaller than 32 bytes, your contract’s gas usage may be higher.This is because the EVM operates on 32 bytes at a time.Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size. + +For example, each operation involving a `uint8` costs an extra ** 22 - 28 gas ** (depending on whether the other operand is also a variable of type `uint8`) as compared to ones involving`uint256`, due to the compiler having to clear the higher bits of the memory word before operating on the`uint8`, as well as the associated stack operations of doing so. + +Note that it might be beneficial to use reduced-size types when dealing with storage values because the compiler will pack multiple elements into one storage slot, but if not, it will have the opposite effect. + +_There are 322 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +36: uint8 internal constant INVALID_EXIT_CODE = 255; +``` + +[[36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L36)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +31: uint128 public nextMessageId; + +64: modifier sameChain(uint64 _chainId) { + +89: uint64 _timestamp = _suspend ? type(uint64).max : uint64(block.timestamp); + +168: uint64 receivedAt = proofReceipt[msgHash].receivedAt; + +230: uint64 receivedAt = proofReceipt[msgHash].receivedAt; + +392: function isDestChainEnabled(uint64 _chainId) + +541: function _storeContext(bytes32 _msgHash, address _from, uint64 _srcChainId) private { + +559: uint64 srcChainId; + +580: uint64 _chainId, +``` + +[[31](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L31), [64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L64), [89](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L89), [168](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L168), [230](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L230), [392](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L392), [541](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L541), [559](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L559), [580](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L580)] + +```solidity +File: packages/protocol/contracts/bridge/IBridge.sol + +19: uint128 id; + +24: uint64 srcChainId; + +26: uint64 destChainId; + +51: uint64 receivedAt; + +63: uint64 srcChainId; // Source chain ID. +``` + +[[19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L19), [24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L24), [26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L26), [51](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L51), [63](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L63)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +22: uint64 indexed chainId, bytes32 indexed name, address newAddress, address oldAddress + +39: uint64 _chainId, + +54: function getAddress(uint64 _chainId, bytes32 _name) public view override returns (address) { +``` + +[[22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L22), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L39), [54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L54)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +19: error RESOLVER_ZERO_ADDR(uint64 chainId, bytes32 name); + +44: uint64 _chainId, + +73: uint64 _chainId, +``` + +[[19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L19), [44](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L44), [73](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L73)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +11: uint8 private constant _FALSE = 1; + +13: uint8 private constant _TRUE = 2; + +21: uint8 private __reentry; + +23: uint8 private __paused; + +119: function _storeReentryLock(uint8 _reentry) internal virtual { + +130: function _loadReentryLock() internal view virtual returns (uint8 reentry_) { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L11), [13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L13), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L21), [23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L23), [119](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L119), [130](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L130)] + +```solidity +File: packages/protocol/contracts/common/IAddressManager.sol + +14: function getAddress(uint64 _chainId, bytes32 _name) external view returns (address); +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/IAddressManager.sol#L14)] + +```solidity +File: packages/protocol/contracts/common/IAddressResolver.sol + +35: uint64 _chainId, +``` + +[[35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/IAddressResolver.sol#L35)] + +```solidity +File: packages/protocol/contracts/L1/ITaikoL1.sol + +27: function proveBlock(uint64 _blockId, bytes calldata _input) external; + +31: function verifyBlocks(uint64 _maxBlocksToVerify) external; +``` + +[[27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/ITaikoL1.sol#L27), [31](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/ITaikoL1.sol#L31)] + +```solidity +File: packages/protocol/contracts/L1/TaikoData.sol + +15: uint64 chainId; + +20: uint64 blockMaxProposals; + +22: uint64 blockRingBufferSize; + +24: uint64 maxBlocksToVerifyPerProposal; + +26: uint32 blockMaxGasLimit; + +28: uint24 blockMaxTxListBytes; + +30: uint24 blobExpiry; + +39: uint96 livenessBond; + +46: uint64 ethDepositMinCountPerBlock; + +48: uint64 ethDepositMaxCountPerBlock; + +50: uint96 ethDepositMinAmount; + +52: uint96 ethDepositMaxAmount; + +59: uint8 blockSyncThreshold; + +64: uint16 tier; + +65: uint128 fee; + +69: uint16 tier; + +83: uint24 txListByteOffset; + +84: uint24 txListByteSize; + +101: uint64 id; + +102: uint32 gasLimit; + +103: uint64 timestamp; // slot 7 + +104: uint64 l1Height; + +105: uint24 txListByteOffset; + +106: uint24 txListByteSize; + +107: uint16 minTier; + +127: uint96 validityBond; + +129: uint96 contestBond; + +130: uint64 timestamp; // slot 6 (90 bits) + +131: uint16 tier; + +132: uint8 contestations; + +140: uint96 livenessBond; + +141: uint64 blockId; // slot 3 + +142: uint64 proposedAt; // timestamp + +143: uint64 proposedIn; // L1 block number + +144: uint32 nextTransitionId; + +145: uint32 verifiedTransitionId; + +152: uint96 amount; + +153: uint64 id; + +162: uint64 genesisHeight; + +163: uint64 genesisTimestamp; + +164: uint64 numEthDeposits; + +165: uint64 nextEthDepositToProcess; + +169: uint64 numBlocks; + +170: uint64 lastVerifiedBlockId; + +172: uint8 __reserved1; + +173: uint16 __reserved2; + +174: uint32 __reserved3; + +175: uint64 lastUnpausedAt; +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L15), [20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L20), [22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L22), [24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L24), [26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L26), [28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L28), [30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L30), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L39), [46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L46), [48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L48), [50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L50), [52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L52), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L59), [64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L64), [65](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L65), [69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L69), [83](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L83), [84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L84), [101](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L101), [102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L102), [103](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L103), [104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L104), [105](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L105), [106](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L106), [107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L107), [127](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L127), [129](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L129), [130](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L130), [131](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L131), [132](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L132), [140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L140), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L141), [142](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L142), [143](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L143), [144](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L144), [145](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L145), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L152), [153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L153), [162](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L162), [163](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L163), [164](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L164), [165](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L165), [169](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L169), [170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L170), [172](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L172), [173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L173), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L174), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L175)] + +```solidity +File: packages/protocol/contracts/L1/TaikoEvents.sol + +24: uint96 livenessBond, + +43: uint16 tier, + +44: uint8 contestations + +57: uint96 validityBond, + +58: uint16 tier + +71: uint96 contestBond, + +72: uint16 tier +``` + +[[24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L24), [43](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L43), [44](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L44), [57](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L57), [58](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L58), [71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L71), [72](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L72)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +76: uint64 _blockId, + +94: uint8 maxBlocksToVerify = LibProving.proveBlock(state, config, this, meta, tran, proof); + +100: function verifyBlocks(uint64 _maxBlocksToVerify) + +145: function getBlock(uint64 _blockId) + +150: uint64 slot; + +163: uint64 _blockId, +``` + +[[76](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L76), [94](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L94), [100](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L100), [145](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L145), [150](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L150), [163](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L163)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +16: uint64 public ownerChainId; + +19: uint64 public nextTxId; + +26: event TransactionExecuted(uint64 indexed txId, bytes4 indexed selector); + +42: (uint64 txId, bytes memory txdata) = abi.decode(_data, (uint64, bytes)); + +63: uint64 _ownerChainId +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L16), [19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L19), [26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L26), [42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L42), [63](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L63)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +27: uint32 gasTargetPerL1Block; + +28: uint8 basefeeAdjustmentQuotient; + +35: uint8 public constant BLOCK_SYNC_THRESHOLD = 5; + +47: uint64 public gasExcess; + +50: uint64 public lastSyncedBlock; + +57: event Anchored(bytes32 parentHash, uint64 gasExcess); + +74: uint64 _l1ChainId, + +75: uint64 _gasExcess + +110: uint64 _l1BlockId, + +111: uint32 _parentGasUsed + +186: uint64 _l1BlockId, + +187: uint32 _parentGasUsed + +200: function getBlockHash(uint64 _blockId) public view returns (bytes32) { + +254: uint64 _l1BlockId, + +255: uint32 _parentGasUsed + +259: returns (uint256 basefee_, uint64 gasExcess_) +``` + +[[27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L27), [28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L28), [35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L35), [47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L47), [50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L50), [57](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L57), [74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L74), [75](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L75), [110](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L110), [111](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L111), [186](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L186), [187](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L187), [200](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L200), [254](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L254), [255](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L255), [259](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L259)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +18: event ConfigAndExcessChanged(Config config, uint64 gasExcess); + +27: uint64 _newGasExcess +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L18), [27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L27)] + +```solidity +File: packages/protocol/contracts/libs/Lib4844.sol + +13: uint32 public constant FIELD_ELEMENTS_PER_BLOB = 4096; +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L13)] + +```solidity +File: packages/protocol/contracts/signal/ISignalService.sol + +21: uint64 chainId; + +22: uint64 blockId; + +37: uint64 indexed chainId, + +38: uint64 indexed blockId, + +69: uint64 _chainId, + +71: uint64 _blockId, + +85: uint64 _chainId, + +106: uint64 _chainId, + +108: uint64 _blockId, + +123: uint64 _chainId, + +125: uint64 _blockId + +129: returns (uint64 blockId_, bytes32 chainData_); + +138: uint64 _chainId, + +140: uint64 _blockId +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L21), [22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L22), [37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L37), [38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L38), [69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L69), [71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L71), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L85), [106](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L106), [108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L108), [123](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L123), [125](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L125), [129](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L129), [138](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L138), [140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L140)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +69: uint64 _chainId, + +71: uint64 _blockId, + +84: uint64 _chainId, + +97: uint64 chainId = _chainId; + +138: uint64 _chainId, + +140: uint64 _blockId, + +159: uint64 _chainId, + +161: uint64 _blockId + +165: returns (uint64 blockId_, bytes32 chainData_) + +178: uint64 _chainId, + +180: uint64 _blockId + +195: uint64 _chainId, + +207: uint64 _chainId, + +236: uint64 _chainId, + +238: uint64 _blockId, + +273: uint64 _chainId, + +274: uint64 _blockId, +``` + +[[69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L69), [71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L71), [84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L84), [97](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L97), [138](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L138), [140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L140), [159](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L159), [161](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L161), [165](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L165), [178](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L178), [180](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L180), [195](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L195), [207](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L207), [236](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L236), [238](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L238), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L273), [274](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L274)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +29: uint128 amount; + +31: uint128 costPerToken; + +34: uint64 grantStart; + +37: uint64 grantCliff; + +40: uint32 grantPeriod; + +43: uint64 unlockStart; + +46: uint64 unlockCliff; + +49: uint32 unlockPeriod; + +53: uint128 amountWithdrawn; + +54: uint128 costPaid; + +68: uint128 public totalAmountGranted; + +71: uint128 public totalAmountVoided; + +74: uint128 public totalAmountWithdrawn; + +77: uint128 public totalCostPaid; + +92: event Voided(address indexed recipient, uint128 amount); + +99: event Withdrawn(address indexed recipient, address to, uint128 amount, uint128 cost); + +99: event Withdrawn(address indexed recipient, address to, uint128 amount, uint128 cost); + +152: uint128 amountVoided = _voidGrant(r.grant); + +180: uint128 amountOwned, + +181: uint128 amountUnlocked, + +182: uint128 amountWithdrawn, + +183: uint128 amountToWithdraw, + +184: uint128 costToWithdraw + +197: uint128 _amountUnlocked = amountUnlocked / 1e18; // divide first + +211: (,,, uint128 amountToWithdraw, uint128 costToWithdraw) = getMyGrantSummary(_recipient); + +211: (,,, uint128 amountToWithdraw, uint128 costToWithdraw) = getMyGrantSummary(_recipient); + +225: function _voidGrant(Grant storage _grant) private returns (uint128 amountVoided) { + +226: uint128 amountOwned = _getAmountOwned(_grant); + +235: function _getAmountOwned(Grant memory _grant) private view returns (uint128) { + +239: function _getAmountUnlocked(Grant memory _grant) private view returns (uint128) { + +246: uint128 _amount, + +247: uint64 _start, + +248: uint64 _cliff, + +249: uint64 _period + +253: returns (uint128) + +273: function _validateCliff(uint64 _start, uint64 _cliff, uint32 _period) private pure { + +273: function _validateCliff(uint64 _start, uint64 _cliff, uint32 _period) private pure { + +273: function _validateCliff(uint64 _start, uint64 _cliff, uint32 _period) private pure { +``` + +[[29](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L29), [31](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L31), [34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L34), [37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L37), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L40), [43](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L43), [46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L46), [49](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L49), [53](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L53), [54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L54), [68](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L68), [71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L71), [74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L74), [77](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L77), [92](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L92), [99](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L99), [99](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L99), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L152), [180](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L180), [181](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L181), [182](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L182), [183](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L183), [184](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L184), [197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L197), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L211), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L211), [225](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L225), [226](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L226), [235](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L235), [239](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L239), [246](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L246), [247](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L247), [248](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L248), [249](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L249), [253](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L253), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L273), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L273), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L273)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +13: uint64 chainId; + +25: uint64 destChainId; + +70: uint64 indexed chainId, + +90: uint64 destChainId, + +126: uint64 srcChainId, +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L13), [25](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L25), [70](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L70), [90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L90), [126](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L126)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +24: uint8 private __srcDecimals; + +57: uint8 _decimals, + +117: returns (uint8) +``` + +[[24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L24), [57](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L57), [117](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L117)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +24: uint64 chainId; + +26: uint8 decimals; + +33: uint64 destChainId; + +69: uint8 ctokenDecimal + +87: uint8 ctokenDecimal + +102: uint64 destChainId, + +130: uint64 srcChainId, +``` + +[[24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L24), [26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L26), [33](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L33), [69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L69), [87](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L87), [102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L102), [130](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L130)] + +```solidity +File: packages/protocol/contracts/verifiers/IVerifier.sol + +14: uint64 blockId; +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/IVerifier.sol#L14)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +26: uint64 validSince; + +30: uint64 public constant INSTANCE_EXPIRY = 180 days; + +34: uint64 public constant INSTANCE_VALIDITY_DELAY = 1 days; + +154: uint32 id = uint32(bytes4(Bytes.slice(_proof.data, 0, 4))); + +204: uint64 validSince = uint64(block.timestamp); +``` + +[[26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L26), [30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L30), [34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L34), [154](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L154), [204](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L204)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol + +10: uint16 isvprodid; + +23: uint16 isvsvn; +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol#L10), [23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol#L23)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +358: uint16 svnValue = svnValueBytes.length < 2 +``` + +[[358](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L358)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol + +189: uint80 ixFirstContentByte; + +190: uint80 ixLastContentByte; + +196: uint8 lengthbytesLength = uint8(der[ix + 1] & 0x7F); +``` + +[[189](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L189), [190](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L190), [196](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L196)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +188: function readUint8(bytes memory self, uint256 idx) internal pure returns (uint8 ret) { + +198: function readUint16(bytes memory self, uint256 idx) internal pure returns (uint16 ret) { + +211: function readUint32(bytes memory self, uint256 idx) internal pure returns (uint32 ret) { + +332: uint8 decoded; +``` + +[[188](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L188), [198](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L198), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L211), [332](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L332)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +9: uint16 yrs; + +10: uint8 mnths; + +11: uint8 dys; + +12: uint8 hrs; + +13: uint8 mins; + +14: uint8 secs; + +15: uint8 offset; + +35: uint16 year, + +36: uint8 month, + +37: uint8 day, + +38: uint8 hour, + +39: uint8 minute, + +40: uint8 second + +48: for (uint16 i = 1970; i < year; ++i) { + +59: for (uint8 i = 1; i < month; ++i) { + +71: function isLeapYear(uint16 year) internal pure returns (bool) { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L9), [10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L10), [11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L11), [12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L12), [13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L13), [14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L14), [15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L15), [35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L35), [36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L36), [37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L37), [38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L38), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L39), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L40), [48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L48), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L59), [71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L71)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +20: uint64 expiry; + +21: uint64 maxBlockId; + +22: uint64 maxProposedIn; + +166: uint16 _tierId +``` + +[[20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L20), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L21), [22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L22), [166](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L166)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +83: uint96 fee = uint96(_config.ethDepositMaxFee.min(block.basefee * _config.ethDepositGas)); + +84: uint64 j = _state.slotA.nextEthDepositToProcess; + +85: uint96 totalFee; + +93: uint96 _fee = deposits_[i].amount > fee ? fee : deposits_[i].amount; +``` + +[[83](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L83), [84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L84), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L85), [93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L93)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +34: uint96 livenessBond, +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L34)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +36: uint96 validityBond, + +37: uint16 tier + +50: uint96 contestBond, + +51: uint16 tier + +100: returns (uint8 maxBlocksToVerify_) + +115: uint64 slot = _meta.id % _config.blockRingBufferSize; + +129: (uint32 tid, TaikoData.TransitionState storage ts) = + +273: uint64 slot + +276: returns (uint32 tid_, TaikoData.TransitionState storage ts_) + +405: uint32 _tid, +``` + +[[36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L36), [37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L37), [50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L50), [51](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L51), [100](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L100), [115](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L115), [129](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L129), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L273), [276](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L276), [405](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L405)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +26: uint64 _blockId, + +38: uint64 slot = _blockId % _config.blockRingBufferSize; + +42: uint32 tid = getTransitionId(_state, blk, slot, _parentHash); + +55: uint64 _blockId + +59: returns (TaikoData.Block storage blk_, uint64 slot_) + +73: uint64 _slot, + +78: returns (uint32 tid_) +``` + +[[26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L26), [38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L38), [42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L42), [55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L55), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L59), [73](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L73), [78](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L78)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +34: uint16 tier, + +35: uint8 contestations + +89: uint64 _maxBlocksToVerify + +100: uint64 blockId = b.lastVerifiedBlockId; + +102: uint64 slot = blockId % _config.blockRingBufferSize; + +107: uint32 tid = blk.verifiedTransitionId; + +117: uint64 numBlocksVerified; + +213: uint64 lastVerifiedBlockId = b.lastVerifiedBlockId + numBlocksVerified; + +227: uint64 _lastVerifiedBlockId, + +234: (uint64 lastSyncedBlock,) = signalService.getSyncedChainData( +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L34), [35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L35), [89](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L89), [100](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L100), [102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L102), [107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L107), [117](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L117), [213](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L213), [227](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L227), [234](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L234)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +27: uint32 public version; + +30: uint32 public minGuardians; + +37: event GuardiansUpdated(uint32 version, address[] guardians); + +55: uint8 _minGuardians +``` + +[[27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L27), [30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L30), [37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L37), [55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L55)] + +```solidity +File: packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol + +20: function getTier(uint16 _tierId) public pure override returns (ITierProvider.Tier memory) { + +54: function getMinTier(uint256) public pure override returns (uint16) { +``` + +[[20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol#L20), [54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol#L54)] + +```solidity +File: packages/protocol/contracts/L1/tiers/ITierProvider.sol + +10: uint96 validityBond; + +11: uint96 contestBond; + +12: uint24 cooldownWindow; // in minutes + +13: uint16 provingWindow; // in minutes + +14: uint8 maxBlocksToVerifyPerProof; + +22: function getTier(uint16 tierId) external view returns (Tier memory); + +33: function getMinTier(uint256 rand) external view returns (uint16); + +39: uint16 public constant TIER_OPTIMISTIC = 100; + +42: uint16 public constant TIER_SGX = 200; + +45: uint16 public constant TIER_SGX_ZKVM = 300; + +48: uint16 public constant TIER_GUARDIAN = 1000; +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L10), [11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L11), [12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L12), [13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L13), [14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L14), [22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L22), [33](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L33), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L39), [42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L42), [45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L45), [48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L48)] + +```solidity +File: packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol + +20: function getTier(uint16 _tierId) public pure override returns (ITierProvider.Tier memory) { + +66: function getMinTier(uint256 _rand) public pure override returns (uint16) { +``` + +[[20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol#L20), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol#L66)] + +```solidity +File: packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol + +20: function getTier(uint16 _tierId) public pure override returns (ITierProvider.Tier memory) { + +66: function getMinTier(uint256 _rand) public pure override returns (uint16) { +``` + +[[20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol#L20), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol#L66)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +29: uint64 _claimStart, + +30: uint64 _claimEnd, + +69: (address delegatee, uint256 nonce, uint256 expiry, uint8 v, bytes32 r, bytes32 s) = +``` + +[[29](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L29), [30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L30), [69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L69)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +28: uint64 public withdrawalWindow; + +56: uint64 _claimStart, + +57: uint64 _claimEnd, + +61: uint64 _withdrawalWindow +``` + +[[28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L28), [56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L56), [57](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L57), [61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L61)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +27: uint64 _claimStart, + +28: uint64 _claimEnd, +``` + +[[27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L27), [28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L28)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +18: uint64 public claimStart; + +21: uint64 public claimEnd; + +46: uint64 _claimStart, + +47: uint64 _claimEnd, + +57: uint64 _claimStart, + +58: uint64 _claimEnd, + +90: function _setConfig(uint64 _claimStart, uint64 _claimEnd, bytes32 _merkleRoot) private { + +90: function _setConfig(uint64 _claimStart, uint64 _claimEnd, bytes32 _merkleRoot) private { +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L18), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L21), [46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L46), [47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L47), [57](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L57), [58](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L58), [90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L90), [90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L90)] + +```solidity +File: packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol + +29: uint16 _maxCopy, +``` + +[[29](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol#L29)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +106: uint32 totalQuoteSize = 48 // header + +249: uint16 isvProdIdPackBE = (enclaveReport.isvProdId >> 8) | (enclaveReport.isvProdId << 8); + +250: uint16 isvSvnPackBE = (enclaveReport.isvSvn >> 8) | (enclaveReport.isvSvn << 8); +``` + +[[106](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L106), [249](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L249), [250](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L250)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol + +26: uint16 isvProdId; + +27: uint16 isvSvn; + +34: uint16 parsedDataSize; + +39: uint16 certType; + +43: uint32 certDataSize; +``` + +[[26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol#L26), [27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol#L27), [34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol#L34), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol#L39), [43](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol#L43)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +30: uint8 internal constant PREFIX_EXTENSION_EVEN = 0; + +33: uint8 internal constant PREFIX_EXTENSION_ODD = 1; + +36: uint8 internal constant PREFIX_LEAF_EVEN = 2; + +39: uint8 internal constant PREFIX_LEAF_ODD = 3; + +134: uint8 branchKey = uint8(key[currentKeyIndex]); + +141: uint8 prefix = uint8(path[0]); + +142: uint8 offset = 2 - (prefix % 2); +``` + +[[30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L30), [33](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L33), [36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L36), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L39), [134](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L134), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L141), [142](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L142)] + +
+ +--- + +### [G-29] Stack variable cost less while used in emitting event + +Using a stack variable instead of a state variable is cheaper when emitting an event. + +_There are 7 instances of this issue._ + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +// @audit nextTxId++ +53: emit TransactionExecuted(nextTxId++, bytes4(txdata)); +``` + +[[53](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L53)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +// @audit gasExcess +157: emit Anchored(blockhash(parentId), gasExcess); +``` + +[[157](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L157)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +// @audit migratingAddress +63: emit MigratedTo(migratingAddress, _account, _amount); + +// @audit migratingAddress +80: emit MigratedTo(migratingAddress, _account, _amount); +``` + +[[63](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L63), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L80)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +// @audit instances[idx].addr +109: emit InstanceDeleted(idx, instances[idx].addr); + +// @audit nextInstanceId +220: emit InstanceAdded(nextInstanceId, _instances[i], address(0), validSince); +``` + +[[109](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L109), [220](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L220)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +// @audit version +95: emit GuardiansUpdated(version, _newGuardians); +``` + +[[95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L95)] + +--- + +### [G-30] Redundant `event` fields can be removed + +Some parameters (`block.timestamp` and `block.number`) are added to event information by default so re-adding them wastes gas, as they are already included. + +_There is 1 instance of this issue._ + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +230: emit InstanceAdded(id, newInstance, oldInstance, block.timestamp); +``` + +[[230](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L230)] + +--- + +### [G-31] Using pre instead of post increments/decrements + +Pre increments/decrements (`++i/--i`) are cheaper than post increments/decrements (`i++/i--`): it saves 6 gas per expression. + +_There are 7 instances of this issue._ + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +222: nextInstanceId++; +``` + +[[222](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L222)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +46: for (i = 1; i <= lenLen; i++) { + +59: for (; i < 32; i++) { + +66: for (uint256 j = 0; j < out_.length; j++) { + +67: out_[j] = b[i++]; + +40: lenLen++; +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L46), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L59), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L66), [67](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L67), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L40)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +85: for (uint256 i = 0; i < proof.length; i++) { +``` + +[[85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L85)] + +--- + +### [G-32] `>=`/`<=` costs less gas than `>`/`<` + +The compiler uses opcodes `GT` and `ISZERO` for code that uses `>`, but only requires `LT` for `>=`. A similar behaviour applies for `>`, which uses opcodes `LT` and `ISZERO`, but only requires `GT` for `<=`. + +_There are 130 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +80: for (uint256 i; i < serialNumBatch.length; ++i) { + +95: for (uint256 i; i < serialNumBatch.length; ++i) { + +191: for (uint256 i; i < enclaveId.tcbLevels.length; ++i) { + +214: for (uint256 i; i < tcb.tcbLevels.length; ++i) { + +240: for (uint256 i; i < CPUSVN_LENGTH; ++i) { + +241: if (pckCpuSvns[i] < tcbCpuSvns[i]) { + +259: for (uint256 i; i < n; ++i) { + +280: block.timestamp > certs[i].notBefore && block.timestamp < certs[i].notAfter; + +280: block.timestamp > certs[i].notBefore && block.timestamp < certs[i].notAfter; + +420: for (uint256 i; i < 3; ++i) { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L80), [95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L95), [191](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L191), [214](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L214), [240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L240), [241](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L241), [259](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L259), [280](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L280), [280](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L280), [420](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L420)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +90: for (uint256 i; i < _msgHashes.length; ++i) { +``` + +[[90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L90)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +59: if (block.chainid > type(uint64).max) { +``` + +[[59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L59)] + +```solidity +File: packages/protocol/contracts/L2/Lib1559Math.sol + +42: if (input > LibFixedPointMath.MAX_EXP_INPUT) { +``` + +[[42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L42)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +82: if (block.chainid <= 1 || block.chainid > type(uint64).max) { + +145: if (_l1BlockId > lastSyncedBlock + BLOCK_SYNC_THRESHOLD) { + +234: for (uint256 i; i < 255 && _blockId >= i + 1; ++i) { + +262: if (gasExcess > 0) { + +275: if (lastSyncedBlock > 0 && _l1BlockId > lastSyncedBlock) { + +275: if (lastSyncedBlock > 0 && _l1BlockId > lastSyncedBlock) { + +279: if (numL1Blocks > 0) { + +281: excess = excess > issuance ? excess - issuance : 1; +``` + +[[82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L82), [145](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L145), [234](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L234), [262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L262), [275](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L275), [275](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L275), [279](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L279), [281](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L281)] + +```solidity +File: packages/protocol/contracts/libs/LibMath.sol + +13: return _a > _b ? _b : _a; + +21: return _a > _b ? _a : _b; +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibMath.sol#L13), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibMath.sol#L21)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +104: for (uint256 i; i < hopProofs.length; ++i) { + +120: bool isFullProof = hop.accountProof.length > 0; + +247: if (topBlockId[_chainId][_kind] < _blockId) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L104), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L120), [247](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L247)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +275: if (_cliff > 0) revert INVALID_GRANT(); + +277: if (_cliff > 0 && _cliff <= _start) revert INVALID_GRANT(); +``` + +[[275](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L275), [277](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L277)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +145: if (_op.tokenIds.length > MAX_TOKEN_PER_TXN) { +``` + +[[145](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L145)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +47: for (uint256 i; i < _op.amounts.length; ++i) { + +251: for (uint256 i; i < _op.tokenIds.length; ++i) { + +269: for (uint256 i; i < _op.tokenIds.length; ++i) { +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L47), [251](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L251), [269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L269)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +34: for (uint256 i; i < _op.tokenIds.length; ++i) { + +170: for (uint256 i; i < _tokenIds.length; ++i) { + +175: for (uint256 i; i < _tokenIds.length; ++i) { + +197: for (uint256 i; i < _op.tokenIds.length; ++i) { + +210: for (uint256 i; i < _op.tokenIds.length; ++i) { +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L34), [170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L170), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L175), [197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L197), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L210)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +104: for (uint256 i; i < _ids.length; ++i) { + +210: for (uint256 i; i < _instances.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L104), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L210)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +54: for (uint256 i; i < size; ++i) { + +56: if (i > 0) { + +244: for (uint256 i; i < split.length; ++i) { + +323: if (extnValuePtr.ixl() < extnValueParentPtr.ixl()) { + +333: if (tbsPtr.ixl() < tbsParentPtr.ixl()) { + +354: for (uint256 i; i < SGX_TCB_CPUSVN_SIZE + 1; ++i) { + +358: uint16 svnValue = svnValueBytes.length < 2 +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L54), [56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L56), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L244), [323](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L323), [333](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L333), [354](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L354), [358](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L358)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +69: if (otherlen < len) { + +80: for (uint256 idx = 0; idx < shortest; idx += 32) { + +90: if (shortest > 32) { + +333: for (uint256 i; i < len; ++i) { +``` + +[[69](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L69), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L80), [90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L90), [333](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L333)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +140: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +152: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +158: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +174: for (uint256 i; i < _sha256.length; ++i) { + +273: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +283: for (uint256 i; i < sha1Prefix.length; ++i) { + +290: for (uint256 i; i < _sha1.length; ++i) { +``` + +[[140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L140), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L152), [158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L158), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L174), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L273), [283](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L283), [290](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L290)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +18: if (uint8(x509Time[0]) - 48 < 5) yrs += 2000; + +48: for (uint16 i = 1970; i < year; ++i) { + +59: for (uint8 i = 1; i < month; ++i) { +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L18), [48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L48), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L59)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +82: block.timestamp > assignment.expiry + +85: || assignment.maxBlockId != 0 && _meta.id > assignment.maxBlockId + +86: || assignment.maxProposedIn != 0 && block.number > assignment.maxProposedIn + +125: if (address(this).balance > 0) { + +172: for (uint256 i; i < _tierFees.length; ++i) { +``` + +[[82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L82), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L85), [86](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L86), [125](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L125), [172](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L172)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +78: if (numPending < _config.ethDepositMinCountPerBlock) { + +86: for (uint256 i; i < deposits_.length;) { + +93: uint96 _fee = deposits_[i].amount > fee ? fee : deposits_[i].amount; + +140: && _state.slotA.numEthDeposits - _state.slotA.nextEthDepositToProcess +141: < _config.ethDepositRingBufferSize - 1; + +150: if (_amount > type(uint96).max) revert L1_INVALID_ETH_DEPOSIT(); +``` + +[[78](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L78), [86](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L86), [93](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L93), [140-141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L140-L141), [150](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L150)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +171: if (uint256(params.txListByteOffset) + params.txListByteSize > MAX_BYTES_PER_BLOB) { + +195: if (meta_.txListByteSize == 0 || meta_.txListByteSize > _config.blockMaxTxListBytes) { + +244: for (uint256 i; i < params.hookCalls.length; ++i) { + +296: return _state.reusableBlobs[_blobHash] + _config.blobExpiry > block.timestamp; +``` + +[[171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L171), [195](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L195), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L244), [296](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L296)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +134: if (_proof.tier == 0 || _proof.tier < _meta.minTier || _proof.tier < ts.tier) { + +134: if (_proof.tier == 0 || _proof.tier < _meta.minTier || _proof.tier < ts.tier) { + +192: bool returnLivenessBond = blk.livenessBond > 0 && _proof.data.length == 32 + +203: if (_proof.tier > ts.tier) { + +381: if (reward > _tier.validityBond) { +``` + +[[134](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L134), [134](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L134), [192](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L192), [203](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L203), [381](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L381)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +34: if (_blockId < b.lastVerifiedBlockId || _blockId >= b.numBlocks) { +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L34)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +127: while (blockId < b.numBlocks && numBlocksVerified < _maxBlocksToVerify) { + +127: while (blockId < b.numBlocks && numBlocksVerified < _maxBlocksToVerify) { + +152: uint256(ITierProvider(tierProvider).getTier(ts.tier).cooldownWindow) * 60 +153: + uint256(ts.timestamp).max(_state.slotB.lastUnpausedAt) > block.timestamp + +212: if (numBlocksVerified > 0) { + +238: if (_lastVerifiedBlockId > lastSyncedBlock + _config.blockSyncThreshold) { + +251: || _config.blockMaxTxListBytes > 128 * 1024 // calldata up to 128K + +256: || _config.ethDepositMaxCountPerBlock > 32 + +257: || _config.ethDepositMaxCountPerBlock < _config.ethDepositMinCountPerBlock + +260: || _config.ethDepositMaxAmount > type(uint96).max || _config.ethDepositGas == 0 + +262: || _config.ethDepositMaxFee > type(uint96).max / _config.ethDepositMaxCountPerBlock +``` + +[[127](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L127), [127](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L127), [152-153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L152-L153), [212](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L212), [238](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L238), [251](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L251), [256](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L256), [257](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L257), [260](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L260), [262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L262)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +63: if (_newGuardians.length < MIN_NUM_GUARDIANS || _newGuardians.length > type(uint8).max) { + +63: if (_newGuardians.length < MIN_NUM_GUARDIANS || _newGuardians.length > type(uint8).max) { + +68: if (_minGuardians < (_newGuardians.length + 1) >> 1 || _minGuardians > _newGuardians.length) + +68: if (_minGuardians < (_newGuardians.length + 1) >> 1 || _minGuardians > _newGuardians.length) + +74: for (uint256 i; i < guardians.length; ++i) { + +80: for (uint256 i = 0; i < _newGuardians.length; ++i) { + +133: for (uint256 i; i < guardiansLength; ++i) { +``` + +[[63](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L63), [63](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L63), [68](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L68), [68](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L68), [74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L74), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L80), [133](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L133)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +40: if (claimEnd > block.timestamp || claimEnd + withdrawalWindow < block.timestamp) { + +40: if (claimEnd > block.timestamp || claimEnd + withdrawalWindow < block.timestamp) { + +114: if (block.timestamp < claimEnd) return (balance, 0); +``` + +[[40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L40), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L40), [114](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L114)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +59: for (uint256 i; i < tokenIds.length; ++i) { +``` + +[[59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L59)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +35: merkleRoot == 0x0 || claimStart == 0 || claimEnd == 0 || claimStart > block.timestamp + +36: || claimEnd < block.timestamp +``` + +[[35](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L35), [36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L36)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +153: for (uint256 i; i < encoded.length; ++i) { + +218: if (cert.certType < 1 || cert.certType > 5) { + +218: if (cert.certType < 1 || cert.certType > 5) { + +281: for (uint256 i; i < 3; ++i) { +``` + +[[153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L153), [218](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L218), [218](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L218), [281](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L281)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +38: _in.length > 0, + +74: while (offset < _in.length) { + +153: _in.length > 0, + +173: _in.length > strLen, + +193: _in.length > lenOfStrLen, + +213: strLen > 55, + +218: _in.length > lenOfStrLen + strLen, + +229: _in.length > listLen, + +239: _in.length > lenOfListLen, + +259: listLen > 55, + +264: _in.length > lenOfListLen + listLen, +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L38), [74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L74), [153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L153), [173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L173), [193](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L193), [213](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L213), [218](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L218), [229](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L229), [239](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L239), [259](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L259), [264](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L264)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +14: if (_in.length == 1 && uint8(_in[0]) < 128) { + +33: if (_len < 56) { + +59: for (; i < 32; i++) { + +66: for (uint256 j = 0; j < out_.length; j++) { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L14), [33](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L33), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L59), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L66)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +77: require(_key.length > 0, "MerkleTrie: empty key"); + +85: for (uint256 i = 0; i < proof.length; i++) { + +120: value_.length > 0, + +173: value_.length > 0, + +208: for (uint256 i = 0; i < length;) { + +221: id_ = _node.length < 32 ? RLPReader.readRawBytes(_node) : RLPReader.readBytes(_node); + +243: uint256 max = (_a.length < _b.length) ? _a.length : _b.length; + +244: for (; shared_ < max && _a[shared_] == _b[shared_];) { +``` + +[[77](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L77), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L85), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L120), [173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L173), [208](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L208), [221](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L221), [243](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L243), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L244)] + +
+ +--- + +### [G-33] `internal` functions only called once can be inlined to save gas + +Consider removing the following internal functions, and put the logic directly where they are called, as they are called only once. + +_There are 20 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +126: function _attestationTcbIsValid(TCBInfoStruct.TCBStatus status) +``` + +[[126](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L126)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +109: function __Essential_init(address _owner) internal virtual { +``` + +[[109](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L109)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +42: function sendEther(address _to, uint256 _amount) internal { +``` + +[[42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L42)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +206: function _verifyHopProof( +``` + +[[206](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L206)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +97: function _mintToken(address _account, uint256 _amount) internal virtual; + +99: function _burnToken(address _from, uint256 _amount) internal virtual; +``` + +[[97](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L97), [99](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L99)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +56: function compare( +``` + +[[56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L56)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +43: function pkcs1Sha256( + +212: function pkcs1Sha1( +``` + +[[43](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L43), [212](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L212)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +34: function toUnixTimestamp( +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L34)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +122: function canDepositEthToL2( +``` + +[[122](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L122)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +287: function isBlobReusable( +``` + +[[287](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L287)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +70: function getTransitionId( +``` + +[[70](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L70)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +77: function _verifyMerkleProof( +``` + +[[77](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L77)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/Bytes.sol + +91: function slice(bytes memory _bytes, uint256 _start) internal pure returns (bytes memory) { +``` + +[[91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L91)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +267: function parseCerificationChainBytes( +``` + +[[267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L267)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +102: function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) { + +128: function readBytes(bytes memory _in) internal pure returns (bytes memory out_) { +``` + +[[102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L102), [128](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L128)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +13: function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) { +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L13)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +68: function get( +``` + +[[68](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L68)] + +
+ +--- + +### [G-34] Inline `modifiers` that are only used once, to save gas + +Consider removing the following modifiers, and put the logic directly in the function where they are used, as they are used only once. + +_There are 5 instances of this issue._ + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +53: modifier whenPaused() { +54: if (!paused()) revert INVALID_PAUSE_STATUS(); +55: _; +56: } + +58: modifier whenNotPaused() { +59: if (paused()) revert INVALID_PAUSE_STATUS(); +60: _; +61: } +``` + +[[53-56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L53-L56), [58-61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L58-L61)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +37: modifier onlyOwnerOrSnapshooter() { +38: if (msg.sender != owner() && msg.sender != snapshooter) { +39: revert BTOKEN_UNAUTHORIZED(); +40: } +41: _; +42: } +``` + +[[37-42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L37-L42)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +39: modifier ongoingWithdrawals() { +40: if (claimEnd > block.timestamp || claimEnd + withdrawalWindow < block.timestamp) { +41: revert WITHDRAWALS_NOT_ONGOING(); +42: } +43: _; +44: } +``` + +[[39-44](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L39-L44)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +33: modifier ongoingClaim() { +34: if ( +35: merkleRoot == 0x0 || claimStart == 0 || claimEnd == 0 || claimStart > block.timestamp +36: || claimEnd < block.timestamp +37: ) revert CLAIM_NOT_ONGOING(); +38: _; +39: } +``` + +[[33-39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L33-L39)] + +--- + +### [G-35] `private` functions only called once can be inlined to save gas + +Consider removing the following private functions, and put the logic directly where they are called, as they are called only once. + +_There are 41 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +162: function _verify(bytes calldata quote) private view returns (bool, bytes memory) { + +175: function _verifyQEReportWithIdentity(V3Struct.EnclaveReport memory quoteEnclaveReport) + +206: function _checkTcbLevels( + +229: function _isCpuSvnHigherOrGreater( + +248: function _verifyCertChain(IPEMCertChainLib.ECSha256Certificate[] memory certs) + +303: function _enclaveReportSigVerification( +``` + +[[162](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L162), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L175), [206](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L206), [229](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L229), [248](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L248), [303](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L303)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +555: function _loadContext() private view returns (Context memory) { +``` + +[[555](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L555)] + +```solidity +File: packages/protocol/contracts/L2/Lib1559Math.sol + +33: function _ethQty( +``` + +[[33](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L33)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +271: function _cacheChainData( +``` + +[[271](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L271)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +225: function _voidGrant(Grant storage _grant) private returns (uint128 amountVoided) { + +239: function _getAmountUnlocked(Grant memory _grant) private view returns (uint128) { + +267: function _validateGrant(Grant memory _grant) private pure { +``` + +[[225](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L225), [239](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L239), [267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L267)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +240: function _handleMessage( + +288: function _getOrDeployBridgedToken(CanonicalNFT memory _ctoken) + +303: function _deployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) { +``` + +[[240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L240), [288](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L288), [303](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L303)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +348: function _handleMessage( + +391: function _getOrDeployBridgedToken(CanonicalERC20 memory ctoken) + +407: function _deployBridgedToken(CanonicalERC20 memory ctoken) private returns (address btoken) { +``` + +[[348](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L348), [391](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L391), [407](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L407)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +187: function _handleMessage( + +224: function _getOrDeployBridgedToken(CanonicalNFT memory _ctoken) + +240: function _deployBridgedToken(CanonicalNFT memory _ctoken) private returns (address btoken_) { +``` + +[[187](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L187), [224](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L224), [240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L240)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +226: function _replaceInstance(uint256 id, address oldInstance, address newInstance) private { + +233: function _isInstanceValid(uint256 id, address instance) private view returns (bool) { +``` + +[[226](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L226), [233](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L233)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +216: function _removeHeadersAndFooters(string memory pemData) + +269: function _findPckTcbInfo( + +341: function _findTcb( +``` + +[[216](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L216), [269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L269), [341](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L341)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +272: function memcpy(uint256 dest, uint256 src, uint256 len) private pure { +``` + +[[272](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L272)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +164: function _getProverFee( +``` + +[[164](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L164)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +299: function _isProposerPermitted( +``` + +[[299](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L299)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +269: function _createTransition( + +350: function _overrideWithHigherProof( + +401: function _checkProverPermission( +``` + +[[269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L269), [350](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L350), [401](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L401)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +224: function _syncChainData( + +245: function _isConfigValid(TaikoData.Config memory _config) private view returns (bool) { +``` + +[[224](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L224), [245](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L245)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +165: function parseAndVerifyHeader(bytes memory rawHeader) + +203: function parseAuthDataAndVerifyCertType( +``` + +[[165](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L165), [203](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L203)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +32: function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) { + +55: function _toBinary(uint256 _x) private pure returns (bytes memory out_) { +``` + +[[32](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L32), [55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L55)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +205: function _parseProof(bytes[] memory _proof) private pure returns (TrieNode[] memory proof_) { + +227: function _getNodePath(TrieNode memory _node) private pure returns (bytes memory nibbles_) { + +235: function _getSharedNibbleLength( +``` + +[[205](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L205), [227](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L227), [235](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L235)] + +
+ +--- + +### [G-36] Use multiple revert checks to save gas + +Splitting the conditions into two separate checks [saves](https://gist.github.com/IllIllI000/7e25b0fca6bd9d57d9b9bcb9d2018959) 2 gas per split. + +_There are 37 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +124: if (_message.srcOwner == address(0) || _message.destOwner == address(0)) { +125: revert B_INVALID_USER(); +126: } + +260: if (_message.gasLimit == 0 && msg.sender != _message.destOwner) { +261: revert B_PERMISSION_DENIED(); +262: } + +321: if (_message.gasLimit == 0 || _isLastAttempt) { +322: if (msg.sender != _message.destOwner) revert B_PERMISSION_DENIED(); +323: } + +405: if (ctx_.msgHash == 0 || ctx_.msgHash == bytes32(PLACEHOLDER)) { +406: revert B_INVALID_CONTEXT(); +407: } +``` + +[[124-126](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L124-L126), [260-262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L260-L262), [321-323](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L321-L323), [405-407](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L405-L407)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +85: if (!_allowZeroAddress && addr_ == address(0)) { +86: revert RESOLVER_ZERO_ADDR(_chainId, _name); +87: } +``` + +[[85-87](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L85-L87)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +42: if (msg.sender != owner() && msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); +``` + +[[42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L42)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +46: if (ctx.srcChainId != ownerChainId || ctx.from != owner()) { +47: revert XCO_PERMISSION_DENIED(); +48: } + +70: if (_ownerChainId == 0 || _ownerChainId == block.chainid) { +71: revert XCO_INVALID_OWNER_CHAINID(); +72: } +``` + +[[46-48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L46-L48), [70-72](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L70-L72)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +82: if (block.chainid <= 1 || block.chainid > type(uint64).max) { +83: revert L2_INVALID_CHAIN_ID(); +84: } + +116: if ( +117: _l1BlockHash == 0 || _l1StateRoot == 0 || _l1BlockId == 0 +118: || (block.number != 1 && _parentGasUsed == 0) +119: ) { +120: revert L2_INVALID_PARAM(); +121: } + +141: if (!skipFeeCheck() && block.basefee != basefee) { +142: revert L2_BASEFEE_MISMATCH(); +143: } +``` + +[[82-84](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L82-L84), [116-121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L116-L121), [141-143](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L141-L143)] + +```solidity +File: packages/protocol/contracts/libs/Lib4844.sol + +57: if (uint256(first) != FIELD_ELEMENTS_PER_BLOB || uint256(second) != BLS_MODULUS) { +58: revert EVAL_FAILED_2(); +59: } +``` + +[[57-59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L57-L59)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +114: if (hop.chainId == 0 || hop.chainId == block.chainid) { +115: revert SS_INVALID_MID_HOP_CHAINID(); +116: } + +131: if (value == 0 || value != _loadSignalValue(address(this), signal)) { +132: revert SS_SIGNAL_NOT_FOUND(); +133: } +``` + +[[114-116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L114-L116), [131-133](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L131-L133)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +274: if (_start == 0 || _period == 0) { +275: if (_cliff > 0) revert INVALID_GRANT(); +276: } else { +277: if (_cliff > 0 && _cliff <= _start) revert INVALID_GRANT(); +278: if (_cliff >= _start + _period) revert INVALID_GRANT(); +279: } + +277: if (_cliff > 0 && _cliff <= _start) revert INVALID_GRANT(); +``` + +[[274-279](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L274-L279), [277](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L277)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +38: if (msg.sender != owner() && msg.sender != snapshooter) { +39: revert BTOKEN_UNAUTHORIZED(); +40: } +``` + +[[38-40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L38-L40)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +45: if (_migratingAddress == migratingAddress && _migratingInbound == migratingInbound) { +46: revert BB_INVALID_PARAMS(); +47: } +``` + +[[45-47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L45-L47)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +108: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); +``` + +[[108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L108)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +158: if (_btokenNew == address(0) || bridgedToCanonical[_btokenNew].addr != address(0)) { +159: revert VAULT_INVALID_NEW_BTOKEN(); +160: } + +174: if ( +175: ctoken.decimals != _ctoken.decimals +176: || keccak256(bytes(ctoken.symbol)) != keccak256(bytes(_ctoken.symbol)) +177: || keccak256(bytes(ctoken.name)) != keccak256(bytes(_ctoken.name)) +178: ) revert VAULT_CTOKEN_MISMATCH(); + +267: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); +``` + +[[158-160](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L158-L160), [174-178](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L174-L178), [267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L267)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +91: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); +``` + +[[91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L91)] + +```solidity +File: packages/protocol/contracts/tokenvault/LibBridgedToken.sol + +20: if ( +21: _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid +22: || bytes(_symbol).length == 0 || bytes(_name).length == 0 +23: ) { +24: revert BTOKEN_INVALID_PARAMS(); +25: } +``` + +[[20-25](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L20-L25)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +81: if ( +82: block.timestamp > assignment.expiry +83: || assignment.metaHash != 0 && _blk.metaHash != assignment.metaHash +84: || assignment.parentMetaHash != 0 && _meta.parentMetaHash != assignment.parentMetaHash +85: || assignment.maxBlockId != 0 && _meta.id > assignment.maxBlockId +86: || assignment.maxProposedIn != 0 && block.number > assignment.maxProposedIn +87: ) { +88: revert HOOK_ASSIGNMENT_EXPIRED(); +89: } +``` + +[[81-89](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L81-L89)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +108: if (params.parentMetaHash != 0 && parentMetaHash != params.parentMetaHash) { +109: revert L1_UNEXPECTED_PARENT(); +110: } + +195: if (meta_.txListByteSize == 0 || meta_.txListByteSize > _config.blockMaxTxListBytes) { +196: revert L1_TXLIST_SIZE(); +197: } +``` + +[[108-110](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L108-L110), [195-197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L195-L197)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +105: if (_tran.parentHash == 0 || _tran.blockHash == 0 || _tran.stateRoot == 0) { +106: revert L1_INVALID_TRANSITION(); +107: } + +111: if (_meta.id <= b.lastVerifiedBlockId || _meta.id >= b.numBlocks) { +112: revert L1_INVALID_BLOCK_ID(); +113: } + +121: if (blk.blockId != _meta.id || blk.metaHash != keccak256(abi.encode(_meta))) { +122: revert L1_BLOCK_MISMATCH(); +123: } + +134: if (_proof.tier == 0 || _proof.tier < _meta.minTier || _proof.tier < ts.tier) { +135: revert L1_INVALID_TIER(); +136: } + +419: if (_tid == 1 && _ts.tier == 0 && inProvingWindow) { +420: if (!isAssignedPover) revert L1_NOT_ASSIGNED_PROVER(); +421: } else { +422: // Disallow the same address to prove the block so that we can detect that the +423: // assigned prover should not receive his liveness bond back +424: if (isAssignedPover) revert L1_ASSIGNED_PROVER_NOT_ALLOWED(); +425: } +``` + +[[105-107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L105-L107), [111-113](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L111-L113), [121-123](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L121-L123), [134-136](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L134-L136), [419-425](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L419-L425)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +34: if (_blockId < b.lastVerifiedBlockId || _blockId >= b.numBlocks) { +35: revert L1_INVALID_BLOCK_ID(); +36: } +``` + +[[34-36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L34-L36)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +63: if (_newGuardians.length < MIN_NUM_GUARDIANS || _newGuardians.length > type(uint8).max) { +64: revert INVALID_GUARDIAN_SET(); +65: } + +68: if (_minGuardians < (_newGuardians.length + 1) >> 1 || _minGuardians > _newGuardians.length) +69: { +70: revert INVALID_MIN_GUARDIANS(); +71: } +``` + +[[63-65](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L63-L65), [68-71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L68-L71)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +40: if (claimEnd > block.timestamp || claimEnd + withdrawalWindow < block.timestamp) { +41: revert WITHDRAWALS_NOT_ONGOING(); +42: } +``` + +[[40-42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L40-L42)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +34: if ( +35: merkleRoot == 0x0 || claimStart == 0 || claimEnd == 0 || claimStart > block.timestamp +36: || claimEnd < block.timestamp +37: ) revert CLAIM_NOT_ONGOING(); +``` + +[[34-37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L34-L37)] + +
+ +--- + +### [G-37] `abi.encode()` is less efficient than `abi.encodepacked()` for non-address arguments + +Consider refactoring the code by using `abi.encodepacked` instead of `abi.encode`, as the former is cheaper when used with non-address arguments. + +_There are 16 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +482: retData = abi.encodePacked(sha256(abi.encode(v3quote)), tcbStatus); +``` + +[[482](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L482)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +450: return keccak256(abi.encode("TAIKO_MESSAGE", _message)); +``` + +[[450](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L450)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +186: return keccak256(abi.encode(_chainId, _kind, _blockId)); +``` + +[[186](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L186)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +281: this.onMessageInvocation, abi.encode(ctoken_, _user, _op.to, _op.tokenIds, _op.amounts) +``` + +[[281](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L281)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +384: this.onMessageInvocation, abi.encode(ctoken_, _user, _to, balanceChange_) +``` + +[[384](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L384)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +217: this.onMessageInvocation, abi.encode(ctoken_, _user, _op.to, _op.tokenIds) +``` + +[[217](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L217)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +136: bytes memory args = abi.encode(sha256(tbs), r, s, gx, gy); +``` + +[[136](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L136)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +126: depositsHash: keccak256(abi.encode(deposits_)), + +213: metaHash: keccak256(abi.encode(meta_)), +``` + +[[126](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L126), [213](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L213)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +121: if (blk.blockId != _meta.id || blk.metaHash != keccak256(abi.encode(_meta))) { +``` + +[[121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L121)] + +```solidity +File: packages/protocol/contracts/L1/provers/GuardianProver.sol + +46: bytes32 hash = keccak256(abi.encode(_meta, _tran)); + +51: ITaikoL1(resolve("taiko", false)).proveBlock(_meta.id, abi.encode(_meta, _tran, _proof)); +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/GuardianProver.sol#L46), [51](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/GuardianProver.sol#L51)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +60: _verifyClaim(abi.encode(user, amount), proof); +``` + +[[60](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L60)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +80: _verifyClaim(abi.encode(user, amount), proof); +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L80)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +56: _verifyClaim(abi.encode(user, tokenIds), proof); +``` + +[[56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L56)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +68: bytes32 hash = keccak256(abi.encode("CLAIM_TAIKO_AIRDROP", data)); +``` + +[[68](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L68)] + +
+ +--- + +### [G-38] Unused named return variables without optimizer waste gas + +Consider changing the variable to be an unnamed one, since the variable is never assigned, nor is it returned by name. If the optimizer is not turned on, leaving the code as it is will also waste gas for the stack variable. + +_There are 20 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +// @audit bool valid +130: returns (bool valid) + +// @audit bool +178: returns (bool, EnclaveIdStruct.EnclaveIdStatus status) + +// @audit bool +212: returns (bool, TCBInfoStruct.TCBStatus status) +``` + +[[130](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L130), [178](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L178), [212](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L212)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +// @audit uint256 invocationDelay_, uint256 invocationExtraDelay_ +421: returns (uint256 invocationDelay_, uint256 invocationExtraDelay_) +``` + +[[421](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L421)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +// @audit address payable +37: returns (address payable) + +// @audit address payable +51: returns (address payable) +``` + +[[37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L37), [51](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L51)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +// @audit +52: returns (bool result_) +``` + +[[52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L52)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +// @audit +46: returns (bool success, bytes[] memory certs) + +// @audit +80: returns (bool success, ECSha256Certificate memory cert) + +// @audit bool success, bytes memory extracted, uint256 endIndex +219: returns (bool success, bytes memory extracted, uint256 endIndex) + +// @audit +258: returns (bytes memory output) + +// @audit uint256 pcesvn, uint256[] memory cpusvns +277: bool success, +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L46), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L80), [219](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L219), [258](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L258), [277](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L277)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +// @audit uint8 ret +188: function readUint8(bytes memory self, uint256 idx) internal pure returns (uint8 ret) { +``` + +[[188](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L188)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +// @audit bool sigValid +120: returns (bool sigValid) +``` + +[[120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L120)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +// @audit uint8 maxBlocksToVerify_ +100: returns (uint8 maxBlocksToVerify_) +``` + +[[100](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L100)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +// @audit +107: returns (uint256 balance, uint256 withdrawableAmount) +``` + +[[107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L107)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +// @audit +27: returns (bool success, V3Struct.ParsedV3QuoteStruct memory v3ParsedQuote) + +// @audit +168: returns (bool success, V3Struct.Header memory header) + +// @audit +209: returns (bool success, V3Struct.ECDSAQuoteV3AuthData memory authDataV3) +``` + +[[27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L27), [168](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L168), [209](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L209)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +// @audit uint256 offset_, uint256 length_, RLPItemType type_ +147: returns (uint256 offset_, uint256 length_, RLPItemType type_) +``` + +[[147](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L147)] + +
+ +--- + +### [G-39] Consider pre-calculating the address of `address(this)` to save gas + +Use Foundry's [`script.sol`](https://book.getfoundry.sh/reference/forge-std/compute-create-address) or Solady's [`LibRlp.sol`](https://github.com/Vectorized/solady/blob/main/src/utils/LibRLP.sol) to save the value in a constant, which will avoid having to spend gas to push the value on the stack every time it's used. + +_There are 40 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +174: if (!ISignalService(signalService).isSignalSent(address(this), msgHash)) { + +196: _storeContext(msgHash, address(this), _message.srcChainId); + +270: _message.to == address(0) || _message.to == address(this) + +343: _app: address(this), + +486: assert(_message.from != address(this)); +``` + +[[174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L174), [196](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L196), [270](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L270), [343](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L343), [486](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L486)] + +```solidity +File: packages/protocol/contracts/L1/TaikoToken.sol + +61: if (_to == address(this)) revert TKO_INVALID_ADDR(); + +79: if (_to == address(this)) revert TKO_INVALID_ADDR(); +``` + +[[61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L61), [79](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L79)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +50: (bool success,) = address(this).call(txdata); +``` + +[[50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L50)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +174: _to.sendEther(address(this).balance); + +176: IERC20(_token).safeTransfer(_to, IERC20(_token).balanceOf(address(this))); +``` + +[[174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L174), [176](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L176)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +112: signalService = address(this); + +131: if (value == 0 || value != _loadSignalValue(address(this), signal)) { + +149: return _loadSignalValue(address(this), signal) == _chainData; + +171: chainData_ = _loadSignalValue(address(this), signal); + +245: _sendSignal(address(this), signal_, _chainData); +``` + +[[112](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L112), [131](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L131), [149](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L149), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L171), [245](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L245)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +137: if (_to == address(this)) revert BTOKEN_CANNOT_RECEIVE(); +``` + +[[137](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L137)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +147: if (_to == address(this)) revert BTOKEN_CANNOT_RECEIVE(); +``` + +[[147](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L147)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +125: if (_to == address(this)) revert BTOKEN_CANNOT_RECEIVE(); +``` + +[[125](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L125)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +108: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +226: IERC1155(token).safeBatchTransferFrom(address(this), to, tokenIds, amounts, ""); + +272: to: address(this), +``` + +[[108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L108), [226](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L226), [272](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L272)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +267: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +378: uint256 _balance = t.balanceOf(address(this)); + +379: t.safeTransferFrom({ from: msg.sender, to: address(this), value: _amount }); + +380: balanceChange_ = t.balanceOf(address(this)) - _balance; +``` + +[[267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L267), [378](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L378), [379](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L379), [380](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L380)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +91: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +171: IERC721(token_).safeTransferFrom(address(this), _to, _tokenIds[i]); + +211: t.safeTransferFrom(_user, address(this), _op.tokenIds[i]); +``` + +[[91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L91), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L171), [211](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L211)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +186: address(this), +``` + +[[186](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L186)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +125: if (address(this).balance > 0) { + +126: taikoL1Address.sendEther(address(this).balance); + +151: address(this), +``` + +[[125](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L125), [126](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L126), [151](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L151)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +238: uint256 tkoBalance = tko.balanceOf(address(this)); + +253: IHook(params.hookCalls[i].hook).onBlockProposed{ value: address(this).balance }( + +260: if (address(this).balance != 0) { + +261: msg.sender.sendEther(address(this).balance); + +268: if (tko.balanceOf(address(this)) != tkoBalance + _config.livenessBond) { +``` + +[[238](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L238), [253](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L253), [260](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L260), [261](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L261), [268](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L268)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +242: tko.transferFrom(msg.sender, address(this), tier.contestBond); + +384: _tko.transferFrom(msg.sender, address(this), _tier.validityBond - reward); +``` + +[[242](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L242), [384](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L384)] + +```solidity +File: packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol + +48: usdc.transferFrom(_from, address(this), _amount); +``` + +[[48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L48)] + +
+ +--- + +### [G-40] Consider using Solady's `FixedPointMathLib` + +Saves gas, and works to avoid unnecessary [overflows](https://github.com/Vectorized/solady/blob/6cce088e69d6e46671f2f622318102bd5db77a65/src/utils/FixedPointMathLib.sol#L267). + +_There are 4 instances of this issue._ + +```solidity +File: packages/protocol/contracts/L2/Lib1559Math.sol + +41: uint256 input = _gasExcess * LibFixedPointMath.SCALING_FACTOR / _adjustmentFactor; +``` + +[[41](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L41)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +264: return _amount * uint64(block.timestamp - _start) / _period; +``` + +[[264](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L264)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +247: _config.chainId <= 1 || _config.chainId == block.chainid // +248: || _config.blockMaxProposals == 1 +249: || _config.blockRingBufferSize <= _config.blockMaxProposals + 1 +250: || _config.blockMaxGasLimit == 0 || _config.blockMaxTxListBytes == 0 +251: || _config.blockMaxTxListBytes > 128 * 1024 // calldata up to 128K +252: || _config.livenessBond == 0 || _config.ethDepositRingBufferSize <= 1 +253: || _config.ethDepositMinCountPerBlock == 0 +254: // Audit recommendation, and gas tested. Processing 32 deposits (as initially set in +255: // TaikoL1.sol) costs 72_502 gas. +256: || _config.ethDepositMaxCountPerBlock > 32 +257: || _config.ethDepositMaxCountPerBlock < _config.ethDepositMinCountPerBlock +258: || _config.ethDepositMinAmount == 0 +259: || _config.ethDepositMaxAmount <= _config.ethDepositMinAmount +260: || _config.ethDepositMaxAmount > type(uint96).max || _config.ethDepositGas == 0 +261: || _config.ethDepositMaxFee == 0 +262: || _config.ethDepositMaxFee > type(uint96).max / _config.ethDepositMaxCountPerBlock +``` + +[[247-262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L247-L262)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +117: uint256 timeBasedAllowance = balance +118: * (block.timestamp.min(claimEnd + withdrawalWindow) - claimEnd) / withdrawalWindow; +``` + +[[117-118](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L117-L118)] + +--- + +### [G-41] Reduce deployment costs by tweaking contracts' metadata + +When solidity generates the bytecode for the smart contract to be deployed, it appends metadata about the compilation at the end of the bytecode. + +By default, the solidity compiler appends metadata at the end of the “actual” initcode, which gets stored to the blockchain when the constructor finishes executing. + +Consider tweaking the metadata to avoid this unnecessary allocation. A full guide can be found [here](https://www.rareskills.io/post/solidity-metadata). + +_There are 86 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +22: contract AutomataDcapV3Attestation is IAttestation { +``` + +[[22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L22)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +16: contract Bridge is EssentialContract, IBridge { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L16)] + +```solidity +File: packages/protocol/contracts/bridge/IBridge.sol + +8: interface IBridge { + +160: interface IRecallableSender { + +174: interface IMessageInvocable { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L8), [160](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L160), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L174)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +10: contract AddressManager is EssentialContract, IAddressManager { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L10)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +11: abstract contract AddressResolver is IAddressResolver, Initializable { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L11)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +10: abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, AddressResolver { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L10)] + +```solidity +File: packages/protocol/contracts/common/IAddressManager.sol + +7: interface IAddressManager { +``` + +[[7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/IAddressManager.sol#L7)] + +```solidity +File: packages/protocol/contracts/common/IAddressResolver.sol + +13: interface IAddressResolver { +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/IAddressResolver.sol#L13)] + +```solidity +File: packages/protocol/contracts/L1/ITaikoL1.sol + +8: interface ITaikoL1 { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/ITaikoL1.sol#L8)] + +```solidity +File: packages/protocol/contracts/L1/TaikoData.sol + +8: library TaikoData { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoData.sol#L8)] + +```solidity +File: packages/protocol/contracts/L1/TaikoErrors.sol + +11: abstract contract TaikoErrors { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoErrors.sol#L11)] + +```solidity +File: packages/protocol/contracts/L1/TaikoEvents.sol + +13: abstract contract TaikoEvents { +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoEvents.sol#L13)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +22: contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents, TaikoErrors { +``` + +[[22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L22)] + +```solidity +File: packages/protocol/contracts/L1/TaikoToken.sol + +15: contract TaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUpgradeable { +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L15)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +14: abstract contract CrossChainOwned is EssentialContract, IMessageInvocable { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L14)] + +```solidity +File: packages/protocol/contracts/L2/Lib1559Math.sol + +10: library Lib1559Math { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L10)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +21: contract TaikoL2 is CrossChainOwned { +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L21)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +9: contract TaikoL2EIP1559Configurable is TaikoL2 { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L9)] + +```solidity +File: packages/protocol/contracts/libs/Lib4844.sol + +8: library Lib4844 { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L8)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +13: library LibAddress { +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L13)] + +```solidity +File: packages/protocol/contracts/libs/LibMath.sol + +7: library LibMath { +``` + +[[7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibMath.sol#L7)] + +```solidity +File: packages/protocol/contracts/libs/LibTrieProof.sol + +15: library LibTrieProof { +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L15)] + +```solidity +File: packages/protocol/contracts/signal/ISignalService.sol + +12: interface ISignalService { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L12)] + +```solidity +File: packages/protocol/contracts/signal/LibSignals.sol + +6: library LibSignals { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/LibSignals.sol#L6)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +14: contract SignalService is EssentialContract, ISignalService { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L14)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +25: contract TimelockTokenPool is EssentialContract { +``` + +[[25](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L25)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +9: abstract contract BaseNFTVault is BaseVault { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L9)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseVault.sol + +12: abstract contract BaseVault is +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L12)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +14: contract BridgedERC1155 is EssentialContract, IERC1155MetadataURIUpgradeable, ERC1155Upgradeable { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L14)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +15: contract BridgedERC20 is +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L15)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +9: abstract contract BridgedERC20Base is EssentialContract, IBridgedERC20 { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L9)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +12: contract BridgedERC721 is EssentialContract, ERC721Upgradeable { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L12)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +16: interface IERC1155NameAndSymbol { + +29: contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L16), [29](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L29)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +18: contract ERC20Vault is BaseVault { +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L18)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +16: contract ERC721Vault is BaseNFTVault, IERC721Receiver { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L16)] + +```solidity +File: packages/protocol/contracts/tokenvault/IBridgedERC20.sol + +10: interface IBridgedERC20 { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/IBridgedERC20.sol#L10)] + +```solidity +File: packages/protocol/contracts/tokenvault/LibBridgedToken.sol + +8: library LibBridgedToken { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L8)] + +```solidity +File: packages/protocol/contracts/verifiers/GuardianVerifier.sol + +10: contract GuardianVerifier is EssentialContract, IVerifier { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/GuardianVerifier.sol#L10)] + +```solidity +File: packages/protocol/contracts/verifiers/IVerifier.sol + +9: interface IVerifier { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/IVerifier.sol#L9)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +19: contract SgxVerifier is EssentialContract, IVerifier { +``` + +[[19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L19)] + +```solidity +File: packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol + +8: interface IAttestation { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol#L8)] + +```solidity +File: packages/protocol/contracts/automata-attestation/interfaces/ISigVerifyLib.sol + +6: interface ISigVerifyLib { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/interfaces/ISigVerifyLib.sol#L6)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol + +6: library EnclaveIdStruct { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol#L6)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +12: contract PEMCertChainLib is IPEMCertChainLib { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L12)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/TCBInfoStruct.sol + +6: library TCBInfoStruct { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/TCBInfoStruct.sol#L6)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol + +12: library NodePtr { + +38: library Asn1Decode { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L12), [38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol#L38)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +8: library BytesUtils { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L8)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +34: library RsaVerify { +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L34)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SHA1.sol + +10: library SHA1 { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SHA1.sol#L10)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +15: contract SigVerifyLib is ISigVerifyLib { +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L15)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +7: library X509DateUtils { +``` + +[[7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L7)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoGovernor.sol + +16: contract TaikoGovernor is +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L16)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoTimelockController.sol + +9: contract TaikoTimelockController is EssentialContract, TimelockControllerUpgradeable { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol#L9)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +14: contract AssignmentHook is EssentialContract, IHook { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L14)] + +```solidity +File: packages/protocol/contracts/L1/hooks/IHook.sol + +8: interface IHook { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/IHook.sol#L8)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +12: library LibDepositing { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L12)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +15: library LibProposing { +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L15)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +16: library LibProving { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L16)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +9: library LibUtils { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L9)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +16: library LibVerifying { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L16)] + +```solidity +File: packages/protocol/contracts/L1/provers/GuardianProver.sol + +10: contract GuardianProver is Guardians { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/GuardianProver.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +9: abstract contract Guardians is EssentialContract { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L9)] + +```solidity +File: packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol + +10: contract DevnetTierProvider is EssentialContract, ITierProvider { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/tiers/ITierProvider.sol + +7: interface ITierProvider { + +37: library LibTiers { +``` + +[[7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L7), [37](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L37)] + +```solidity +File: packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol + +10: contract MainnetTierProvider is EssentialContract, ITierProvider { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol + +10: contract TestnetTierProvider is EssentialContract, ITierProvider { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol#L10)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +11: contract ERC20Airdrop is MerkleClaimable { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L11)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +12: contract ERC20Airdrop2 is MerkleClaimable { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L12)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +9: contract ERC721Airdrop is MerkleClaimable { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L9)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +10: abstract contract MerkleClaimable is EssentialContract { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L10)] + +```solidity +File: packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol + +5: library ExcessivelySafeCall { +``` + +[[5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol#L5)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/Bytes.sol + +6: library Bytes { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/Bytes.sol#L6)] + +```solidity +File: packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol + +8: interface IUSDC { + +28: contract USDCAdapter is BridgedERC20Base { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L8), [28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L28)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/interfaces/IPEMCertChainLib.sol + +6: interface IPEMCertChainLib { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/interfaces/IPEMCertChainLib.sol#L6)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +11: library V3Parser { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L11)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol + +6: library V3Struct { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol#L6)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +9: library RLPReader { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L9)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +9: library RLPWriter { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L9)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +11: library MerkleTrie { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L11)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol + +9: library SecureMerkleTrie { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol#L9)] + +
+ +--- + +### [G-42] Emitting constants wastes gas + +Every event parameter costs `Glogdata` (**8 gas**) per byte. You can avoid this extra cost, in cases where you're emitting a constant, by creating a second version of the event, which doesn't have the parameter (and have users look to the contract's variables for its value instead), and using the new event in the cases shown below. + +_There are 4 instances of this issue._ + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +// @audit true +210: emit MessageReceived(msgHash, _message, true); + +// @audit false +303: emit MessageReceived(msgHash, _message, false); +``` + +[[210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L210), [303](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L303)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +// @audit 0 +230: emit TransitionProved({ +231: blockId: blk.blockId, +232: tran: _tran, +233: prover: msg.sender, +234: validityBond: 0, +235: tier: _proof.tier +236: }); +``` + +[[230-236](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L230-L236)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +// @audit 0, 0, 0, 0 +73: emit BlockVerified({ +74: blockId: 0, +75: assignedProver: address(0), +76: prover: address(0), +77: blockHash: _genesisBlockHash, +78: stateRoot: 0, +79: tier: 0, +80: contestations: 0 +81: }); +``` + +[[73-81](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L73-L81)] + +--- + +### [G-43] Update OpenZeppelin dependency to save gas + +Every release contains new gas optimizations, use the latest version to take advantage of this. + +_There are 54 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +4: import "@openzeppelin/contracts/utils/Address.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L4)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +4: import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L4)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +4: import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; + +5: import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L5)] + +```solidity +File: packages/protocol/contracts/L1/TaikoToken.sol + +4: import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol"; + +5: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol"; + +6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L5), [6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L6)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L4)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L5)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +4: import "@openzeppelin/contracts/utils/Address.sol"; + +5: import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +6: import "@openzeppelin/contracts/utils/introspection/IERC165.sol"; + +7: import "@openzeppelin/contracts/interfaces/IERC1271.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L5), [6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L6), [7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L7)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +4: import "@openzeppelin/contracts/utils/math/SafeCast.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L4)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +4: import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; + +5: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +6: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L5), [6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L6)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseVault.sol + +4: import "@openzeppelin/contracts-upgradeable/utils/introspection/IERC165Upgradeable.sol"; + +5: import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L5)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +4: import "@openzeppelin/contracts/utils/Strings.sol"; + +5: import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; + +6: import +7: "@openzeppelin/contracts-upgradeable/token/ERC1155/extensions/IERC1155MetadataURIUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L5), [6-7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L6-L7)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +4: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; + +5: import "@openzeppelin/contracts/utils/Strings.sol"; + +6: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20SnapshotUpgradeable.sol"; + +7: import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L5), [6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L6), [7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L7)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +4: import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; + +5: import "@openzeppelin/contracts/utils/Strings.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L5)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +4: import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; + +5: import "@openzeppelin/contracts-upgradeable/token/ERC1155/utils/ERC1155ReceiverUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L5)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +5: import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; + +6: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L5), [6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L6)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +4: import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; + +5: import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L5)] + +```solidity +File: packages/protocol/contracts/tokenvault/LibBridgedToken.sol + +4: import "@openzeppelin/contracts/utils/Strings.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L4)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +4: import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L4)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoGovernor.sol + +4: import "@openzeppelin/contracts-upgradeable/governance/GovernorUpgradeable.sol"; + +5: import +6: "@openzeppelin/contracts-upgradeable/governance/compatibility/GovernorCompatibilityBravoUpgradeable.sol"; + +7: import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesUpgradeable.sol"; + +8: import +9: "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesQuorumFractionUpgradeable.sol"; + +10: import +11: "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorTimelockControlUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L4), [5-6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L5-L6), [7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L7), [8-9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L8-L9), [10-11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L10-L11)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoTimelockController.sol + +4: import "@openzeppelin/contracts-upgradeable/governance/TimelockControllerUpgradeable.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol#L4)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +5: import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L5)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L4)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L4)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L4)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +5: import "@openzeppelin/contracts/governance/utils/IVotes.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L4), [5](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L5)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +4: import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L4)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +4: import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L4)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +4: import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; +``` + +[[4](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L4)] + +
+ +--- + +### [G-44] Function names can be optimized + +Function that are `public`/`external` and `public` state variable names can be optimized to save gas. + +Method IDs that have two leading zero bytes can save **128 gas** each during deployment, and renaming functions to have lower method IDs will save **22 gas** per call, per sorted position shifted. [Reference](https://blog.emn178.cc/en/post/solidity-gas-optimization-function-name/) + +_There are 56 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +22: contract AutomataDcapV3Attestation is IAttestation { +``` + +[[22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L22)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +16: contract Bridge is EssentialContract, IBridge { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L16)] + +```solidity +File: packages/protocol/contracts/bridge/IBridge.sol + +8: interface IBridge { + +160: interface IRecallableSender { + +174: interface IMessageInvocable { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L8), [160](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L160), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/IBridge.sol#L174)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +10: contract AddressManager is EssentialContract, IAddressManager { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L10)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +11: abstract contract AddressResolver is IAddressResolver, Initializable { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L11)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +10: abstract contract EssentialContract is UUPSUpgradeable, Ownable2StepUpgradeable, AddressResolver { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L10)] + +```solidity +File: packages/protocol/contracts/common/IAddressManager.sol + +7: interface IAddressManager { +``` + +[[7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/IAddressManager.sol#L7)] + +```solidity +File: packages/protocol/contracts/common/IAddressResolver.sol + +13: interface IAddressResolver { +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/IAddressResolver.sol#L13)] + +```solidity +File: packages/protocol/contracts/L1/ITaikoL1.sol + +8: interface ITaikoL1 { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/ITaikoL1.sol#L8)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +22: contract TaikoL1 is EssentialContract, ITaikoL1, TaikoEvents, TaikoErrors { +``` + +[[22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L22)] + +```solidity +File: packages/protocol/contracts/L1/TaikoToken.sol + +15: contract TaikoToken is EssentialContract, ERC20SnapshotUpgradeable, ERC20VotesUpgradeable { +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L15)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +14: abstract contract CrossChainOwned is EssentialContract, IMessageInvocable { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L14)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +21: contract TaikoL2 is CrossChainOwned { +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L21)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +9: contract TaikoL2EIP1559Configurable is TaikoL2 { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L9)] + +```solidity +File: packages/protocol/contracts/signal/ISignalService.sol + +12: interface ISignalService { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/ISignalService.sol#L12)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +14: contract SignalService is EssentialContract, ISignalService { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L14)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +25: contract TimelockTokenPool is EssentialContract { +``` + +[[25](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L25)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseVault.sol + +12: abstract contract BaseVault is +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L12)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +14: contract BridgedERC1155 is EssentialContract, IERC1155MetadataURIUpgradeable, ERC1155Upgradeable { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L14)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +15: contract BridgedERC20 is +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L15)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +9: abstract contract BridgedERC20Base is EssentialContract, IBridgedERC20 { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L9)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +12: contract BridgedERC721 is EssentialContract, ERC721Upgradeable { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L12)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +16: interface IERC1155NameAndSymbol { + +29: contract ERC1155Vault is BaseNFTVault, ERC1155ReceiverUpgradeable { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L16), [29](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L29)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +18: contract ERC20Vault is BaseVault { +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L18)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +16: contract ERC721Vault is BaseNFTVault, IERC721Receiver { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L16)] + +```solidity +File: packages/protocol/contracts/tokenvault/IBridgedERC20.sol + +10: interface IBridgedERC20 { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/IBridgedERC20.sol#L10)] + +```solidity +File: packages/protocol/contracts/verifiers/GuardianVerifier.sol + +10: contract GuardianVerifier is EssentialContract, IVerifier { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/GuardianVerifier.sol#L10)] + +```solidity +File: packages/protocol/contracts/verifiers/IVerifier.sol + +9: interface IVerifier { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/IVerifier.sol#L9)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +19: contract SgxVerifier is EssentialContract, IVerifier { +``` + +[[19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L19)] + +```solidity +File: packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol + +8: interface IAttestation { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol#L8)] + +```solidity +File: packages/protocol/contracts/automata-attestation/interfaces/ISigVerifyLib.sol + +6: interface ISigVerifyLib { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/interfaces/ISigVerifyLib.sol#L6)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +12: contract PEMCertChainLib is IPEMCertChainLib { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L12)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +15: contract SigVerifyLib is ISigVerifyLib { +``` + +[[15](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L15)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoGovernor.sol + +16: contract TaikoGovernor is +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L16)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoTimelockController.sol + +9: contract TaikoTimelockController is EssentialContract, TimelockControllerUpgradeable { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol#L9)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +14: contract AssignmentHook is EssentialContract, IHook { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L14)] + +```solidity +File: packages/protocol/contracts/L1/hooks/IHook.sol + +8: interface IHook { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/IHook.sol#L8)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +16: library LibProving { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L16)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibUtils.sol + +9: library LibUtils { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibUtils.sol#L9)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +16: library LibVerifying { +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L16)] + +```solidity +File: packages/protocol/contracts/L1/provers/GuardianProver.sol + +10: contract GuardianProver is Guardians { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/GuardianProver.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +9: abstract contract Guardians is EssentialContract { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L9)] + +```solidity +File: packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol + +10: contract DevnetTierProvider is EssentialContract, ITierProvider { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/tiers/ITierProvider.sol + +7: interface ITierProvider { +``` + +[[7](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/ITierProvider.sol#L7)] + +```solidity +File: packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol + +10: contract MainnetTierProvider is EssentialContract, ITierProvider { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol + +10: contract TestnetTierProvider is EssentialContract, ITierProvider { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol#L10)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +11: contract ERC20Airdrop is MerkleClaimable { +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L11)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +12: contract ERC20Airdrop2 is MerkleClaimable { +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L12)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +9: contract ERC721Airdrop is MerkleClaimable { +``` + +[[9](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L9)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +10: abstract contract MerkleClaimable is EssentialContract { +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L10)] + +```solidity +File: packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol + +8: interface IUSDC { + +28: contract USDCAdapter is BridgedERC20Base { +``` + +[[8](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L8), [28](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L28)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/interfaces/IPEMCertChainLib.sol + +6: interface IPEMCertChainLib { +``` + +[[6](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/interfaces/IPEMCertChainLib.sol#L6)] + +
+ +--- + +### [G-45] Avoid zero transfers calls + +Emit any transfer events if the EIP requires it, but avoid doing the actual call when the amount is zero. + +_There are 10 instances of this issue._ + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +219: IERC20(taikoToken).transferFrom(sharedVault, _to, amountToWithdraw); +``` + +[[219](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L219)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +196: tko.transfer(blk.assignedProver, blk.livenessBond); + +242: tko.transferFrom(msg.sender, address(this), tier.contestBond); + +367: _tko.transfer(_ts.prover, _ts.validityBond + reward); + +371: _tko.transfer(_ts.contester, _ts.contestBond + reward); + +382: _tko.transfer(msg.sender, reward - _tier.validityBond); + +384: _tko.transferFrom(msg.sender, address(this), _tier.validityBond - reward); +``` + +[[196](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L196), [242](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L242), [367](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L367), [371](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L371), [382](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L382), [384](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L384)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +189: tko.transfer(ts.prover, bondToReturn); +``` + +[[189](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L189)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +63: IERC20(token).transferFrom(vault, user, amount); +``` + +[[63](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L63)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +91: IERC20(token).transferFrom(vault, user, amount); +``` + +[[91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L91)] + +--- + +### [G-46] Using `delete` instead of setting mapping/struct to 0 saves gas + +Avoid an assignment by deleting the value instead of setting it to zero, as it's [cheaper](https://gist.github.com/DadeKuma/ea874815202fc77e9d81f81a047c1e5e). + +_There are 10 instances of this issue._ + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +231: _grant.grantStart = 0; + +232: _grant.grantPeriod = 0; +``` + +[[231](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L231), [232](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L232)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +336: tbsPtr = 0; // exit +``` + +[[336](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L336)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +190: meta_.txListByteOffset = 0; +``` + +[[190](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L190)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +197: blk.livenessBond = 0; + +300: ts_.blockHash = 0; + +301: ts_.stateRoot = 0; + +302: ts_.validityBond = 0; + +306: ts_.tier = 0; + +307: ts_.contestations = 0; +``` + +[[197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L197), [300](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L300), [301](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L301), [302](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L302), [306](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L306), [307](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L307)] + +--- + +### [G-47] Using `bool` for storage incurs overhead + +Booleans are more expensive than `uint256` or any type that takes up a full word because each write operation emits an extra SLOAD to first read the slot's contents, replace the bits taken up by the boolean, and then write back. + +This is the compiler's defense against contract upgrades and pointer aliasing, and it cannot be disabled. Use `uint256(0) and uint256(1)` for `true/false` to avoid a Gwarmaccess (**100 gas**) for the extra `SLOAD`. + +_There are 10 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +38: bool private _checkLocalEnclaveReport; + +39: mapping(bytes32 enclave => bool trusted) private _trustedUserMrEnclave; + +40: mapping(bytes32 signer => bool trusted) private _trustedUserMrSigner; + +47: mapping(uint256 idx => mapping(bytes serialNum => bool revoked)) private _serialNumIsRevoked; +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L38), [39](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L39), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L40), [47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L47)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +42: mapping(address addr => bool banned) public addressBanned; +``` + +[[42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L42)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +21: mapping(address addr => bool authorized) public isAuthorized; +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L21)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +14: bool public migratingInbound; +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L14)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +52: mapping(address btoken => bool blacklisted) public btokenBlacklist; +``` + +[[52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L52)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +55: mapping(address instanceAddress => bool alreadyAttested) public addressRegistered; +``` + +[[55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L55)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +12: mapping(bytes32 hash => bool claimed) public isClaimed; +``` + +[[12](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L12)] + +
+ +--- + +### [G-48] Mappings are cheaper to use than storage arrays + +When using storage arrays, solidity adds an internal lookup of the array's length (a **Gcoldsload 2100 gas**) to ensure you don't read past the array's end. + +You can avoid this lookup by using a mapping and storing the number of entries in a separate storage variable. In cases where you have sentinel values (e.g. 'zero' means invalid), you can avoid length checks. + +_There are 36 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +48: uint256[43] private __gap; +``` + +[[48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L48)] + +```solidity +File: packages/protocol/contracts/common/AddressManager.sol + +14: uint256[49] private __gap; +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressManager.sol#L14)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +14: uint256[49] private __gap; +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L14)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +25: uint256[49] private __gap; +``` + +[[25](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L25)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +26: uint256[50] private __gap; +``` + +[[26](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L26)] + +```solidity +File: packages/protocol/contracts/L1/TaikoToken.sol + +16: uint256[50] private __gap; +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoToken.sol#L16)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +21: uint256[49] private __gap; +``` + +[[21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L21)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +52: uint256[47] private __gap; +``` + +[[52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L52)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol + +13: uint256[49] private __gap; +``` + +[[13](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol#L13)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +23: uint256[48] private __gap; +``` + +[[23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L23)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +82: uint128[44] private __gap; +``` + +[[82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L82)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +61: uint256[48] private __gap; +``` + +[[61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L61)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseVault.sol + +18: uint256[50] private __gap; +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L18)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +27: uint256[46] private __gap; +``` + +[[27](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L27)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +32: uint256[47] private __gap; +``` + +[[32](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L32)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +16: uint256[49] private __gap; +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L16)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +19: uint256[48] private __gap; +``` + +[[19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L19)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +32: uint256[50] private __gap; +``` + +[[32](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L32)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +54: uint256[47] private __gap; +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L54)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +19: uint256[50] private __gap; +``` + +[[19](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L19)] + +```solidity +File: packages/protocol/contracts/verifiers/GuardianVerifier.sol + +11: uint256[50] private __gap; +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/GuardianVerifier.sol#L11)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +57: uint256[47] private __gap; +``` + +[[57](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L57)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoGovernor.sol + +23: uint256[50] private __gap; +``` + +[[23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoGovernor.sol#L23)] + +```solidity +File: packages/protocol/contracts/L1/gov/TaikoTimelockController.sol + +10: uint256[50] private __gap; +``` + +[[10](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol#L10)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +40: uint256[50] private __gap; +``` + +[[40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L40)] + +```solidity +File: packages/protocol/contracts/L1/provers/GuardianProver.sol + +11: uint256[50] private __gap; +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/GuardianProver.sol#L11)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +23: address[] public guardians; + +32: uint256[46] private __gap; +``` + +[[23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L23), [32](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L32)] + +```solidity +File: packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol + +11: uint256[50] private __gap; +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol#L11)] + +```solidity +File: packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol + +11: uint256[50] private __gap; +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol#L11)] + +```solidity +File: packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol + +11: uint256[50] private __gap; +``` + +[[11](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol#L11)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol + +18: uint256[48] private __gap; +``` + +[[18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol#L18)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol + +30: uint256[45] private __gap; +``` + +[[30](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol#L30)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +16: uint256[48] private __gap; +``` + +[[16](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L16)] + +```solidity +File: packages/protocol/contracts/team/airdrop/MerkleClaimable.sol + +23: uint256[47] private __gap; +``` + +[[23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol#L23)] + +```solidity +File: packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol + +32: uint256[49] private __gap; +``` + +[[32](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol#L32)] + +
+ +--- + +### [G-49] Bytes constants are more efficient than string constants + +If a string can fit in 32 bytes is it better to use `bytes32` instead of `string`, as it is cheaper. + +```solidity +// @audit avoid this +string constant stringVariable = "LessThan32Bytes"; + +// @audit as this is cheaper +bytes32 constant stringVariable = "LessThan32Bytes"; +``` + +_There are 5 instances of this issue._ + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +17: string internal constant HEADER = "-----BEGIN CERTIFICATE-----"; + +18: string internal constant FOOTER = "-----END CERTIFICATE-----"; + +22: string internal constant PCK_COMMON_NAME = "Intel SGX PCK Certificate"; + +23: string internal constant PLATFORM_ISSUER_NAME = "Intel SGX PCK Platform CA"; + +24: string internal constant PROCESSOR_ISSUER_NAME = "Intel SGX PCK Processor CA"; +``` + +[[17](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L17), [18](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L18), [22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L22), [23](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L23), [24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L24)] + +--- + +### [G-50] Constructors can be marked `payable` + +`payable` functions cost less gas to execute, since the compiler does not have to add extra checks to ensure that a payment wasn't provided. + +A `constructor` can safely be marked as `payable`, since only the deployer would be able to pass funds, and the project itself would not pass any funds. + +_There are 3 instances of this issue._ + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +54: constructor(address sigVerifyLibAddr, address pemCertLibAddr) { +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L54)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +64: constructor() { +``` + +[[64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L64)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol + +20: constructor(address es256Verifier) { +``` + +[[20](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol#L20)] + +--- + +### [G-51] Inverting the `if` condition wastes gas + +Flipping the `true` and `false` blocks instead saves 3 gas. + +_There are 2 instances of this issue._ + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +209: } else if (!isMessageProven) { +210: emit MessageReceived(msgHash, _message, true); +211: } else { +212: revert B_INVOCATION_TOO_EARLY(); +213: } + +302: } else if (!isMessageProven) { +303: emit MessageReceived(msgHash, _message, false); +304: } else { +305: revert B_INVOCATION_TOO_EARLY(); +306: } +``` + +[[209-213](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L209-L213), [302-306](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L302-L306)] + +--- + +### [G-52] Long revert strings + +Considering refactoring the revert message to fit in 32 bytes to avoid using more than one memory slot. + +_There are 27 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +87: require( +88: v3Quote.v3AuthData.certification.certType == 5, +89: "certType must be 5: Concatenated PCK Cert Chain (PEM formatted)" +90: ); +``` + +[[87-90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L87-L90)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +37: require( +38: _in.length > 0, +39: "RLPReader: length of an RLP item must be greater than zero to be decodable" +40: ); + +56: require( +57: itemType == RLPItemType.LIST_ITEM, +58: "RLPReader: decoded item type for list is not a list item" +59: ); + +61: require( +62: listOffset + listLength == _in.length, +63: "RLPReader: list item has an invalid data remainder" +64: ); + +112: require( +113: itemType == RLPItemType.DATA_ITEM, +114: "RLPReader: decoded item type for bytes is not a data item" +115: ); + +117: require( +118: _in.length == itemOffset + itemLength, +119: "RLPReader: bytes value contains an invalid remainder" +120: ); + +152: require( +153: _in.length > 0, +154: "RLPReader: length of an RLP item must be greater than zero to be decodable" +155: ); + +172: require( +173: _in.length > strLen, +174: "RLPReader: length of content must be greater than string length (short string)" +175: ); + +182: require( +183: strLen != 1 || firstByteOfContent >= 0x80, +184: "RLPReader: invalid prefix, single byte < 0x80 are not prefixed (short string)" +185: ); + +192: require( +193: _in.length > lenOfStrLen, +194: "RLPReader: length of content must be > than length of string length (long string)" +195: ); + +202: require( +203: firstByteOfContent != 0x00, +204: "RLPReader: length of content must not have any leading zeros (long string)" +205: ); + +212: require( +213: strLen > 55, +214: "RLPReader: length of content must be greater than 55 bytes (long string)" +215: ); + +217: require( +218: _in.length > lenOfStrLen + strLen, +219: "RLPReader: length of content must be greater than total length (long string)" +220: ); + +228: require( +229: _in.length > listLen, +230: "RLPReader: length of content must be greater than list length (short list)" +231: ); + +238: require( +239: _in.length > lenOfListLen, +240: "RLPReader: length of content must be > than length of list length (long list)" +241: ); + +248: require( +249: firstByteOfContent != 0x00, +250: "RLPReader: length of content must not have any leading zeros (long list)" +251: ); + +258: require( +259: listLen > 55, +260: "RLPReader: length of content must be greater than 55 bytes (long list)" +261: ); + +263: require( +264: _in.length > lenOfListLen + listLen, +265: "RLPReader: length of content must be greater than total length (long list)" +266: ); +``` + +[[37-40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L37-L40), [56-59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L56-L59), [61-64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L61-L64), [112-115](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L112-L115), [117-120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L117-L120), [152-155](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L152-L155), [172-175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L172-L175), [182-185](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L182-L185), [192-195](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L192-L195), [202-205](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L202-L205), [212-215](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L212-L215), [217-220](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L217-L220), [228-231](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L228-L231), [238-241](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L238-L241), [248-251](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L248-L251), [258-261](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L258-L261), [263-266](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L263-L266)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +89: require(currentKeyIndex <= key.length, "MerkleTrie: key index exceeds total key length"); + +99: require( +100: Bytes.equal(abi.encodePacked(keccak256(currentNode.encoded)), currentNodeID), +101: "MerkleTrie: invalid large internal hash" +102: ); + +105: require( +106: Bytes.equal(currentNode.encoded, currentNodeID), +107: "MerkleTrie: invalid internal node hash" +108: ); + +119: require( +120: value_.length > 0, +121: "MerkleTrie: value length must be greater than zero (branch)" +122: ); + +125: require( +126: i == proof.length - 1, +127: "MerkleTrie: value node must be last node in proof (branch)" +128: ); + +150: require( +151: pathRemainder.length == sharedNibbleLength, +152: "MerkleTrie: path remainder must share all nibbles with key" +153: ); + +162: require( +163: keyRemainder.length == sharedNibbleLength, +164: "MerkleTrie: key remainder must be identical to path remainder" +165: ); + +172: require( +173: value_.length > 0, +174: "MerkleTrie: value length must be greater than zero (leaf)" +175: ); + +178: require( +179: i == proof.length - 1, +180: "MerkleTrie: value node must be last node in proof (leaf)" +181: ); +``` + +[[89](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L89), [99-102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L99-L102), [105-108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L105-L108), [119-122](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L119-L122), [125-128](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L125-L128), [150-153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L150-L153), [162-165](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L162-L165), [172-175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L172-L175), [178-181](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L178-L181)] + +
+ +--- + +### [G-53] Nesting `if` statements that use `&&` saves gas + +Using the `&&` operator on a single `if` [costs more gas](https://gist.github.com/DadeKuma/931ce6794a050201ec6544dbcc31316c) than using two nested `if`. + +_There are 23 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +220: if (pceSvnIsHigherOrGreater && cpuSvnsAreHigherOrGreater) { +``` + +[[220](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L220)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +250: if (invocationDelay != 0 && msg.sender != proofReceipt[msgHash].preferredExecutor) { + +260: if (_message.gasLimit == 0 && msg.sender != _message.destOwner) { + +439: } else if (block.chainid >= 32_300 && block.chainid <= 32_400) { + +491: _message.data.length >= 4 // msg can be empty +492: && bytes4(_message.data) != IMessageInvocable.onMessageInvocation.selector +493: && _message.to.isContract() +``` + +[[250](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L250), [260](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L260), [439](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L439), [491-493](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L491-L493)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +85: if (!_allowZeroAddress && addr_ == address(0)) { +``` + +[[85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L85)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +42: if (msg.sender != owner() && msg.sender != resolve(_name, true)) revert RESOLVER_DENIED(); +``` + +[[42](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L42)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +117: _l1BlockHash == 0 || _l1StateRoot == 0 || _l1BlockId == 0 +118: || (block.number != 1 && _parentGasUsed == 0) + +141: if (!skipFeeCheck() && block.basefee != basefee) { + +275: if (lastSyncedBlock > 0 && _l1BlockId > lastSyncedBlock) { +``` + +[[117-118](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L117-L118), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L141), [275](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L275)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +285: if (cacheStateRoot && _isFullProof && !_isLastHop) { + +293: if (cacheSignalRoot && (_isFullProof || !_isLastHop)) { +``` + +[[285](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L285), [293](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L293)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +277: if (_cliff > 0 && _cliff <= _start) revert INVALID_GRANT(); +``` + +[[277](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L277)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +38: if (msg.sender != owner() && msg.sender != snapshooter) { +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L38)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +45: if (_migratingAddress == migratingAddress && _migratingInbound == migratingInbound) { +``` + +[[45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L45)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +135: (notBeforeTag != 0x17 && notBeforeTag == 0x18) +136: || (notAfterTag != 0x17 && notAfterTag != 0x18) +``` + +[[135-136](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L135-L136)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +82: block.timestamp > assignment.expiry +83: || assignment.metaHash != 0 && _blk.metaHash != assignment.metaHash +84: || assignment.parentMetaHash != 0 && _meta.parentMetaHash != assignment.parentMetaHash +85: || assignment.maxBlockId != 0 && _meta.id > assignment.maxBlockId +86: || assignment.maxProposedIn != 0 && block.number > assignment.maxProposedIn + +120: if (input.tip != 0 && block.coinbase != address(0)) { +``` + +[[82-86](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L82-L86), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L120)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +108: if (params.parentMetaHash != 0 && parentMetaHash != params.parentMetaHash) { + +164: if (_config.blobReuseEnabled && params.cacheBlobForReuse) { + +310: if (proposerOne != address(0) && msg.sender != proposerOne) { +``` + +[[108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L108), [164](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L164), [310](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L310)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +419: if (_tid == 1 && _ts.tier == 0 && inProvingWindow) { +``` + +[[419](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L419)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +14: if (_in.length == 1 && uint8(_in[0]) < 128) { +``` + +[[14](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L14)] + +
+ +--- + +### [G-54] Counting down when iterating, saves gas + +Counting down saves **6 gas** per loop, since checks for zero are more efficient than checks against any other value. + +_There are 45 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +80: for (uint256 i; i < serialNumBatch.length; ++i) { + +95: for (uint256 i; i < serialNumBatch.length; ++i) { + +191: for (uint256 i; i < enclaveId.tcbLevels.length; ++i) { + +214: for (uint256 i; i < tcb.tcbLevels.length; ++i) { + +240: for (uint256 i; i < CPUSVN_LENGTH; ++i) { + +259: for (uint256 i; i < n; ++i) { + +420: for (uint256 i; i < 3; ++i) { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L80), [95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L95), [191](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L191), [214](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L214), [240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L240), [259](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L259), [420](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L420)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +90: for (uint256 i; i < _msgHashes.length; ++i) { +``` + +[[90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L90)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +234: for (uint256 i; i < 255 && _blockId >= i + 1; ++i) { +``` + +[[234](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L234)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +104: for (uint256 i; i < hopProofs.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L104)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +47: for (uint256 i; i < _op.amounts.length; ++i) { + +251: for (uint256 i; i < _op.tokenIds.length; ++i) { + +269: for (uint256 i; i < _op.tokenIds.length; ++i) { +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L47), [251](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L251), [269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L269)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +34: for (uint256 i; i < _op.tokenIds.length; ++i) { + +170: for (uint256 i; i < _tokenIds.length; ++i) { + +175: for (uint256 i; i < _tokenIds.length; ++i) { + +197: for (uint256 i; i < _op.tokenIds.length; ++i) { + +210: for (uint256 i; i < _op.tokenIds.length; ++i) { +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L34), [170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L170), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L175), [197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L197), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L210)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +104: for (uint256 i; i < _ids.length; ++i) { + +210: for (uint256 i; i < _instances.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L104), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L210)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +54: for (uint256 i; i < size; ++i) { + +244: for (uint256 i; i < split.length; ++i) { + +354: for (uint256 i; i < SGX_TCB_CPUSVN_SIZE + 1; ++i) { +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L54), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L244), [354](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L354)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +333: for (uint256 i; i < len; ++i) { +``` + +[[333](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L333)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +140: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +152: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +158: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +174: for (uint256 i; i < _sha256.length; ++i) { + +273: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +283: for (uint256 i; i < sha1Prefix.length; ++i) { + +290: for (uint256 i; i < _sha1.length; ++i) { +``` + +[[140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L140), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L152), [158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L158), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L174), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L273), [283](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L283), [290](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L290)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +48: for (uint16 i = 1970; i < year; ++i) { + +59: for (uint8 i = 1; i < month; ++i) { +``` + +[[48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L48), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L59)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +172: for (uint256 i; i < _tierFees.length; ++i) { +``` + +[[172](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L172)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +244: for (uint256 i; i < params.hookCalls.length; ++i) { +``` + +[[244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L244)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +74: for (uint256 i; i < guardians.length; ++i) { + +80: for (uint256 i = 0; i < _newGuardians.length; ++i) { + +133: for (uint256 i; i < guardiansLength; ++i) { +``` + +[[74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L74), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L80), [133](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L133)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +59: for (uint256 i; i < tokenIds.length; ++i) { +``` + +[[59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L59)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +153: for (uint256 i; i < encoded.length; ++i) { + +281: for (uint256 i; i < 3; ++i) { +``` + +[[153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L153), [281](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L281)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +46: for (i = 1; i <= lenLen; i++) { + +59: for (; i < 32; i++) { + +66: for (uint256 j = 0; j < out_.length; j++) { +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L46), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L59), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L66)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +85: for (uint256 i = 0; i < proof.length; i++) { +``` + +[[85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L85)] + +
+ +--- + +### [G-55] `do-while` is cheaper than `for`-loops when the initial check can be skipped + +Example: + +```solidity +for (uint256 i; i < len; ++i){ ... } -> do { ...; ++i } while (i < len); +``` + +_There are 49 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +80: for (uint256 i; i < serialNumBatch.length; ++i) { + +95: for (uint256 i; i < serialNumBatch.length; ++i) { + +191: for (uint256 i; i < enclaveId.tcbLevels.length; ++i) { + +214: for (uint256 i; i < tcb.tcbLevels.length; ++i) { + +240: for (uint256 i; i < CPUSVN_LENGTH; ++i) { + +259: for (uint256 i; i < n; ++i) { + +420: for (uint256 i; i < 3; ++i) { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L80), [95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L95), [191](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L191), [214](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L214), [240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L240), [259](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L259), [420](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L420)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +90: for (uint256 i; i < _msgHashes.length; ++i) { +``` + +[[90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L90)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +234: for (uint256 i; i < 255 && _blockId >= i + 1; ++i) { +``` + +[[234](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L234)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +104: for (uint256 i; i < hopProofs.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L104)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +47: for (uint256 i; i < _op.amounts.length; ++i) { + +251: for (uint256 i; i < _op.tokenIds.length; ++i) { + +269: for (uint256 i; i < _op.tokenIds.length; ++i) { +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L47), [251](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L251), [269](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L269)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +34: for (uint256 i; i < _op.tokenIds.length; ++i) { + +170: for (uint256 i; i < _tokenIds.length; ++i) { + +175: for (uint256 i; i < _tokenIds.length; ++i) { + +197: for (uint256 i; i < _op.tokenIds.length; ++i) { + +210: for (uint256 i; i < _op.tokenIds.length; ++i) { +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L34), [170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L170), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L175), [197](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L197), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L210)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +104: for (uint256 i; i < _ids.length; ++i) { + +210: for (uint256 i; i < _instances.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L104), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L210)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +54: for (uint256 i; i < size; ++i) { + +244: for (uint256 i; i < split.length; ++i) { + +354: for (uint256 i; i < SGX_TCB_CPUSVN_SIZE + 1; ++i) { +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L54), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L244), [354](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L354)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +80: for (uint256 idx = 0; idx < shortest; idx += 32) { + +333: for (uint256 i; i < len; ++i) { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L80), [333](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L333)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +140: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +152: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +158: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +174: for (uint256 i; i < _sha256.length; ++i) { + +273: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +283: for (uint256 i; i < sha1Prefix.length; ++i) { + +290: for (uint256 i; i < _sha1.length; ++i) { +``` + +[[140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L140), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L152), [158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L158), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L174), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L273), [283](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L283), [290](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L290)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +48: for (uint16 i = 1970; i < year; ++i) { + +59: for (uint8 i = 1; i < month; ++i) { +``` + +[[48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L48), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L59)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +172: for (uint256 i; i < _tierFees.length; ++i) { +``` + +[[172](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L172)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +86: for (uint256 i; i < deposits_.length;) { +``` + +[[86](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L86)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +244: for (uint256 i; i < params.hookCalls.length; ++i) { +``` + +[[244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L244)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +74: for (uint256 i; i < guardians.length; ++i) { + +80: for (uint256 i = 0; i < _newGuardians.length; ++i) { + +133: for (uint256 i; i < guardiansLength; ++i) { +``` + +[[74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L74), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L80), [133](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L133)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +59: for (uint256 i; i < tokenIds.length; ++i) { +``` + +[[59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L59)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +153: for (uint256 i; i < encoded.length; ++i) { + +281: for (uint256 i; i < 3; ++i) { +``` + +[[153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L153), [281](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L281)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +46: for (i = 1; i <= lenLen; i++) { + +59: for (; i < 32; i++) { + +66: for (uint256 j = 0; j < out_.length; j++) { +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L46), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L59), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L66)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +85: for (uint256 i = 0; i < proof.length; i++) { + +208: for (uint256 i = 0; i < length;) { + +244: for (; shared_ < max && _a[shared_] == _b[shared_];) { +``` + +[[85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L85), [208](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L208), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L244)] + +
+ +--- + +### [G-56] Lack of `unchecked` in loops + +Use `unchecked` to increment the loop variable as it can save gas: + +```solidity +for(uint256 i; i < length;) { + unchecked{ + ++i; + } +} +``` + +_There are 39 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +80: for (uint256 i; i < serialNumBatch.length; ++i) { + +95: for (uint256 i; i < serialNumBatch.length; ++i) { + +191: for (uint256 i; i < enclaveId.tcbLevels.length; ++i) { + +214: for (uint256 i; i < tcb.tcbLevels.length; ++i) { + +240: for (uint256 i; i < CPUSVN_LENGTH; ++i) { + +259: for (uint256 i; i < n; ++i) { + +420: for (uint256 i; i < 3; ++i) { +``` + +[[80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L80), [95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L95), [191](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L191), [214](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L214), [240](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L240), [259](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L259), [420](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L420)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +90: for (uint256 i; i < _msgHashes.length; ++i) { +``` + +[[90](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L90)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +104: for (uint256 i; i < hopProofs.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L104)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +47: for (uint256 i; i < _op.amounts.length; ++i) { +``` + +[[47](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L47)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +34: for (uint256 i; i < _op.tokenIds.length; ++i) { + +170: for (uint256 i; i < _tokenIds.length; ++i) { + +175: for (uint256 i; i < _tokenIds.length; ++i) { +``` + +[[34](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L34), [170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L170), [175](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L175)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +104: for (uint256 i; i < _ids.length; ++i) { + +210: for (uint256 i; i < _instances.length; ++i) { +``` + +[[104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L104), [210](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L210)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +54: for (uint256 i; i < size; ++i) { + +244: for (uint256 i; i < split.length; ++i) { + +354: for (uint256 i; i < SGX_TCB_CPUSVN_SIZE + 1; ++i) { +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L54), [244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L244), [354](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L354)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol + +333: for (uint256 i; i < len; ++i) { +``` + +[[333](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol#L333)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol + +140: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +152: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +158: for (uint256 i; i < digestAlgoWithParamLen; ++i) { + +174: for (uint256 i; i < _sha256.length; ++i) { + +273: for (uint256 i = 2; i < 2 + paddingLen; ++i) { + +283: for (uint256 i; i < sha1Prefix.length; ++i) { + +290: for (uint256 i; i < _sha1.length; ++i) { +``` + +[[140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L140), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L152), [158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L158), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L174), [273](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L273), [283](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L283), [290](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol#L290)] + +```solidity +File: packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol + +48: for (uint16 i = 1970; i < year; ++i) { + +59: for (uint8 i = 1; i < month; ++i) { +``` + +[[48](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L48), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol#L59)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +172: for (uint256 i; i < _tierFees.length; ++i) { +``` + +[[172](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L172)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +244: for (uint256 i; i < params.hookCalls.length; ++i) { +``` + +[[244](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L244)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +74: for (uint256 i; i < guardians.length; ++i) { + +80: for (uint256 i = 0; i < _newGuardians.length; ++i) { +``` + +[[74](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L74), [80](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L80)] + +```solidity +File: packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol + +59: for (uint256 i; i < tokenIds.length; ++i) { +``` + +[[59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol#L59)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol + +153: for (uint256 i; i < encoded.length; ++i) { + +281: for (uint256 i; i < 3; ++i) { +``` + +[[153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L153), [281](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol#L281)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol + +46: for (i = 1; i <= lenLen; i++) { + +59: for (; i < 32; i++) { + +66: for (uint256 j = 0; j < out_.length; j++) { +``` + +[[46](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L46), [59](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L59), [66](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol#L66)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +85: for (uint256 i = 0; i < proof.length; i++) { +``` + +[[85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L85)] + +
+ +--- + +### [G-57] `uint` comparison with zero can be cheaper + +Checking for `!= 0` is cheaper than `> 0` for unsigned integers. + +_There are 15 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +262: if (gasExcess > 0) { + +275: if (lastSyncedBlock > 0 && _l1BlockId > lastSyncedBlock) { + +279: if (numL1Blocks > 0) { +``` + +[[262](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L262), [275](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L275), [279](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L279)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +120: bool isFullProof = hop.accountProof.length > 0; +``` + +[[120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L120)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +275: if (_cliff > 0) revert INVALID_GRANT(); + +277: if (_cliff > 0 && _cliff <= _start) revert INVALID_GRANT(); +``` + +[[275](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L275), [277](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L277)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +56: if (i > 0) { +``` + +[[56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L56)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +125: if (address(this).balance > 0) { +``` + +[[125](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L125)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +192: bool returnLivenessBond = blk.livenessBond > 0 && _proof.data.length == 32 +``` + +[[192](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L192)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +212: if (numBlocksVerified > 0) { +``` + +[[212](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L212)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol + +38: _in.length > 0, + +153: _in.length > 0, +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L38), [153](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol#L153)] + +```solidity +File: packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol + +77: require(_key.length > 0, "MerkleTrie: empty key"); + +120: value_.length > 0, + +173: value_.length > 0, +``` + +[[77](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L77), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L120), [173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol#L173)] + +
+ +--- + +### [G-58] Use assembly to check for `address(0)` + +[A simple zero address check](https://medium.com/@kalexotsu/solidity-assembly-checking-if-an-address-is-0-efficiently-d2bfe071331) can be written in assembly to save some gas. + +_There are 74 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +124: if (_message.srcOwner == address(0) || _message.destOwner == address(0)) { + +124: if (_message.srcOwner == address(0) || _message.destOwner == address(0)) { + +124: if (_message.srcOwner == address(0) || _message.destOwner == address(0)) { + +270: _message.to == address(0) || _message.to == address(this) +271: || _message.to == signalService || addressBanned[_message.to] + +270: _message.to == address(0) || _message.to == address(this) +271: || _message.to == signalService || addressBanned[_message.to] + +270: _message.to == address(0) || _message.to == address(this) + +270: _message.to == address(0) || _message.to == address(this) + +291: _message.refundTo == address(0) ? _message.destOwner : _message.refundTo; + +398: enabled_ = destBridge_ != address(0); + +398: enabled_ = destBridge_ != address(0); +``` + +[[124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L124), [124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L124), [124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L124), [270-271](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L270-L271), [270-271](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L270-L271), [270](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L270), [270](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L270), [291](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L291), [398](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L398), [398](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L398)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +81: if (addressManager == address(0)) revert RESOLVER_INVALID_MANAGER(); + +85: if (!_allowZeroAddress && addr_ == address(0)) { + +85: if (!_allowZeroAddress && addr_ == address(0)) { +``` + +[[81](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L81), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L85), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L85)] + +```solidity +File: packages/protocol/contracts/common/EssentialContract.sol + +105: if (_addressManager == address(0)) revert ZERO_ADDR_MANAGER(); + +110: _transferOwnership(_owner == address(0) ? msg.sender : _owner); +``` + +[[105](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L105), [110](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/EssentialContract.sol#L110)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +172: if (_to == address(0)) revert L2_INVALID_PARAM(); + +173: if (_token == address(0)) { +``` + +[[172](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L172), [173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L173)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +24: if (_to == address(0)) revert ETH_TRANSFER_FAILED(); +``` + +[[24](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L24)] + +```solidity +File: packages/protocol/contracts/signal/SignalService.sol + +36: if (_app == address(0)) revert SS_INVALID_SENDER(); +``` + +[[36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/signal/SignalService.sol#L36)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +121: if (_taikoToken == address(0)) revert INVALID_PARAM(); + +124: if (_costToken == address(0)) revert INVALID_PARAM(); + +127: if (_sharedVault == address(0)) revert INVALID_PARAM(); + +136: if (_recipient == address(0)) revert INVALID_PARAM(); + +169: if (_to == address(0)) revert INVALID_PARAM(); +``` + +[[121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L121), [124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L124), [127](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L127), [136](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L136), [169](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L169)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseNFTVault.sol + +149: if (_op.token == address(0)) revert VAULT_INVALID_TOKEN(); +``` + +[[149](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseNFTVault.sol#L149)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +102: return migratingAddress != address(0) && !migratingInbound; + +102: return migratingAddress != address(0) && !migratingInbound; +``` + +[[102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L102), [102](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L102)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +64: destOwner: _op.destOwner != address(0) ? _op.destOwner : msg.sender, + +108: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +108: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +249: if (bridgedToCanonical[_op.token].addr != address(0)) { + +293: if (btoken_ == address(0)) { +``` + +[[64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L64), [108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L108), [108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L108), [249](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L249), [293](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L293)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +158: if (_btokenNew == address(0) || bridgedToCanonical[_btokenNew].addr != address(0)) { + +158: if (_btokenNew == address(0) || bridgedToCanonical[_btokenNew].addr != address(0)) { + +158: if (_btokenNew == address(0) || bridgedToCanonical[_btokenNew].addr != address(0)) { + +170: if (btokenOld_ != address(0)) { + +215: if (_op.token == address(0)) revert VAULT_INVALID_TOKEN(); + +227: destOwner: _op.destOwner != address(0) ? _op.destOwner : msg.sender, + +267: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +267: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +358: if (bridgedToCanonical[_token].addr != address(0)) { + +397: if (btoken == address(0)) { +``` + +[[158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L158), [158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L158), [158](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L158), [170](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L170), [215](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L215), [227](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L227), [267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L267), [267](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L267), [358](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L358), [397](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L397)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +50: destOwner: _op.destOwner != address(0) ? _op.destOwner : msg.sender, + +91: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +91: if (to == address(0) || to == address(this)) revert VAULT_INVALID_TO(); + +195: if (bridgedToCanonical[_op.token].addr != address(0)) { + +230: if (btoken_ == address(0)) { +``` + +[[50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L50), [91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L91), [91](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L91), [195](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L195), [230](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L230)] + +```solidity +File: packages/protocol/contracts/tokenvault/LibBridgedToken.sol + +21: _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid +22: || bytes(_symbol).length == 0 || bytes(_name).length == 0 + +21: _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid +22: || bytes(_symbol).length == 0 || bytes(_name).length == 0 + +21: _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid + +21: _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid + +21: _srcToken == address(0) || _srcChainId == 0 || _srcChainId == block.chainid +``` + +[[21-22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L21-L22), [21-22](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L21-L22), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L21), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L21), [21](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L21)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +107: if (instances[idx].addr == address(0)) revert SGX_INVALID_INSTANCE(); + +124: if (automataDcapAttestation == address(0)) { + +215: if (_instances[i] == address(0)) revert SGX_INVALID_INSTANCE(); + +234: if (instance == address(0)) return false; +``` + +[[107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L107), [124](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L124), [215](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L215), [234](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L234)] + +```solidity +File: packages/protocol/contracts/L1/hooks/AssignmentHook.sol + +109: if (assignment.feeToken == address(0)) { + +120: if (input.tip != 0 && block.coinbase != address(0)) { + +120: if (input.tip != 0 && block.coinbase != address(0)) { +``` + +[[109](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L109), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L120), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/hooks/AssignmentHook.sol#L120)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibDepositing.sol + +44: address recipient_ = _recipient == address(0) ? msg.sender : _recipient; +``` + +[[44](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibDepositing.sol#L44)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProposing.sol + +81: if (params.assignedProver == address(0)) { + +85: if (params.coinbase == address(0)) { + +310: if (proposerOne != address(0) && msg.sender != proposerOne) { + +310: if (proposerOne != address(0) && msg.sender != proposerOne) { + +316: return proposer == address(0) || msg.sender == proposer; + +316: return proposer == address(0) || msg.sender == proposer; +``` + +[[81](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L81), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L85), [310](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L310), [310](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L310), [316](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L316), [316](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProposing.sol#L316)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibProving.sol + +163: if (verifier != address(0)) { + +224: assert(ts.validityBond == 0 && ts.contestBond == 0 && ts.contester == address(0)); + +224: assert(ts.validityBond == 0 && ts.contestBond == 0 && ts.contester == address(0)); + +239: if (ts.contester != address(0)) revert L1_ALREADY_CONTESTED(); + +363: if (_ts.contester != address(0)) { +``` + +[[163](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L163), [224](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L224), [224](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L224), [239](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L239), [363](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibProving.sol#L363)] + +```solidity +File: packages/protocol/contracts/L1/libs/LibVerifying.sol + +145: if (ts.contester != address(0)) { + +148: if (tierProvider == address(0)) { +``` + +[[145](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L145), [148](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/libs/LibVerifying.sol#L148)] + +```solidity +File: packages/protocol/contracts/L1/provers/Guardians.sol + +82: if (guardian == address(0)) revert INVALID_GUARDIAN(); +``` + +[[82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/provers/Guardians.sol#L82)] + +
+ +--- + +### [G-59] Use scratch space for building calldata with assembly + +If an external call's calldata can fit into two or fewer words, use the scratch space to build the calldata, rather than allowing Solidity to do a memory expansion. + +_There are 333 instances of this issue._ + +
+Expand findings + +```solidity +File: packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol + +167: V3Parser.parseInput(quote, address(pemCertLib)); + +313: bytes32 expectedAuthDataHash = bytes32(qeEnclaveReport.reportData.substring(0, 32)); + +321: V3Parser.packQEReport(authDataV3.pckSignedQeReport); + +378: ) = V3Parser.validateParsedInput(v3quote); + +424: (certDecodedSuccessfully, parsedQuoteCerts[i]) = pemCertLib.decodeCert( +425: authDataV3.certification.decodedCertDataArray[i], isPckCert +426: ); + +437: bool tcbConfigured = LibString.eq(parsedFmspc, fetchedTcbInfo.fmspc); + +443: bool pceidMatched = LibString.eq(pckCert.pck.sgxExtension.pceid, fetchedTcbInfo.pceid); +``` + +[[167](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L167), [313](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L313), [321](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L321), [378](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L378), [424-426](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L424-L426), [437](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L437), [443](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol#L443)] + +```solidity +File: packages/protocol/contracts/bridge/Bridge.sol + +150: ISignalService(resolve("signal_service", false)).sendSignal(msgHash_); + +174: if (!ISignalService(signalService).isSignalSent(address(this), msgHash)) { + +195: if (_message.from.supportsInterface(type(IRecallableSender).interfaceId)) { + +206: _message.srcOwner.sendEther(_message.value); + +295: refundTo.sendEther(_message.fee + refundAmount); + +298: msg.sender.sendEther(_message.fee); + +299: refundTo.sendEther(refundAmount); + +342: return ISignalService(resolve("signal_service", false)).isSignalSent({ +343: _app: address(this), +344: _signal: hashMessage(_message) +345: }); + +493: && _message.to.isContract() + +522: ISignalService(resolve("signal_service", false)).sendSignal( +523: signalForFailedMessage(_msgHash) +524: ); + +591: (success_,) = _signalService.staticcall(data); +``` + +[[150](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L150), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L174), [195](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L195), [206](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L206), [295](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L295), [298](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L298), [299](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L299), [342-345](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L342-L345), [493](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L493), [522-524](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L522-L524), [591](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/bridge/Bridge.sol#L591)] + +```solidity +File: packages/protocol/contracts/common/AddressResolver.sol + +83: addr_ = payable(IAddressManager(addressManager).getAddress(_chainId, _name)); +``` + +[[83](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/common/AddressResolver.sol#L83)] + +```solidity +File: packages/protocol/contracts/L1/TaikoL1.sol + +113: LibProving.pauseProving(state, _pause); +``` + +[[113](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L1/TaikoL1.sol#L113)] + +```solidity +File: packages/protocol/contracts/L2/CrossChainOwned.sol + +45: IBridge.Context memory ctx = IBridge(msg.sender).context(); + +50: (bool success,) = address(this).call(txdata); +``` + +[[45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L45), [50](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/CrossChainOwned.sol#L50)] + +```solidity +File: packages/protocol/contracts/L2/Lib1559Math.sol + +45: return uint256(LibFixedPointMath.exp(int256(input))); +``` + +[[45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/Lib1559Math.sol#L45)] + +```solidity +File: packages/protocol/contracts/L2/TaikoL2.sol + +174: _to.sendEther(address(this).balance); + +176: IERC20(_token).safeTransfer(_to, IERC20(_token).balanceOf(address(this))); + +176: IERC20(_token).safeTransfer(_to, IERC20(_token).balanceOf(address(this))); + +284: gasExcess_ = uint64(excess.min(type(uint64).max)); + +290: basefee_ = Lib1559Math.basefee( +291: gasExcess_, uint256(_config.basefeeAdjustmentQuotient) * _config.gasTargetPerL1Block +292: ); +``` + +[[174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L174), [176](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L176), [176](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L176), [284](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L284), [290-292](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/L2/TaikoL2.sol#L290-L292)] + +```solidity +File: packages/protocol/contracts/libs/Lib4844.sol + +43: (bool ok, bytes memory ret) = POINT_EVALUATION_PRECOMPILE_ADDRESS.staticcall( +44: abi.encodePacked(_blobHash, _x, _y, _commitment, _pointProof) +45: ); +``` + +[[43-45](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/Lib4844.sol#L43-L45)] + +```solidity +File: packages/protocol/contracts/libs/LibAddress.sol + +54: if (!Address.isContract(_addr)) return false; + +56: try IERC165(_addr).supportsInterface(_interfaceId) returns (bool _result) { + +70: if (Address.isContract(_addr)) { + +71: return IERC1271(_addr).isValidSignature(_hash, _sig) == _EIP1271_MAGICVALUE; + +73: return ECDSA.recover(_hash, _sig) == _addr; +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L54), [56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L56), [70](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L70), [71](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L71), [73](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibAddress.sol#L73)] + +```solidity +File: packages/protocol/contracts/libs/LibTrieProof.sol + +52: RLPReader.RLPItem[] memory accountState = RLPReader.readList(rlpAccount); + +55: bytes32(RLPReader.readBytes(accountState[_ACCOUNT_FIELD_INDEX_STORAGE_HASH])); + +61: bytes.concat(_slot), RLPWriter.writeUint(uint256(_value)), _storageProof, storageRoot_ + +61: bytes.concat(_slot), RLPWriter.writeUint(uint256(_value)), _storageProof, storageRoot_ +``` + +[[52](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L52), [55](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L55), [61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L61), [61](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L61)] + +```solidity +File: packages/protocol/contracts/team/TimelockTokenPool.sol + +171: address recipient = ECDSA.recover(hash, _sig); +``` + +[[171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/team/TimelockTokenPool.sol#L171)] + +```solidity +File: packages/protocol/contracts/tokenvault/BaseVault.sol + +53: ctx_ = IBridge(msg.sender).context(); + +64: ctx_ = IBridge(msg.sender).context(); +``` + +[[53](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L53), [64](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BaseVault.sol#L64)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC1155.sol + +54: __ERC1155_init(LibBridgedToken.buildURI(_srcToken, _srcChainId)); + +116: return LibBridgedToken.buildName(__name, srcChainId); + +122: return LibBridgedToken.buildSymbol(__symbol); +``` + +[[54](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L54), [116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L116), [122](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC1155.sol#L122)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20.sol + +97: return LibBridgedToken.buildName(super.name(), srcChainId); + +108: return LibBridgedToken.buildSymbol(super.symbol()); +``` + +[[97](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L97), [108](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20.sol#L108)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC20Base.sol + +82: IBridgedERC20(migratingAddress).mint(_account, _amount); +``` + +[[82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol#L82)] + +```solidity +File: packages/protocol/contracts/tokenvault/BridgedERC721.sol + +88: return LibBridgedToken.buildName(super.name(), srcChainId); + +94: return LibBridgedToken.buildSymbol(super.symbol()); + +110: LibBridgedToken.buildURI(srcToken, srcChainId), Strings.toString(_tokenId) + +110: LibBridgedToken.buildURI(srcToken, srcChainId), Strings.toString(_tokenId) +``` + +[[88](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L88), [94](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L94), [110](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L110), [110](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/BridgedERC721.sol#L110)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC1155Vault.sol + +51: if (!_op.token.supportsInterface(ERC1155_INTERFACE_ID)) { + +112: to.sendEther(msg.value); + +146: message.srcOwner.sendEther(message.value); + +200: || BaseVault.supportsInterface(interfaceId); + +263: try t.name() returns (string memory _name) { + +266: try t.symbol() returns (string memory _symbol) { +``` + +[[51](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L51), [112](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L112), [146](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L146), [200](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L200), [263](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L263), [266](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC1155Vault.sol#L266)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC20Vault.sol + +164: if (IBridgedERC20(_btokenNew).owner() != owner()) { + +184: IBridgedERC20(btokenOld_).changeMigrationStatus(_btokenNew, false); + +185: IBridgedERC20(_btokenNew).changeMigrationStatus(btokenOld_, true); + +271: to.sendEther(msg.value); + +304: _message.srcOwner.sendEther(_message.value); + +330: IERC20(token_).safeTransfer(_to, _amount); + +333: IBridgedERC20(token_).mint(_to, _amount); + +360: IBridgedERC20(_token).burn(msg.sender, _amount); + +368: decimals: meta.decimals(), + +369: symbol: meta.symbol(), + +370: name: meta.name() + +378: uint256 _balance = t.balanceOf(address(this)); + +380: balanceChange_ = t.balanceOf(address(this)) - _balance; +``` + +[[164](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L164), [184](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L184), [185](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L185), [271](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L271), [304](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L304), [330](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L330), [333](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L333), [360](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L360), [368](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L368), [369](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L369), [370](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L370), [378](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L378), [380](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC20Vault.sol#L380)] + +```solidity +File: packages/protocol/contracts/tokenvault/ERC721Vault.sol + +38: if (!_op.token.supportsInterface(ERC721_INTERFACE_ID)) { + +95: to.sendEther(msg.value); + +129: _message.srcOwner.sendEther(_message.value); + +176: BridgedERC721(token_).mint(_to, _tokenIds[i]); + +198: BridgedERC721(_op.token).burn(_user, _op.tokenIds[i]); + +206: symbol: t.symbol(), + +207: name: t.name() +``` + +[[38](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L38), [95](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L95), [129](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L129), [176](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L176), [198](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L198), [206](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L206), [207](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/ERC721Vault.sol#L207)] + +```solidity +File: packages/protocol/contracts/tokenvault/LibBridgedToken.sol + +36: return string.concat("Bridged ", _name, unicode" (⭀", Strings.toString(_srcChainId), ")"); + +40: return string.concat(_symbol, ".t"); + +56: Strings.toHexString(uint160(_srcToken), 20), + +58: Strings.toString(_srcChainId), +``` + +[[36](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L36), [40](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L40), [56](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L56), [58](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/tokenvault/LibBridgedToken.sol#L58)] + +```solidity +File: packages/protocol/contracts/verifiers/SgxVerifier.sol + +128: (bool verified,) = IAttestation(automataDcapAttestation).verifyParsedQuote(_attestation); + +156: bytes memory signature = Bytes.slice(_proof.data, 24); + +159: ECDSA.recover(getSignedHash(_tran, newInstance, _ctx.prover, _ctx.metaHash), signature); + +185: ITaikoL1(taikoL1).getConfig().chainId, +``` + +[[128](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L128), [156](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L156), [159](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L159), [185](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/verifiers/SgxVerifier.sol#L185)] + +```solidity +File: packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol + +82: uint256 root = der.root(); + +85: uint256 tbsParentPtr = der.firstChildOf(root); + +88: uint256 tbsPtr = der.firstChildOf(tbsParentPtr); + +104: tbsPtr = der.nextSiblingOf(tbsPtr); + +107: bytes memory serialNumBytes = der.bytesAt(tbsPtr); + +111: tbsPtr = der.nextSiblingOf(tbsPtr); + +112: tbsPtr = der.nextSiblingOf(tbsPtr); + +115: uint256 issuerPtr = der.firstChildOf(tbsPtr); + +116: issuerPtr = der.firstChildOf(issuerPtr); + +117: issuerPtr = der.firstChildOf(issuerPtr); + +118: issuerPtr = der.nextSiblingOf(issuerPtr); + +119: cert.pck.issuerName = string(der.bytesAt(issuerPtr)); + +120: bool issuerNameIsValid = LibString.eq(cert.pck.issuerName, PLATFORM_ISSUER_NAME) + +121: || LibString.eq(cert.pck.issuerName, PROCESSOR_ISSUER_NAME); + +127: tbsPtr = der.nextSiblingOf(tbsPtr); + +130: uint256 notBeforePtr = der.firstChildOf(tbsPtr); + +131: uint256 notAfterPtr = der.nextSiblingOf(notBeforePtr); + +132: bytes1 notBeforeTag = der[notBeforePtr.ixs()]; + +133: bytes1 notAfterTag = der[notAfterPtr.ixs()]; + +140: cert.notBefore = X509DateUtils.toTimestamp(der.bytesAt(notBeforePtr)); + +140: cert.notBefore = X509DateUtils.toTimestamp(der.bytesAt(notBeforePtr)); + +141: cert.notAfter = X509DateUtils.toTimestamp(der.bytesAt(notAfterPtr)); + +141: cert.notAfter = X509DateUtils.toTimestamp(der.bytesAt(notAfterPtr)); + +144: tbsPtr = der.nextSiblingOf(tbsPtr); + +147: uint256 subjectPtr = der.firstChildOf(tbsPtr); + +148: subjectPtr = der.firstChildOf(subjectPtr); + +149: subjectPtr = der.firstChildOf(subjectPtr); + +150: subjectPtr = der.nextSiblingOf(subjectPtr); + +151: cert.pck.commonName = string(der.bytesAt(subjectPtr)); + +152: if (!LibString.eq(cert.pck.commonName, PCK_COMMON_NAME)) { + +157: tbsPtr = der.nextSiblingOf(tbsPtr); + +161: uint256 subjectPublicKeyInfoPtr = der.firstChildOf(tbsPtr); + +162: subjectPublicKeyInfoPtr = der.nextSiblingOf(subjectPublicKeyInfoPtr); + +166: uint256 sigPtr = der.nextSiblingOf(tbsParentPtr); + +167: sigPtr = der.nextSiblingOf(sigPtr); + +171: sigPtr = NodePtr.getPtr(sigPtr.ixs() + 3, sigPtr.ixf() + 3, sigPtr.ixl()); + +171: sigPtr = NodePtr.getPtr(sigPtr.ixs() + 3, sigPtr.ixf() + 3, sigPtr.ixl()); + +171: sigPtr = NodePtr.getPtr(sigPtr.ixs() + 3, sigPtr.ixf() + 3, sigPtr.ixl()); + +173: sigPtr = der.firstChildOf(sigPtr); + +174: bytes memory sigX = _trimBytes(der.bytesAt(sigPtr), 32); + +176: sigPtr = der.nextSiblingOf(sigPtr); + +177: bytes memory sigY = _trimBytes(der.bytesAt(sigPtr), 32); + +179: cert.tbsCertificate = der.allBytesAt(tbsParentPtr); + +180: cert.pubKey = _trimBytes(der.bytesAt(subjectPublicKeyInfoPtr), 64); + +186: tbsPtr = der.nextSiblingOf(tbsPtr); + +189: if (der[tbsPtr.ixs()] != 0xA3) { + +193: tbsPtr = der.firstChildOf(tbsPtr); + +194: tbsPtr = der.firstChildOf(tbsPtr); + +208: cert.pck.sgxExtension.pceid = LibString.toHexStringNoPrefix(pceidBytes); + +209: cert.pck.sgxExtension.fmspc = LibString.toHexStringNoPrefix(fmspcBytes); + +222: uint256 beginPos = LibString.indexOf(pemData, HEADER); + +223: uint256 endPos = LibString.indexOf(pemData, FOOTER); + +241: string[] memory split = LibString.split(contentSlice, string(delimiter)); + +245: contentStr = LibString.concat(contentStr, split[i]); + +266: output = input.substring(lengthDiff, expectedLength); + +287: uint256 internalPtr = der.firstChildOf(tbsPtr); + +288: if (der[internalPtr.ixs()] != 0x06) { + +292: if (BytesUtils.compareBytes(der.bytesAt(internalPtr), SGX_EXTENSION_OID)) { + +292: if (BytesUtils.compareBytes(der.bytesAt(internalPtr), SGX_EXTENSION_OID)) { + +294: internalPtr = der.nextSiblingOf(internalPtr); + +295: uint256 extnValueParentPtr = der.rootOfOctetStringAt(internalPtr); + +296: uint256 extnValuePtr = der.firstChildOf(extnValueParentPtr); + +302: uint256 extnValueOidPtr = der.firstChildOf(extnValuePtr); + +303: if (der[extnValueOidPtr.ixs()] != 0x06) { + +306: if (BytesUtils.compareBytes(der.bytesAt(extnValueOidPtr), TCB_OID)) { + +306: if (BytesUtils.compareBytes(der.bytesAt(extnValueOidPtr), TCB_OID)) { + +310: if (BytesUtils.compareBytes(der.bytesAt(extnValueOidPtr), PCEID_OID)) { + +310: if (BytesUtils.compareBytes(der.bytesAt(extnValueOidPtr), PCEID_OID)) { + +312: uint256 pceidPtr = der.nextSiblingOf(extnValueOidPtr); + +313: pceidBytes = der.bytesAt(pceidPtr); + +316: if (BytesUtils.compareBytes(der.bytesAt(extnValueOidPtr), FMSPC_OID)) { + +316: if (BytesUtils.compareBytes(der.bytesAt(extnValueOidPtr), FMSPC_OID)) { + +318: uint256 fmspcPtr = der.nextSiblingOf(extnValueOidPtr); + +319: fmspcBytes = der.bytesAt(fmspcPtr); + +323: if (extnValuePtr.ixl() < extnValueParentPtr.ixl()) { + +323: if (extnValuePtr.ixl() < extnValueParentPtr.ixl()) { + +324: extnValuePtr = der.nextSiblingOf(extnValuePtr); + +333: if (tbsPtr.ixl() < tbsParentPtr.ixl()) { + +333: if (tbsPtr.ixl() < tbsParentPtr.ixl()) { + +334: tbsPtr = der.nextSiblingOf(tbsPtr); + +350: uint256 tcbPtr = der.nextSiblingOf(oidPtr); + +352: uint256 svnParentPtr = der.firstChildOf(tcbPtr); + +355: uint256 svnPtr = der.firstChildOf(svnParentPtr); // OID + +356: uint256 svnValuePtr = der.nextSiblingOf(svnPtr); // value + +357: bytes memory svnValueBytes = der.bytesAt(svnValuePtr); + +361: if (BytesUtils.compareBytes(der.bytesAt(svnPtr), PCESVN_OID)) { + +361: if (BytesUtils.compareBytes(der.bytesAt(svnPtr), PCESVN_OID)) { + +371: svnParentPtr = der.nextSiblingOf(svnParentPtr); +``` + +[[82](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L82), [85](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L85), [88](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L88), [104](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L104), [107](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L107), [111](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L111), [112](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L112), [115](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L115), [116](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L116), [117](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L117), [118](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L118), [119](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L119), [120](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L120), [121](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L121), [127](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L127), [130](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L130), [131](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L131), [132](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L132), [133](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L133), [140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L140), [140](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L140), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L141), [141](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L141), [144](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L144), [147](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L147), [148](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L148), [149](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L149), [150](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L150), [151](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L151), [152](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L152), [157](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L157), [161](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L161), [162](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L162), [166](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L166), [167](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L167), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L171), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L171), [171](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L171), [173](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L173), [174](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L174), [176](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L176), [177](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L177), [179](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L179), [180](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L180), [186](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L186), [189](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L189), [193](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L193), [194](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L194), [208](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L208), [209](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L209), [222](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L222), [223](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L223), [241](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L241), [245](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L245), [266](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L266), [287](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L287), [288](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L288), [292](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L292), [292](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L292), [294](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L294), [295](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L295), [296](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L296), [302](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L302), [303](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L303), [306](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L306), [306](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol#L306), [310](https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a47232232 + +
+ +**[dantaik (Taiko) confirmed and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/344#issuecomment-2036531972):** + +> Appreciate the feedback, some suggestions have been taken, as shown in https://github.com/taikoxyz/taiko-mono/pull/16627. + +--- + +# Audit Analysis + +For this audit, 22 analysis reports were submitted by wardens. An analysis report examines the codebase as a whole, providing observations and advice on such topics as architecture, mechanism, or approach. The [report highlighted below](https://github.com/code-423n4/2024-03-taiko-findings/issues/253) by **kaveyjoe** received the top score from the judge. + +_The following wardens also submitted reports: [MrPotatoMagic](https://github.com/code-423n4/2024-03-taiko-findings/issues/380), [yongskiws](https://github.com/code-423n4/2024-03-taiko-findings/issues/379), [fouzantanveer](https://github.com/code-423n4/2024-03-taiko-findings/issues/350), [0xepley](https://github.com/code-423n4/2024-03-taiko-findings/issues/317), [Sathish9098](https://github.com/code-423n4/2024-03-taiko-findings/issues/313), [hassanshakeel13](https://github.com/code-423n4/2024-03-taiko-findings/issues/303), [popeye](https://github.com/code-423n4/2024-03-taiko-findings/issues/244), [joaovwfreire](https://github.com/code-423n4/2024-03-taiko-findings/issues/216), [aariiif](https://github.com/code-423n4/2024-03-taiko-findings/issues/158), [Myd](https://github.com/code-423n4/2024-03-taiko-findings/issues/145), [roguereggiant](https://github.com/code-423n4/2024-03-taiko-findings/issues/89), [cheatc0d3](https://github.com/code-423n4/2024-03-taiko-findings/issues/369), [JCK](https://github.com/code-423n4/2024-03-taiko-findings/issues/356), [hunter_w3b](https://github.com/code-423n4/2024-03-taiko-findings/issues/316), [pavankv](https://github.com/code-423n4/2024-03-taiko-findings/issues/290), [LinKenji](https://github.com/code-423n4/2024-03-taiko-findings/issues/275), [0xbrett8571](https://github.com/code-423n4/2024-03-taiko-findings/issues/272), [clara](https://github.com/code-423n4/2024-03-taiko-findings/issues/236), [albahaca](https://github.com/code-423n4/2024-03-taiko-findings/issues/225), [emerald7017](https://github.com/code-423n4/2024-03-taiko-findings/issues/157), and [foxb868](https://github.com/code-423n4/2024-03-taiko-findings/issues/142)._ + +## 1. Introduction + +An Ethereum-equivalent ZK-Rollup allows for scaling Ethereum without sacrificing security or compatibility. Advancements in Zero-Knowledge Proof cryptography and its application towards proving Ethereum Virtual Machine (EVM) execution have led to a flourishing of ZK-EVMs, now with further design decisions to choose from. Taiko aims to be a decentralized ZK-Rollup, prioritizing Ethereum-equivalence. Supporting all existing Ethereum applications, tooling, and infrastructure is the primary goal and benefit of this path. Besides the maximally compatible ZK-EVM component, which proves the correctness of EVM computation on the rollup, Taiko must implement a layer-2 blockchain architecture to support it. + +Taiko aims to be a fully Ethereum-equivalent ZK-Rollup. aim to scale Ethereum in a manner that emulates Ethereum itself at a technical level, and a principles level. + +**Taiko consists of three main parts**: + +- the ZK-EVM circuits (for proof generation) +- the L2 rollup node (for managing the rollup chain) +- the protocol on L1 (for connecting these two parts together for rollup protocol verification). + Blocks in the Taiko L2 blockchain consist of collections of transactions that are executed sequentially. New blocks can be appended to the chain to update its state, which can be calculated by following the protocol rules for the execution of the transactions. + +### 1.1 How Does Taiko Work? + +Taiko operates by utilizing a Zero Knowledge Rollup (ZK-Rollup) mechanism, specifically designed to scale the Ethereum blockchain without compromising its foundational features of security, censorship resistance, and permissionless access. Here's a breakdown of how Taiko functions: + +- Zero Knowledge Proofs (ZKPs): Taiko leverages ZKPs to validate transactions confidentially, reducing data processing on Ethereum's mainnet. This efficiency cuts costs and increases transaction speed. +- Integration with Ethereum L1: Unlike rollups that use a centralized sequencer, Taiko's transactions are sequenced by Ethereum's Layer 1 validators. This method, called based sequencing, ensures that Taiko inherits Ethereum's security and decentralization properties. +- Smart Contracts and Governance: Taiko operates through smart contracts on Ethereum, detailing its protocol. Governance, including protocol updates, is managed by the Taiko DAO, ensuring community-driven decisions. +- Open Source and Compatibility: As an open-source platform, Taiko allows developers to deploy dApps seamlessly, maintaining Ethereum's ease of use and accessibility. +- Decentralized Validation: Taiko supports a decentralized model for proposers and validators, enhancing network security and integrity. Ethereum L1 validators also play a pivotal role, emphasizing decentralization. +- Community-Driven Governance: The Taiko DAO, driven by TKO token holders, oversees significant protocol decisions. This governance model promotes inclusivity and community engagement. + +In essence, Taiko's approach, built on zero knowledge proofs and closely integrated with Ethereum's infrastructure, offers a scalable and secure solution while adhering to Ethereum’s foundational values. Its commitment to open-source development and community governance aligns well with the ethos of the wider Ethereum community. + +### 1.2 Mechanism of Taiko + +**Mechanism of action of Taiko** +Taiko's operating mechanism is based on the cooperation of three main subjects: + +Proposer: Responsible for creating blocks from user transactions at layer 2 and proposing to Ethereum. +Prover: Create zk-Snark proofs to check the validity of transactions from layer 2, blocks proposed by the Proposer. +Node runner: Executes transactions in the network. Both the proposer and the prover must run a node to fulfill a role in the network. +Taiko's transaction confirmation process takes place as follows: +Users make transactions on layer 2 Taiko. + +Proposer creates block rollup, synthesizes transactions from users at layer 2 and proposes to Ethereum. +Prover creates valid proof, proving the correctness of the block just submitted. +The block will then mark complete on the chain. The block status changes from green to yellow after being validated. + +## 2. Architecture and protocol overview + +_Note: to view the provided image, please see the original submission [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/253)._ + +- Block execution is deterministic once the block is appended to the proposed block list in the TaikoL1 contract. Once registered, the protocol ensures that all block properties are immutable. This makes the block execution deterministic: the post-block state can now be calculated by anyone. As such, the block is immediately verified. This also ensures that no one knows more about the latest state than anyone else, which would create an unfair advantage. +- Block metadata is validated when the block is proposed. The prover has no impact on how the block is executed and what the post-block state is; +- The proof can be generated after the block is checked for validity and its parent block’s state is known +- As all proposed blocks are deterministic, they can be proven in parallel, because all intermediate states between blocks are known and unique. Once a proof is submitted for the block and its parent block, we call the block on-chain verified. + +**1 . Block proposal** + +- Anyone can run a Taiko sequencer. It monitors the Taiko network mempool for signed and submitted txs. +- The sequencer determines the tx order in the block. +- When a block is built, the proposing sequencer submits a proposeBlock transaction (block = transaction list + metadata) directly to Ethereum through the TaikoL1 contract. There is no consensus among L2 nodes, but there is some networking between L2 nodes (syncing, sharing transactions, etc.) However, the order of Taiko blocks on Ethereum (L1) is determined by the Ethereum node. +- All Taiko nodes connect to Ethereum nodes and subscribe to Ethereum's block events. When a Taiko block proposal is confirmed, the block is appended to a queue on L1 in a TaikoL1 contract. Taiko nodes can then download these blocks and execute valid transactions in each block. Taiko nodes track which L2 blocks are verified by subscribing to another TaikoL1 event on Ethereum. + +**2. Block validation** + +- The block consists of a transaction list (txList) and metadata. The txList of an L2 block will eventually (when EIP-4844 is live) be part of a blob in the L1 Consensus Layer (CL). +- txList is not directly accessible to L1 contracts. Therefore, a ZKP shall prove that the chosen txList is a slice of the given blob data. +- Block validity criteria that all blocks need to respect: K_maxBobSize, K_BlockMaxTxs, K_BlockMaxGasLimit and config.anchorTxGasLimit +- Once the block is proposed, the Taiko client checks if the block is decoded into a list of transactions +- Taiko client validates each enclosed transaction and generates a tracelog for each transaction for the prover to use as witness data. If a tx is invalid, it will be dropped. +- The first transaction in the Taiko L2 block is always an anchoring transaction, which verifies the 256 hashes of the latest blocks, the L2 chain ID and the EIP-1559 base fee + +**3. Block proving** + +- Anyone can run a prover. +- Proof can be prepared if all valid txs have been executed; and the parent block’s state is known. The proof proves the change in the block state. +- The block can be verified once the parent block is verified; and there is a valid ZKP proving the transition from the parent state to the current block’s state. +- only the first proof will be accepted for any given block transition (fork choice). +- The address receiving the reward is coupled with the proof, preventing it from being stolen by other provers. + +**Sequencer design (sequencers are called proposers in Taiko)** + +- Based sequencing/L1-sequencing: as an Ethereum-equivalent rollup, Taiko can reuse Ethereum L1 validators to drive the sequencing of Taiko blocks, inheriting L1 liveness and decentralization. This is also called "based sequencing", or a "based rollup". More info on this: https://ethresear.ch/t/based-rollups-superpowers-from-l1-sequencing/15016 +- Based sequencing inherits the decentralization of L1 and naturally reuses L1 searcher-builder-proposer infrastructure. L1 searchers and block builders are incentivised to extract rollup MEV by including rollup blocks within their L1 bundles and L1 blocks. This then incentivises L1 proposers to include rollup blocks on the L1. + Details: + +- L2 sequencers (proposers) deliver L2 blocks (as bundles) directly to L1 builders (they act like the searchers in the L1 PBS setup). Builders take L2 blocks as regular bundles (similarly as they get L1 bundles from searchers) +- L2 sequencers will earn some MEV (here MEV includes (i) L2 block fees and (ii) MEV from txs reorgs etc.) - this is their motivation to be proposers. In the same manner as on L1, in the chain of searcher >> builder >> proposer, the proposer gets most MEV but searchers still get some share to make profits. It works the same way for L2 sequencers. +- As mentioned anyone can propose a block anytime (there are no time slots on Taiko like on Ethereum the 12-second slots) +- L2 sequencers build blocks and they compete for the most lucrative txs. Multiple blocks are proposed in parallel based on the same L2 mempool. These blocks are sent to the L1 builders as bundles, and it may happen that some transactions are included in multiple bundles proposed by L2 sequencers. +- When the L1 builders choose which L2 block to accept – they run simulations to find the most profitable bundle. If some txs in the L2 block were already taken by another builder and proposed by the Ethereum validator (this means that block already reached finality), then they are not counted in the current bundle anymore but get excluded from it. However the other L2 blocks proposed should still be valuable enough to be selected and included by an L1 builder within negligible time. +- Theoretically it could happen that most of the txs in a proposed L2 block were already included by L1 builders through other L2 blocks, and thus it is not anymore profitable, but this is expected to be a very rare, marginal case. + +**Fee structure** + +L2 tx fee = L2 EIP-1559* base fee + L1 tx fee + prover fee + proposer fee* + +_Note: to view the provided image, please see the original submission [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/253)._ + +L2 EIP-1559 fee = L2 EIP-1559 tip (goes to the proposer) + L2 EIP-1559 base fee (goes to the Taiko DAO). + +Once a proposer has collected enough transactions, most probably including and ordering them with the intent to generate a (maxim) profit, they create a block. + +- Profit means that for the proposer, the sum of transaction fees (L2 tx fees) from the block is larger than L1 tx fee + prover fee + EIP-1559 base fee. + +**Prover economics and prover mechanisms** + +1 . First prover wins and gets rewarded only +One proof should be confirmed for one “window.” A “window” is a period of time in which multiple blocks are proposed. Any prover can submit a proof for any amount of blocks at any time. + +- There is a target reward, x, that is paid to the prover if they confirm the proof exactly at the target window, t = n. If proven earlier, the reward is lower, if later, reward is higher. +- A target reward is defined based on the historical reward values and is adjusted after each window depending on the proof confirmation time + +_Note: to view the provided image, please see the original submission [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/253)._ + +- Effects: + - To be efficient within this design, a prover should be able to find an optimal trade-off point between (i) confirming the proof as late as possible (to get the higher reward) and (ii) confirming the proof earlier than all other provers. + - to confirm the proof as early as possible is not an optimal strategy for the prover; confirming all proofs as fast as possible decreases the rewards making it unreasonable for provers (but beneficial for users). + +2 . Staking-based prover design + +one prover is pseudo-randomly chosen for each block from a pool which includes the top 32 provers, and assigns it to a proposed block. This designated prover must then submit a valid proof within a set time window for block verification. If the prover fails to submit the proof on time, the prover’s stake will be slashed. Prover exit is possible anytime, with a withdrawal time of one week. + +- Prover weight W is calculated based on the stake A and expected reward per gas R. This weight reflects probability to be chosen. + +_Note: to view the provided image, please see the original submission [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/253)._ + +- The current fee per gas F is calculated based on historical values and is supplied by the core protocol. +- Three other parameters unique for each prover; claimed while joining the pool: + + 1. Amount of Taiko’s TTKO tokens to stake A; + 2. The expected reward per gas, R, is limited to (75% – 125%) _ F range. If the R claimed by the prover is below or above this range, R will be automatically fixed at 75% _ F or 125% \* F, respectively; + 3. The compute capacity specified by the prover + + - If selected, the capacity reduces by one, and + - when the capacity hits zero, the prover will no longer be selected. + - When a block is proven (by them or any other prover), the capacity increases by one, up to the max capacity specified by the prover during staking. + +- If fails to prove the block within a specific time window, the prover gets slashed; +- If the prover failed to prove the block or there is no available prover at the moment to be assigned, any prover can jump in and prove the block. Such a block is considered an “open block”; +- If the block was proven, the prover reward is R \* gasUsed. +- the oracle prover cannot prove/verify blocks directly and thus cannot change the chain state. Therefore, a regular prover will need to generate a ZKP to prove the overridden fork choice. + +3. PBS-inspired proposing and proving design + +There are two ways to assign a block to a prover: + +- If you run a Taiko-node as a proposer or prover, your proposer will select your own local prover by default (left side of the below screenshot), and this prover has to provide a bond of 2.5 TKO as assurance for generating the proof +- proposers can also choose any prover from the open prover market. Proposers send a hash of the L2 block’s transaction list to an open market of provers, who offer a price that they’re willing to provide a bond of 2.5 TKO for (right side of the below screenshot); proposers pay their provers off-chain. + +_Note: to view the provided image, please see the original submission [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/253)._ + +When an agreement is reached concerning the proving fee for a specific block, the chosen proof service provider is then granting a cryptographic signature to the proposer which serves as a binding commitment to deliver the proof within the agreed-upon timeframe. + +Provers within this off-chain proof market come in two primary forms: Externally Owned Accounts (EOA) and contracts, often referred to as Prover pools. The reward depends on the proof service provider and the agreement. For EOAs and Prover pools that implement the IERC1271 interface, the reward is disbursed in ETH. However, in cases where providers implement the IProver interface, the prover fee can be ETH, any other ERC20 tokens, or even NFTs, based on the negotiated terms. + +_Note: to view the provided image, please see the original submission [here](https://github.com/code-423n4/2024-03-taiko-findings/issues/253)._ + +In the event of a failure to deliver the proof within the given time, 1/4 of the bond provided, is directed to the actual prover, while the remaining 3/4 are permanently burnt. Conversely, successful and timely proof delivery ensures the return of these tokens to the Prover. + +### How taiko L1 Works?? + +Taiko is a Layer 2 optimistic rollup solution for Ethereum that aims to provide fast and low-cost transactions while maintaining the security guarantees of the Ethereum network. The L1 part of Taiko plays a crucial role in managing the communication between Layer 2 and the Ethereum mainnet (Layer 1) and ensuring the validity of the L2 state. + +**Here is an overview of how Taiko L1 works**: + +- **Sequencer Selection**: The L1 Taiko contract selects a sequencer responsible for processing and ordering L2 transactions. The sequencer is chosen based on the highest total ETH staked, and the contract ensures that only one sequencer is active at any given time. +- **Transaction Relay**: When users submit transactions to Layer 2, they are first sent to the Taiko L1 contract. The L1 contract checks whether the sequencer has been properly initialized and then forwards the transaction to the sequencer. +- **L2 Block Creation**: The sequencer collects and orders transactions into L2 blocks, performs any necessary state updates, and then generates a merkle root. +- **Block Submission**: The sequencer then submits the L2 block to the L1 contract, along with the new merkle root and necessary metadata. The L1 contract checks whether the submitted block is valid and updates its records accordingly. +- **Dispute Resolution**: In case of a dispute about the validity of an L2 block, anyone can call the dispute function in the L1 contract. This initiates a challenge period, during which parties can submit evidence to either support or dispute the block's validity. If a dispute is successfully resolved, the L1 contract updates the state accordingly. + +Overall, the L1 component of Taiko plays a crucial role in managing the L2 sequencer, facilitating communication and state transitions between L1 and L2, and ensuring the overall security of the system. + +### How taiko L2 Works?? + +Taiko's Layer 2 (L2) is an optimistic rollup solution for Ethereum that aims to provide fast and low-cost transactions while maintaining the security guarantees of the Ethereum network. In a nutshell, the L2 solution bundles transactions into batches and processes them off-chain, only posting the bundles and any necessary proofs on-chain to maintain security and maintain a consistent state. + +**Here's an overview of how Taiko's L2 works**: + +- **Transaction Submission**: Users submit transactions to the sequencer, which collects and orders transactions into L2 blocks. +- **State Transition**: The sequencer performs any necessary state updates in accordance with the L2 transactions it receives and the current L2 state. The sequencer generates a merkle root to represent the updated L2 state and submits the block along with the merkle root and other metadata to the L1 contract. +- **State Validation**: The L1 contract validates the submitted L2 block by checking its merkle root against the previous L2 state and evaluating any necessary fraud proofs. If the L1 contract deems the L2 block valid, it updates its records to reflect the new L2 state. +- **Dispute Resolution**: In case of a dispute about the validity of an L2 block, anyone can submit a challenge within a certain time period, during which evidence can be submitted to either support or dispute the block's validity. If a dispute is successfully resolved, the L1 contract updates the state accordingly. +- **Withdrawals**: Users can withdraw their assets from the L2 contract to the L1 contract by submitting a withdraw request to the L2 contract and waiting for a predetermined challenge period to elapse. Once the challenge period has passed, the funds are transferred to the user's L1 address. + +Overall, Taiko L2 offers a fast and cost-effective way to process transactions off-chain and only post the necessary information on-chain to maintain security and consistency. The L2 contract submits blocks to the L1 contract, and the L1 contract is responsible for validating the L2 blocks and maintaining the overall system security. + +## 3. Scope Contracts + +1 . contracts/common/ + +- [common/IAddressManager.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/IAddressManager.sol) +- [common/AddressManager.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/AddressManager.sol) +- [common/IAddressResolver.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/IAddressResolver.sol) +- [common/AddressResolver.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/AddressResolver.sol) +- [common/EssentialContract.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/EssentialContract.sol) + +2 . contracts/libs/ + +- [libs/Lib4844.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/Lib4844.sol) +- [libs/LibAddress.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/LibAddress.sol) +- [libs/LibMath.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/LibMath.sol) +- [libs/LibTrieProof.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/LibTrieProof.sol) + +3. contracts/L1/ + +- [L1/gov/TaikoGovernor.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/gov/TaikoGovernor.sol) +- [L1/gov/TaikoTimelockController.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol) +- [L1/hooks/IHook.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/hooks/IHook.sol) +- [L1/hooks/AssignmentHook.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/hooks/AssignmentHook.sol) +- [L1/ITaikoL1.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/ITaikoL1.sol) +- [L1/libs/LibDepositing.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibDepositing.sol) +- [L1/libs/LibProposing.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibProposing.sol) +- [L1/libs/LibProving.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibProving.sol) +- [L1/libs/LibUtils.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibUtils.sol) +- [L1/libs/LibVerifying.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibVerifying.sol) +- [GuardianProver.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/provers/GuardianProver.sol) +- [L1/provers/Guardians.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/provers/Guardians.sol) +- [L1/TaikoData.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoData.sol) +- [L1/TaikoErrors.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoErrors.sol) +- [L1/TaikoEvents.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoEvents.sol) +- [L1/TaikoL1.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoL1.sol) +- [L1/TaikoToken.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoToken.sol) +- [L1/tiers/ITierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/ITierProvider.sol) +- [L1/tiers/DevnetTierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol) +- [L1/tiers/MainnetTierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol) +- [L1/tiers/TestnetTierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol) + +4. contracts/L2/ + +- [L2/CrossChainOwned.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/CrossChainOwned.sol) +- [L2/Lib1559Math.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/Lib1559Math.sol) +- [L2/TaikoL2.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2.sol) +- [L2/TaikoL2EIP1559Configurable.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol) + +5. contracts/signal/ + +- [signal/ISignalService.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/signal/ISignalService.sol) +- [signal/LibSignals.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/signal/LibSignals.sol) +- [signal/SignalService.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/signal/SignalService.sol) + +6. contracts/bridge/ + +- [bridge/IBridge.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/IBridge.sol) +- [bridge/Bridge.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol) + +7. contracts/tokenvault/ + +- [tokenvault/adapters/USDCAdapter.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol) +- [tokenvault/BridgedERC20.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC20.sol) +- [tokenvault/BridgedERC20Base.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol) +- [tokenvault/BridgedERC721.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC721.sol) +- [tokenvault/BridgedERC1155.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC1155.sol) +- [tokenvault/BaseNFTVault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BaseNFTVault.sol) +- [tokenvault/BaseVault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BaseVault.sol) +- [tokenvault/ERC1155Vault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC1155Vault.sol) +- [tokenvault/ERC20Vault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC20Vault.sol) +- [tokenvault/ERC721Vault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC721Vault.sol) +- [tokenvault/IBridgedERC20.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/IBridgedERC20.sol) +- [tokenvault/LibBridgedToken.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/LibBridgedToken.sol) + +8. contracts/thirdparty/ + +- [thirdparty/nomad-xyz/ExcessivelySafeCall.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol) +- [thirdparty/optimism/Bytes.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/Bytes.sol) +- [thirdparty/optimism/rlp/RLPReader.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol) +- [thirdparty/optimism/rlp/RLPWriter.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol) +- [thirdparty/optimism/trie/MerkleTrie.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol) +- [thirdparty/optimism/trie/SecureMerkleTrie.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol) +- [thirdparty/solmate/LibFixedPointMath.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/solmate/LibFixedPointMath.sol) + +9. contracts/verifiers/ + +- [verifiers/IVerifier.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/verifiers/IVerifier.sol) +- [verifiers/GuardianVerifier.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/verifiers/GuardianVerifier.sol) +- [verifiers/SgxVerifier.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/verifiers/SgxVerifier.sol) + +10. contracts/team/ + +- [team/airdrop/ERC20Airdrop.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol) +- [team/airdrop/ERC20Airdrop2.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol) +- [team/airdrop/ERC721Airdrop.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol) +- [team/airdrop/MerkleClaimable.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol) +- [team/TimelockTokenPool.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/TimelockTokenPool.sol) + +11. contracts/automata-attestation/ + +- [automata-attestation/AutomataDcapV3Attestation.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol) +- [automata-attestation/interfaces/IAttestation.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol) +- [automata-attestation/interfaces/ISigVerifyLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/interfaces/ISigVerifyLib.sol) +- [automata-attestation/lib/EnclaveIdStruct.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol) +- [automata-attestation/lib/interfaces/IPEMCertChainLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/interfaces/IPEMCertChainLib.sol) +- [automata-attestation/lib/PEMCertChainLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol) +- [automata-attestation/lib/QuoteV3Auth/V3Parser.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol) +- [automata-attestation/lib/QuoteV3Auth/V3Struct.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol) +- [automata-attestation/lib/TCBInfoStruct.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/TCBInfoStruct.sol) +- [automata-attestation/utils/Asn1Decode.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol) +- [automata-attestation/utils/BytesUtils.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol) +- [automata-attestation/utils/RsaVerify.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol) +- [automata-attestation/utils/SHA1.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/SHA1.sol) +- [automata-attestation/utils/SigVerifyLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol) +- [automata-attestation/utils/X509DateUtils.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol) + +## 4. Codebase Analysis + +### 4.1 Approach Taken reviewing the codebase + +First, by examining the scope of the code, I determined my code review and analysis strategy. +https://code4rena.com/audits/2024-03-taiko#top +My approach to ensure a thorough and comprehensive audit would encompass several steps, combining theoretical understanding, practical testing, and security assessments. Here’s how I would proceed: + +- **Understanding the Taiko Protocol**: I familiarized myself with the Taiko protocol and its components, focusing on the Layer 2 (L2) aspects. L2 solutions provide enhanced scalability and privacy features to the Ethereum blockchain. The Taiko protocol combines several L2 techniques, such as optimistic and zero-knowledge rollups, and validity proof systems. + +- **Exploring the Codebase**: I explored the Taiko smart contract codebase available on GitHub to understand the different components and contract interactions. The codebase mainly consists of the following categories: + + - Core: Core contracts related to the L2 infrastructure, such as TaikoL1, TaikoL2, L1ERC20Bridge, and others. + - Verifiers: Contracts responsible for verifying the validity proofs, such as GuardianVerifier and SgxVerifier. + - Tokens: Token-related contracts, including ERC-20 and ERC-721 bridges. + - Third-party libraries/contracts: Libraries and third-party contracts from OpenZeppelin, Solmate, and others. + - Airdrops, timelocks, and other team-related contracts: Contracts dealing with airdrops, token vesting, and other team-related applications. + +- **Dependency Analysis**: I examined the external dependencies used in the contracts, such as OpenZeppelin and Solmate, ensuring they were up-to-date and compatible with the codebase. + +- **Code Quality Review**: I checked the code for proper formatting, naming conventions, and overall readability. I also ensured that the code followed best practices for secure development, minimizing complexity where possible, and making contract interactions modular and clear. + +- **Security Analysis**: I manually inspected the contracts and used automated tools to identify potential security issues, including: + + - Reentrancy + - Integer overflows/underflows + - Front-running opportunities + - Race conditions + - Denial-of-Service (DoS) attacks + - Privilege escalation + - Visibility issues + +- **Testing**: I reviewed the test coverage and ensured that the tests were comprehensive, testing various scenarios, boundary cases, and potential attack vectors. + +- **Audit Findings and Recommendations**: I reviewed audit reports related to the Taiko protocol to ensure that previously identified issues were addressed. + +### 4.2 Contracts Overview + +1 . [common/IAddressManager.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/IAddressManager.sol) +This is an interface defining common functions for managing addresses, such as adding or removing an address from a whitelist or blacklist. + +2. [common/AddressManager.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/AddressManager.sol) + This is an implementation of the IAddressManager interface. It manages a set of addresses and maintains separate whitelists and blacklists. The contract has internal functions for adding/removing addresses from both lists, as well as functions for getting the total number of addresses and checking membership on the lists. + +3. [common/IAddressResolver.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/IAddressResolver.sol) + This is an interface for a contract that resolves addresses, essentially mapping deployment addresses (i.e., contract or token addresses) to other information that the protocol requires. + +4. [common/AddressResolver.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/AddressResolver.sol) + This is an implementation of the IAddressResolver interface. It can resolve the addresses based on the name of the required contract. The contract maintains a mapping between the contract name and the actual deployment address, and exposes functions for adding, updating, and removing contract mappings, as well as resolving the contract address. + +5. [common/EssentialContract.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/common/EssentialContract.sol) + This is a base contract for other protocol contracts to inherit. It ensures that the implementing contract is initialized properly and provides access to essential protocol functionality. The contract defines an interface for a two-step setup process, which includes initialization (performed once at deployment) and activation (performed after deployment). Additionally, the contract includes functions for checking initialization and activation status, as well as a mechanism for upgrading the contract. + +6. [libs/Lib4844.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/Lib4844.sol) + This library provides helper functions for interacting with the 4844 network: an optimistic rollup network built on top of the Ethereum blockchain. The library includes methods for calculating the storage root, adding logger, and constructing and validating transaction proofs. These utility functions simplify 4844-related logic in the main Taiko protocol contracts, making it easier to perform tasks that involve the 4844 network, such as fetching and validating transaction proofs from the rollup network. + +7. [libs/LibAddress.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/LibAddress.sol) + This library provides functions for handling Ethereum addresses. It includes several helper functions to deal with ENS names, checking if an address is a contract, and performing common address operations like sending and approving tokens. This library helps keep address-related functions reusable, simplified, and consistent across the entire protocol. + +8. [libs/LibMath.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/LibMath.sol) + This library provides various mathematical operations, particularly related to fixed-point numbers and division. It includes functions for safe division, fractional multiplication, and other useful arithmetic operations that are required throughout the Taiko protocol. + +9. [libs/LibTrieProof.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/libs/LibTrieProof.sol) + This library is specifically designed for Merkle Trie proof functions, which are essential when working with Ethereum's state trie. This library provides functions to create and validate merkle paths as well as perform range proofs. The functions can be used to efficiently check the state root stored in 4844 blocks and entries in associated Merkle Tries. + +10. [L1/gov/TaikoGovernor.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/gov/TaikoGovernor.sol) + This contract is the governance contract for the Taiko protocol on L1. It allows for the creation and management of proposals, as well as the ability to queue and execute actions. It inherits from TaikoTimelockController.sol, which provides a timelock mechanism for actions being executed. + +11. [L1/gov/TaikoTimelockController.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol) + This contract is responsible for implementing a timelock mechanism for the Taiko protocol on L1. It allows for actions to be queued and then executed after a specified delay. It also provides functionality for cancelling queued actions. + +12. [L1/hooks/IHook.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/hooks/IHook.sol) + This contract is an interface for hooks, which are contracts that can be called before or after certain actions in the Taiko protocol. + +13. [L1/hooks/AssignmentHook.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/hooks/AssignmentHook.sol) + This contract is an implementation of the IHook interface and is used to handle the assignment of roles and permissions in the Taiko protocol. + +14. [L1/ITaikoL1.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/ITaikoL1.sol) + This contract is an interface for the Taiko L1 contract, which is the main contract for the Taiko protocol on L1. It includes functionality for creating and managing proposals, as well as handling deposits and withdrawals. + +15. [L1/libs/LibDepositing.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibDepositing.sol) + This contract contains library functions for handling deposits in the Taiko protocol. It includes functions for calculating the correct deposit amount, as well as handling the actual deposit of funds. + +16. [L1/libs/LibProposing.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibProposing.sol) + This contract contains library functions for handling proposals in the Taiko protocol. It includes functions for calculating the number of votes needed to pass a proposal, as well as functions for handling the execution of proposals. + +17. [L1/libs/LibProving.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibProving.sol) + This contract contains library functions for proof generation and verification in the Taiko protocol. + +18. [L1/libs/LibUtils.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibUtils.sol) + This contract contains library functions for various utility functions used throughout the Taiko protocol. + +19. [L1/libs/LibVerifying.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/libs/LibVerifying.sol) + This contract contains library functions for verifying signatures and messages in the Taiko protocol. + +20. [GuardianProver.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/provers/GuardianProver.sol) + This contract is responsible for generating proofs required for certain actions in the Taiko protocol. It uses the Guardians.sol contract to generate these proofs. + +21. [L1/provers/Guardians.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/provers/Guardians.sol) + This contract manages a list of guardians who are responsible for generating proofs required for certain actions in the Taiko protocol. + +22. [L1/TaikoData.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoData.sol) + This contract contains various data structures used throughout the Taiko protocol. + +23. [L1/TaikoErrors.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoErrors.sol) + This contract contains custom errors used throughout the Taiko protocol. + +24. [L1/TaikoEvents.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoEvents.sol) + This contract contains event definitions used throughout the Taiko protocol. + +25. [L1/TaikoL1.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoL1.sol) + This contract is the main contract for the Taiko protocol on L1 and is responsible for managing proposals, handling deposits and withdrawals, and interfacing with the TaikoTimelockController.sol contract. + +26. [L1/TaikoToken.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/TaikoToken.sol) + This contract is an ERC20 token used for voting in the Taiko protocol. + +27. [L1/tiers/ITierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/ITierProvider.sol) + This contract is an interface for tier providers, which are contracts that provide information about the current tier of a given address. + +28. [L1/tiers/DevnetTierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/DevnetTierProvider.sol) + This contract is an implementation of the ITierProvider interface for the devnet environment. + +29. [L1/tiers/MainnetTierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/MainnetTierProvider.sol) + This contract is an implementation of the ITierProvider interface for the mainnet environment. + +30. [L1/tiers/TestnetTierProvider.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L1/tiers/TestnetTierProvider.sol) + This contract is an implementation of the ITierProvider interface for the testnet environment. + +31. [L2/CrossChainOwned.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/CrossChainOwned.sol) + This contract is an implementation of the Owned pattern, where the contract owner can transfer ownership to another address. It also includes a function to force a contract upgrade by specifying the address of the new implementation. + +32. [L2/Lib1559Math.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/Lib1559Math.sol) + This library contains mathematical functions related to Ethereum's EIP-1559 upgrade. It includes functions to calculate the base fee, maximum base fee per gas, and gas tip cap. + +33. [L2/TaikoL2.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2.sol) + This contract is the main L2 contract responsible for handling transactions, storing the state root, and interacting with the L1 contract via the bridge. It includes functionalities for transaction submission, state transition, and state proof verification. + +34. [L2/TaikoL2EIP1559Configurable.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/L2/TaikoL2EIP1559Configurable.sol) + This contract is similar to TaikoL2 but is EIP-1559 compatible. It includes functions to set the base fee, gas tip cap, and other related parameters. + +35. [signal/ISignalService.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/signal/ISignalService.sol) + This is an interface contract for the SignalService. It provides function declarations for emitting and canceling signals. + +36. [signal/LibSignals.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/signal/LibSignals.sol) + This library contract contains functions for creating and managing signals. It includes functions for creating signals, canceling signals, and checking the status of signals. + +37. [signal/SignalService.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/signal/SignalService.sol) + This contract is the main SignalService implementation. It enables users to create and cancel signals, while also tracking the status and expiry of signals. + +38. [bridge/IBridge.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/IBridge.sol) + This is an interface contract for the Bridge. It contains function declarations for L1-L2 transaction handling and state syncing. + +39. [bridge/Bridge.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/bridge/Bridge.sol) + This contract is the main Bridge implementation. It facilitates the transfer of messages between L1 and L2, ensuring the atomicity and consistency of the state between the two layers. Additionally, it includes functionalities for handling cross-layer transactions, applying penalties for invalid transactions, and syncing L1 and L2 states. + +40. [tokenvault/adapters/USDCAdapter.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/adapters/USDCAdapter.sol) + This contract is an adapter for the USDC token. It inherits from IBridgedERC20, which is an interface for bridged ERC20 tokens. The contract includes two functions: name and symbol, which return the name and symbol of the USDC token. + +41. [tokenvault/BridgedERC20.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC20.sol): + This contract is an implementation of the IBridgedERC20 interface. It is a bridged version of the ERC20 standard that allows for transferring tokens between different blockchain networks. The contract includes functionality for transferring tokens, approving other contracts to transfer tokens, and getting the allowance that an owner has granted to a spender. + +42. [tokenvault/BridgedERC20Base.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC20Base.sol) + This contract is the base contract for BridgedERC20. It includes the basic functionality for bridged tokens, such as transferring tokens, approving other contracts to transfer tokens, and getting allowances. + +43. [tokenvault/BridgedERC721.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC721.sol) + This contract is an implementation of the ERC721 standard for non-fungible tokens (NFTs) that allows for transferring NFTs between different blockchain networks. The contract includes functionality for transferring NFTs, approving other contracts to transfer NFTs, and getting the approval status for a given NFT. + +44. [tokenvault/BridgedERC1155.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BridgedERC1155.sol) + This contract is an implementation of the ERC1155 standard for multi-token contracts that allows for transferring multiple tokens between different blockchain networks. The contract includes functionality for transferring tokens, approving other contracts to transfer tokens, and getting allowances for multiple tokens. + +45. [tokenvault/BaseNFTVault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BaseNFTVault.sol) + This contract is a base contract for NFT vaults. It includes basic functionality for NFT vaults, such as storing NFTs and transferring them out of the vault. + +46. [tokenvault/BaseVault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/BaseVault.sol) + This contract is a base contract for token vaults. It includes basic functionality for token vaults, such as storing tokens and transferring them out of the vault. + +47. [tokenvault/ERC1155Vault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC1155Vault.sol) + This contract is a vault for ERC1155 tokens that allows for transferring multiple tokens between different blockchain networks. It inherits from BridgedERC1155, which implements the ERC1155 standard. + +48. [tokenvault/ERC20Vault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC20Vault.sol) + This contract is a vault for ERC20 tokens that allows for transferring tokens between different blockchain networks. It inherits from BridgedERC20Base. + +49. [tokenvault/ERC721Vault.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/ERC721Vault.sol) + This contract is a vault for ERC721 tokens that allows for transferring NFTs between different blockchain networks. It inherits from BridgedERC721. + +50. [tokenvault/IBridgedERC20.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/IBridgedERC20.sol) + This contract is an interface for bridged ERC20 tokens. It includes the basic functionality for transferring tokens, approving other contracts to transfer tokens, and getting allowances. + +51. [tokenvault/LibBridgedToken.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/tokenvault/LibBridgedToken.sol) + This contract is a library for BridgedERC20, BridgedERC721, and BridgedERC1155. It includes common functionality for bridged tokens, such as managing metadata. + +52. [thirdparty/nomad-xyz/ExcessivelySafeCall.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/nomad-xyz/ExcessivelySafeCall.sol) + This contract is a simple library that provides a safe way to call external contracts without worrying about reentrancy attacks. It uses a pattern called the "Reentrancy Guard" to ensure that a contract can only be called once within a given execution context. This is useful for situations where a contract needs to make an external call that could potentially modify its state. + +53. [thirdparty/optimism/Bytes.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/Bytes.sol) + This contract is a simple library that provides a number of utility functions for working with byte arrays in Solidity. It includes functions for checking the length of a byte array, slicing a byte array, and concatenating multiple byte arrays together. + +54. [thirdparty/optimism/rlp/RLPReader.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/rlp/RLPReader.sol) + This contract is a library that provides functions for parsing Recursive Length Prefix (RLP) encoded data. RLP is a binary data format used in Ethereum to encode structured data. This library provides functions for decoding RLP-encoded data into Solidity data types, such as integers, byte arrays, and arrays of other data types. + +55. [thirdparty/optimism/rlp/RLPWriter.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/rlp/RLPWriter.sol) + This contract is a library that provides functions for encoding data into Recursive Length Prefix (RLP) format. It can be used to encode Solidity data types, such as integers, byte arrays, and arrays of other data types, into RLP format. + +56. [thirdparty/optimism/trie/MerkleTrie.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/trie/MerkleTrie.sol) + This contract is a library that provides an implementation of a Merkle tree. A Merkle tree is a binary tree data structure that allows for efficient and secure verification of large datasets. This library provides functions for creating a Merkle tree, adding data to the tree, and verifying the integrity of the tree. + +57. [thirdparty/optimism/trie/SecureMerkleTrie.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/optimism/trie/SecureMerkleTrie.sol) + This contract is a library that provides a secure implementation of a Merkle tree. It is similar to the MerkleTrie library, but includes additional security measures to prevent against attacks such as hash collisions. + +58. [thirdparty/solmate/LibFixedPointMath.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/thirdparty/solmate/LibFixedPointMath.sol) + This contract is a library that provides functions for performing arithmetic operations with fixed-point numbers. Fixed-point numbers are a way of representing decimal values in a binary format, and are commonly used in blockchain applications for representing values such as token balances. This library provides functions for adding, subtracting, multiplying, and dividing fixed-point numbers. + +59. [verifiers/IVerifier.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/verifiers/IVerifier.sol) + This contract is an interface for verifiers. It defines the functions that a verifier contract must implement. + +60. [verifiers/GuardianVerifier.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/verifiers/GuardianVerifier.sol) + This contract is a verifier that uses a "guardian" contract to verify the correctness of transactions. The guardian contract is responsible for checking the state of the Taiko protocol and ensuring that transactions are valid. + +61. [verifiers/SgxVerifier.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/verifiers/SgxVerifier.sol) + This contract is a verifier that uses Intel Software Guard Extensions (SGX) to verify the correctness of transactions. SGX is a hardware-based technology that allows for secure execution of code in an enclave environment. This verifier uses SGX to ensure that transactions are not tampered with. + +62. [team/airdrop/ERC20Airdrop.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop.sol) + This contract is used for distributing a fixed number of tokens to a list of recipients. It is an implementation of the ERC20 token standard. + +63. [team/airdrop/ERC20Airdrop2.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC20Airdrop2.sol) + This contract is similar to ERC20Airdrop, but allows for the possibility of distributing additional tokens in the future. + +64. [team/airdrop/ERC721Airdrop.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/ERC721Airdrop.sol) + This contract is used for distributing a fixed number of non-fungible tokens to a list of recipients. It is an implementation of the ERC721 token standard. + +65. [team/airdrop/MerkleClaimable.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/airdrop/MerkleClaimable.sol) + This contract is a library that provides functions for generating and verifying Merkle proofs. It can be used to allow users to claim tokens or other assets by proving that they are entitled to them. + +66. [team/TimelockTokenPool.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/team/TimelockTokenPool.sol) + This contract is used for holding a pool of tokens that are subject to a time lock. This can be useful for distributing tokens to a team or community over a period of time. + +67. automata-attestation/AutomataDcapV3Attestation.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol) + This contract is the main contract in the automata-attestation directory. It is responsible for verifying attestation Quote V3 from Intel SGX enclaves. The contract uses several libraries and interfaces to perform the verification, including IAttestation, ISigVerifyLib, IPEMCertChainLib, and QuoteV3Auth. + +68. [automata-attestation/interfaces/IAttestation.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/interfaces/IAttestation.sol) + This is an interface contract that defines the required functions for attestation. It includes functions for getting the quote from an enclave and verifying the quote. + +69. [automata-attestation/interfaces/ISigVerifyLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/interfaces/ISigVerifyLib.sol) + This is an interface contract that defines the required functions for signature verification. It includes functions for verifying ECDSA and RSA signatures. + +70. [automata-attestation/lib/EnclaveIdStruct.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol) + This contract defines a struct for storing enclave ID information. + +71. [automata-attestation/lib/interfaces/IPEMCertChainLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/interfaces/IPEMCertChainLib.sol) + This is an interface contract that defines the required functions for working with a chain of Platform Error Management Certificates (PEMCertChain). It includes functions for getting the root certificate and verifying the chain. + +72. [automata-attestation/lib/PEMCertChainLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/PEMCertChainLib.sol) + This contract implements the IPEMCertChainLib interface and provides functionality for working with a chain of PEMCertificates. + +73. [automata-attestation/lib/QuoteV3Auth/V3Parser.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Parser.sol) + This contract is a library contract that provides functionality for parsing Quote V3 from Intel SGX enclaves. + +74. [automata-attestation/lib/QuoteV3Auth/V3Struct.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/QuoteV3Auth/V3Struct.sol) + This contract defines a struct for storing Quote V3 information. + +75. [automata-attestation/lib/TCBInfoStruct.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/lib/TCBInfoStruct.sol) + This contract defines a struct for storing Trusted Computing Base (TCB) information. + +76. [automata-attestation/utils/Asn1Decode.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/Asn1Decode.sol) + This contract is a library contract that provides functionality for decoding ASN.1 encoded data. + +77. [automata-attestation/utils/BytesUtils.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/BytesUtils.sol) + This contract is a library contract that provides functionality for working with bytes, including concatenating, slicing, and checking lengths. + +78. [automata-attestation/utils/RsaVerify.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/RsaVerify.sol) + This contract is a library contract that provides functionality for verifying RSA signatures. + +79. [automata-attestation/utils/SHA1.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/SHA1.sol)This contract is a library contract that provides SHA-1 hashing functionality. + +80. [automata-attestation/utils/SigVerifyLib.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/SigVerifyLib.sol) + This contract is a library contract that provides signature verification functionality, including ECDSA and RSA. + +81. [automata-attestation/utils/X509DateUtils.sol](https://github.com/code-423n4/2024-03-taiko/blob/main/packages/protocol/contracts/automata-attestation/utils/X509DateUtils.sol) + This contract is a library contract that provides functionality for working with X.509 dates, including parsing and comparing. + +### 4.3 Codebase Quality Analysis + +| Aspect | Description | +| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Architecture and Design | | +| Upgradeability | The contracts/L1/gov/TaikoGovernor.sol and contracts/L1/gov/TaikoTimelockController.sol contracts have a version variable that allows for upgrades. The rest of the contracts do not have upgradeability features. | +| Modularity | The codebase is divided into several directories, each containing related contracts. This modular structure helps to organize the code and makes it easier to navigate. | +| Testability | The contracts/L1/TaikoData.sol contract provides a getTestData() function that returns test data for use in testing. This is a good practice for making code more testable. | +| Security | | +| Authorization | The contracts/L1/gov/TaikoGovernor.sol contract uses role-based access control to restrict certain functions to specific addresses. This is a good practice for preventing unauthorized access. | +| Input Validation | The contracts/L1/libs/LibMath.sol contract provides functions for validating input values, such as isUint and isAddr. These functions should be used throughout the codebase to ensure that inputs are valid before being processed. | +| Auditability | | +| Comments | Comments are used throughout the codebase to explain the code and provide additional information. This is a good practice for making code more readable and understandable. | +| Naming Conventions | Consistent naming conventions are used throughout the codebase. This helps to quickly identify and understand the code. | +| Code Complexity | The codebase has a mix of simple and complex functions. Simple functions are generally easier to understand and audit, while complex functions can be more difficult to follow. | +| Error Handling | The contracts/L1/TaikoErrors.sol contract provides a standardized way of handling errors throughout the codebase. This is a good practice for ensuring that errors are handled consistently and that the code remains readable. | +| Documentation | | +| Codebase Overview | A high-level overview of the codebase would be helpful for quickly understanding the structure and organization of the code. This could include a diagram or chart showing the relationships between the different contracts and directories. | +| Contract Documentation | Each contract should have detailed documentation that explains its purpose, functionality, and any relevant variables or functions. This documentation should be easily accessible from the code itself, either through comments or separate documentation files. | +| Function Documentation | Each function should have detailed documentation that explains its purpose, functionality, and any relevant input and output parameters. This documentation should be easily accessible from the code itself, either through comments or separate documentation files. | +| Global Variables | Global variables that are used throughout the codebase should be documented in a central location. This helps to ensure that they are used consistently and that their purpose is clear. | +| Security Best Practices | The codebase should follow well-established security best practices, such as using secure coding practices and performing regular security audits. This helps to ensure that the code remains secure and up-to-date with the latest threats and vulnerabilities. | + +### 4.5 Contracts Workflow + +| Contracts | Category | Core Functionality | Technical Details | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------ | +| IAddressResolver, AddressResolver | Common | Address resolution for L1 and L2 contracts | Uses a trie data structure to efficiently store and retrieve addresses | +| IHook, AssignmentHook | L1 Hooks | Allows L1 contracts to be notified of specific events | Provides a flexible system for triggering callbacks from L1 contracts | +| ITaikoL1 | L1 Contracts | Main L1 contract that orchestrates L1 operations | Contains logic for L1 deposits, proposals, proving, and verifying | +| LibDepositing, LibProposing, LibProving, LibUtils, LibVerifying | L1 Libraries | Various utility functions for L1 contracts | Provides functionality for deposit calculations, proposing, proving, and verifying | +| GuardianProver, Guardians | L1 Provers | Manages secure enclaves for proof verification | Provides an interface for secure enclave communication and verification | +| TaikoData, TaikoErrors, TaikoEvents, TaikoL1, TaikoToken | L1 Contracts | Core L1 contracts for Taiko | Contains logic for L1 errors, events, and token management | +| IBridge, Bridge | Bridge | Manages L1 to L2 token transfers | Provides an interface for L1 to L2 token bridging | +| IVerifier, GuardianVerifier, SgxVerifier | Verifiers | Verifies L2 state transitions | Provides an interface for verifying L2 state transitions using Secure Enclaves or SGX technology | +| CrossChainOwned | L2 Contracts | Provides cross-chain ownership management | Facilitates cross-chain contract interaction and ownership management | +| Lib1559Math, TaikoL2, TaikoL2EIP1559Configurable, TaikoL1, TaikoL2, TaikoEvents | L2 Contracts | Core L2 contracts for Taiko | Contains logic for L2 token management, transactions, and events | +| ISignalService, LibSignals, SignalService | Signal Service | Manages signal services for Taiko | Provides an interface for various signal services and library functions | +| USDCAdapter | Token Vaults | Manages the USDC token vault | Provides functionality for depositing and withdrawing USDC tokens | +| BridgedERC20, BridgedERC20Base, BridgedERC721, BridgedERC1155, BaseNFTVault, BaseVault, ERC1155Vault, ERC20Vault, ERC721Vault, IBridgedERC20, LibBridgedToken | Token Vaults | Various token vault and adapter contracts | Provides functionality for depositing and withdrawing various ERC token standards | +| ExcessivelySafeCall, Bytes, RLPReader, RLPWriter, MerkleTrie, SecureMerkleTrie, LibFixedPointMath | Third Party Contracts and Libraries | Various contracts and libraries from third parties | Provides various functionality for third party contracts and libraries | +| IVerifier | Verifiers | Verifies L2 state transitions | Provides an interface for verifying L2 state transitions using Secure Enclaves or SGX technology | + +## 5. Economic Model Analysis + +| Variable Name | Description | Economic Impact | +| ----------------- | --------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| depositFee | Fee charged for depositing assets. | Determines the revenue generated by the protocol for handling deposits. High deposit fees encourage more protocol revenue but may discourage users from depositing. | +| withdrawalFee | Fee charged for withdrawing assets. | Determines the revenue generated by the protocol for handling withdrawals. High withdrawal fees may discourage users from withdrawing. | +| crossChainFee | Fee charged for cross-chain transactions. | Determines the revenue generated by the protocol for facilitating cross-chain transactions. High cross-chain fees may discourage users from using the cross-chain feature. | +| proposerFee | Fee charged for proposing blocks. | Determines the revenue generated by the protocol for handling block proposals. High proposer fees may discourage users from proposing blocks. | +| guardianFee | Fee charged for verifying blocks. | Determines the revenue generated by the protocol for handling block verifications. High guardian fees may discourage users from verifying blocks. | +| L1GasPrice | Gas price on the L1 chain. | Determines the cost of executing transactions and smart contracts on the L1 chain. High gas prices may discourage users from using the L1 chain. | +| L2GasPrice | Gas price on the L2 chain. | Determines the cost of executing transactions and smart contracts on the L2 chain. High gas prices may discourage users from using the L2 chain. | +| rewardsPerBlock | Rewards distributed per block. | Determines the incentives for users to participate in the protocol, such as proposing and verifying blocks. High rewards encourage more participation but may reduce overall revenue. | +| tokenEmissionRate | Rate at which new tokens are generated. | Determines the inflation rate of the token and the dilution of existing token holders. High emission rates lead to rapid inflation and token dilution. | +| minimumDeposit | Minimum deposit amount. | Determines the minimum amount required for users to participate in the protocol. Low minimum deposits encourage more participation, but may also reduce overall security. | +| maximumDeposit | Maximum deposit amount. | Determines the maximum amount that users can deposit in the protocol. High maximum deposits may increase overall security but may also pose a risk to the system if not properly managed. | +| minimumWithdrawal | Minimum withdrawal amount. | Determines the minimum amount required for users to withdraw their assets. Low minimum withdrawals encourage more participation but may also increase transaction costs. | +| maximumWithdrawal | Maximum withdrawal amount. | Determines the maximum amount that users can withdraw from the protocol. High maximum withdrawals may increase overall security but may also pose a risk to the system if not properly managed. | +| tierProvider | Contract responsible for providing tier information. | Determines the economic incentives and penalties for different user tiers. Influences the overall security of the system. | +| airdrop | Contract responsible for distributing tokens as airdrops. | Determines the distribution of tokens to users and may impact the token's value. | +| teamPool | Contract responsible for managing the team's token pool. | Determines the distribution and allocation of tokens to the team members and may impact the token's value. | +| verifier | Contract responsible for verifying block attestations. | Determines the security and integrity of the system. High-quality verifiers can increase overall system security. | + +## 6. Architecture Business Logic + +| Component | Functionality | Interactions | +| ------------------------ | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| L1 Contracts | L1 bridge functionality, L1 token handling, L1 cross-chain messages, L1 data handling, and L1 governance. | L1 <-> L2 bridge contracts, L1 bridge helpers, L1 governance contracts, L1 token contracts, L1 ERC20 token wrappers, L1 ERC721 token wrappers, and L1 ERC1155 token wrappers. | +| L2 Contracts | L2 bridge functionality, L2 token handling, L2 cross-chain messages, L2 data handling, and L2 verifiers. | L1 <-> L2 bridge contracts, L2 cross-chain message queue, L2 ERC20 token wrappers, L2 ERC721 token wrappers, L2 ERC1155 token wrappers, and L2 verifier contracts. | +| Bridge Contracts | Bi-directional message passing, token transfers, and token wrappers between L1 and L2. | L1 <-> L2 bridge contracts, L1 token contracts, and L2 token contracts. | +| Helper Contracts | Assist L1 and L2 contracts with various tasks, such as deposits, withdrawals, and message handling. | L1 <-> L2 bridge contracts, and L1 and L2 token contracts. | +| Governance Contracts | Allow for managing parameters and upgrades for the Taiko protocol. | L1 <-> L2 bridge contracts and helper contracts. | +| Token Contracts | Native tokens for L1 and L2. | L1 and L2 token contracts, L1 and L2 bridge contracts, and L1 and L2 ERC20, ERC721, and ERC1155 token wrappers. | +| Verifier Contracts | Handle L1 and L2 verification tasks. | Bridge contracts, L1 and L2 token contracts, and L1 and L2 ERC20, ERC721, and ERC1155 token wrappers. | +| Token Vault Contracts | Interact with L1 and L2 tokens for deposit/withdrawal, transfer, and cross-chain messages. | Bridge contracts, L1 <-> L2 bridge contracts, and L1 and L2 token contracts. | +| Signal Service Contracts | Process L1 and L2 contract signals. | Bridge contracts, L1 token contracts, L2 token contracts, and governance contracts. | +| Third-Party Libraries | Reusable libraries for various tasks, such as RLP encoding and decoding. | Multiple contracts throughout the Taiko protocol. | + +## 7. Representation of Risk Model + +### 7.1 Centralization & Systematic Risks + +- Centralized management of trusted parties, including Guardians, Verifiers, and Tier Providers. +- Guardians have significant control and potential influence over the system's consensus, introducing the risk of centralization. Guardians may collude, censor transactions, or manipulate the system for personal gain. A transparent and fair guardian selection process, as well as frequent evaluations and updates, can help mitigate these risks. +- Tier Providers are responsible for managing the transaction fees and auxiliary gas costs, which can lead to centralization risks if these providers collude, manipulate, or censor transactions. Transparency in their selection process and regular evaluations can help mitigate these risks. +- Taiko currently uses two verifier contracts - GuardianVerifier and SgxVerifier. However, any vulnerabilities found in these contracts may impact the entire system's security. Ensuring a robust and secure design and conducting regular audits can help minimize these risks. +- The bridge between the L1 and L2 chains is a single trust boundary and is responsible for securing and maintaining communication between the two chains. This centralized communication line can lead to single-point failures, censorship, or manipulation of transactions. Prioritizing bridge security, resilience, and regular audits can help reduce these risks. +- Bridge.sol contains critical functionality such as token deposits and withdrawals. Centralizing this functionality in a single contract can have systemic implications if vulnerabilities are found in this contract. Consider distributing this functionality across multiple contracts to reduce potential exposure and risk. +- BaseNFTVault.sol and its derived contracts manage NFT tokens, which can be centralized and expose the system to failures, censorship, or manipulation by a single or a group of vault owners. Implementing decentralized measures, such as vault rotation or owner switching, can help reduce these risks. +- Taiko relies on third-party libraries like OpenZeppelin, optimism, and solmate, introducing potential systemic risks. If vulnerabilities are discovered in these libraries, they can affect multiple contracts within the Taiko ecosystem. Ensuring timely updates and audits of these libraries can help minimize these risks. +- Centralized control over various token contracts can introduce systemic risks, especially if these tokens are fungible and widely adopted. Specifying clear guidelines for token implementations, audits, and periodic reviews can help maintain a robust and secure environment. +- TokenVault and Bridge handle critical aspects of token transfers, deposits, and withdrawals between L1 and L2 chains. Centralizing these functionalities may introduce vulnerabilities, manipulations, or failures. Decentralizing these contracts or distributing their responsibilities can help mitigate systemic risks. + +### 7.2 Technical Risks + +- The TaikoL1 contract's deposit function uses \_checkProofAndUpdateState function, which is vulnerable to denial-of-service attacks if the proof is invalid. +- The CrossChainOwned contract's execute function uses \_checkProofAndUpdateState, introducing the same risk as the TaikoL1 contract. +- The TaikoL2 contract's deposit function and TaikoL2EIP1559Configurable contract's deposit function use \_checkProofAndUpdateState, introducing the same risk as the TaikoL1 contract. +- The TaikoErrors contract's fail function uses revert, which consumes gas and introduces the possibility of transaction failure. +- The ApprovalHook contract's execute function uses \_checkProofAndUpdateState function, which, if the proof is invalid, can result in denial-of-service attacks. +- The AssignmentHook contract uses \_checkProofAndUpdateState function, introducing the same risk as in the ApprovalHook contract. +- The RoundEndHook contract uses \_checkProofAndUpdateState function, introducing the same risk as in the ApprovalHook contract. +- Some of the contracts make use of external libraries, such as solmate, optimism, and nomad-xyz. These libraries have not been audited and could contain vulnerabilities that could be exploited to compromise the system. +- The USDCAdapter contract uses transferFrom to move funds, but does not check the return value. This could allow malicious actors to execute a reentrancy attack. +- The GuardianProver contract uses the push opcode to execute a call to TaikoL1. However, there is no check to ensure that the call succeeded. This could allow malicious actors to execute a denial-of-service (DoS) attack. +- The BaseVault contract has a nonce variable that is used to ensure that funds can only be withdrawn by calling the correct function. However, this variable is not reset after withdrawal. This could allow malicious actors to repeatedly call the withdraw function and drain the vault of its funds. +- The SgxVerifier contract assumes that the hardware implementation of the remote attestation process cannot be tampered with. However, this assumption may not be valid and could allow malicious actors to submit false or malicious attestations that are accepted by the system. +- The DevnetTierProvider contract uses a fixed list of addresses to determine the validity of proofs. This could allow malicious actors to submit false or invalid proofs that are accepted by the system. + +### 7.3 Weak Spots + +- The TaikoL1, CrossChainOwned, TaikoL2, and TaikoL2EIP1559Configurable contracts do not properly validate input parameters, allowing for potential vulnerabilities. +- The TaikoData contract and various libraries contain complex logic, which may lead to potential security risks and vulnerabilities. +- Dependencies on third-party code, such as nomad-xyz/ExcessivelySafeCall, optimism/Bytes, optimism/rlp/RLPReader.sol, optimism/rlp/RLPWriter.sol, optimism/trie/MerkleTrie.sol, optimism/trie/SecureMerkleTrie.sol, and solmate/LibFixedPointMath.sol, introduce potential security risks, as their behavior is influenced by their implementers. +- The TaikoL1, CrossChainOwned, TaikoL2, and TaikoL2EIP1559Configurable contracts implement complex logic in \_checkProofAndUpdateState functions, introducing potential vulnerabilities and security risks. +- The TaikoL1 contract's deposit function does not properly check the input proof length, introducing potential vulnerabilities. +- The TaikoL2EIP1559Configurable contract does not validate input parameters, introducing potential security risks. +- The USDCAdapter contract has a typo in its implementation storage variable, which may lead to errors and potential security risks. +- The BridgedERC20Base contract relies on count and length to iterate over mappings, which may lead to incorrect results or potential security risks. + +### 7.4 Economic Risks + +- The TaikoEvents contract contains an Exit event that can be triggered when a contract errors out. However, the documentation does not make it clear how this event could be used or what its implications are. If this event is used to exit a contract prematurely, it could result in a loss of funds for users. +- The TaikoL2EIP1559Configurable contract has a gasPriceLimit function that can be used to set the maximum gas price for transactions. However, this function does not check that the new gas price is higher than the current price. This could allow malicious actors to set the gas price to a very low value, effectively allowing them to execute transactions at a much lower cost than other users. +- The TaikoL2 contract has a migrate function that can be used to migrate funds from one contract to another. However, this function does not check that the destination contract is valid. This could allow malicious actors to migrate funds to a malicious contract, resulting in a loss of funds for users. +- The TaikoL1 contract has a init function that can be used to initialize the contract. However, this function does not check that the contract has sufficient funds to execute its operations. This could allow malicious actors to execute a denial-of-service (DoS) attack by repeatedly calling the init function with low-cost transactions that consume all of the contract's gas. +- The TaikoL1 contract also has a execute function that can be used to execute arbitrary commands on the contract. This function does not check that the contract has sufficient funds to execute the command, nor does it check that the command is valid. This could allow malicious actors to execute arbitrary code on the contract, potentially resulting in a loss of funds for users. + +## 8. Architecture Recommendations + +- Diversify the set of trusted parties that are responsible for performing critical tasks such as proving and verifying proofs. +- Use a more robust mechanism for error handling, such as reverting the contract or logging an error message, instead of relying on hardcoded error messages. +- Implement proper input validation and error handling in all contract functions to prevent reentrancy, denial-of-service (DoS), and other attacks. +- Use a more robust mechanism for storing and retrieving attestation data, such as a public blockchain, to ensure that data is tamper-evident and auditable. +- Consider implementing multi-party computation techniques, such as threshold signing, to decentralize the responsibility for executing critical tasks. +- Perform thorough security testing and auditing of all contracts and external libraries to identify and fix any vulnerabilities. +- Implement rate-limiting and gas limits on critical functions to prevent abuse and denial-of-service (DoS) attacks. +- Implement proper input validation and error handling in all contract functions to prevent reentrancy, denial-of-service (DoS), and other attacks. +- Consider implementing a more robust mechanism for handling contract errors, such as reverting the contract or logging an error message, instead of relying on a single Exit event. +- Consider implementing a more robust mechanism for configuring gas limits on transactions, such as using a separate contract or smart contract wallet. +- Implement proper input validation and error handling in all contract functions to prevent reentrancy, denial-of-service (DoS), and other attacks. +- Implement proper input validation and error handling in all contract functions to prevent reentrancy, denial-of-service (DoS), and other attacks. +- Consider implementing a more robust mechanism for handling contract errors, such as reverting the contract or logging an error message, instead of relying on a single Exit event. +- Consider implementing a more robust mechanism for handling contract errors, such as reverting the contract or logging an error message, instead of relying on a single Exit event. + +## 9. Learning And Insights + +- **Understanding of cross-chain bridges**: Taiko codebase deals with bridges for transferring assets between different blockchain networks, which is a complex and interesting problem. Reviewing this codebase helped me to understand the challenges involved in building cross-chain bridges and the different approaches used to solve them. +- **Better understanding of L2 scaling solutions**: Taiko codebase is built on top of L2 scaling solutions such as Optimism and ZK-Rollups. Reviewing this codebase helped me to understand how these L2 solutions work and how they can be used to build scalable blockchain applications. +- **Understanding of cryptography and security**: Taiko codebase involves cryptographic protocols such as ECDSA signatures and elliptic curve cryptography. Reviewing this codebase helped me to understand the importance of security in blockchain development and the different techniques used to ensure the security of the system. +- **Code organization and readability**: Taiko codebase is well-organized and easy to read, with consistent naming conventions and well-documented code. Reviewing this codebase helped me to understand the importance of code organization and readability in blockchain development. +- **Modularity and reusability**: Taiko codebase makes extensive use of libraries and interfaces, which helps to promote code modularity and reusability. Reviewing this codebase helped me to understand the importance of designing code for reuse and how to build reusable components in blockchain development. +- **Learning from experienced developers**: Taiko codebase is developed by experienced developers who have a deep understanding of blockchain technology and smart contract development. Reviewing this codebase helped me to learn from their experience and expertise. + +## 10. Conclusion + +I reviewed the Taiko codebase and identified several strengths, weaknesses, opportunities, and threats (SWOT analysis) for the project. I found that the codebase is well-structured, well-documented, and follows best practices for blockchain development. The team has taken a security-focused approach to development, with a strong emphasis on formal verification and testing. + +However, there are some areas for improvement, including the need for additional input validation, error handling, and gas optimization techniques. Additionally, there are some potential risks associated with the use of L2 scaling solutions and cross-chain bridges, including the need for adequate security measures to prevent attacks and ensure data consistency and integrity. + +To address these challenges, I recommend that the Taiko team continue to prioritize security and best practices throughout the development process. This includes implementing additional input validation, error handling, and gas optimization techniques, as well as conducting ongoing security testing and auditing. Additionally, the team should consider implementing multi-party computation techniques, such as threshold signing, to decentralize the responsibility for critical tasks and improve the system's overall resilience. + +Overall, the Taiko codebase is a solid foundation for building a scalable and secure L2 scaling solution. With continued attention to detail and commitment to best practices, the Taiko project is well-positioned for long-term success. + +## 11. Message For Taiko Team + +Congratulations to the Taiko team on a successful audit! It's clear that a lot of work and dedication has gone into building this project, and the attention to detail and thoughtfulness that went into the code and documentation is commendable. + +The codebase is well-structured and organized, and it's clear that the team has a deep understanding of blockchain technology and smart contract development. The use of libraries and interfaces to promote modularity and reusability is particularly impressive, as is the attention paid to security and cryptography. + +As a warden in the Code4rena community, I'm always impressed when I see a project that takes security seriously, and the Taiko team's approach to security is commendable. The team's commitment to testing and formal verification is a clear sign that they take security seriously, and I believe this will help to build trust and confidence in the Taiko project. + +Overall, I'm excited to see where the Taiko project will go, and I'm confident that the team's dedication and expertise will help to ensure its success. Keep up the great work, and thank you for the opportunity to review your code! + +## 12. Time Spent + +| Task | Time Spent (hours) | +| ------------------------- | ------------------ | +| Analysis of documentation | 20 | +| Review of Taiko codebase | 40 | +| Preparation of report | 10 | +| Total time spent | 70 | + +## 13. Refrences + +- https://github.com/code-423n4/2024-03-taiko +- https://docs.taiko.xyz/start-here/getting-started +- https://taiko.mirror.xyz/oRy3ZZ_4-6IEQcuLCMMlxvdH6E-T3_H7UwYVzGDsgf4 +- https://www.datawallet.com/crypto/what-is-taiko +- https://medium.com/@mustafa.hourani/interview-with-taiko-a-leading-type-1-zkevm-ddf71eb4eabe +- https://taiko.mirror.xyz/y_47kIOL5kavvBmG0zVujD2TRztMZt-xgM5d4oqp4_Y?ref=bankless.ghost.io + +**[dantaik (Taiko) acknowledged and commented](https://github.com/code-423n4/2024-03-taiko-findings/issues/253#issuecomment-2036830623):** + +> Love this report. + +--- + +# Disclosures + +C4 is an open organization governed by participants in the community. + +C4 audits incentivize the discovery of exploits, vulnerabilities, and bugs in smart contracts. Security researchers are rewarded at an increasing rate for finding higher-risk issues. Audit submissions are judged by a knowledgeable security researcher and solidity developer and disclosed to sponsoring developers. C4 does not conduct formal verification regarding the provided code but instead provides final verification. + +C4 does not provide any guarantee or warranty regarding the security of this project. All smart contract software should be used at the sole risk and responsibility of users. diff --git a/packages/protocol/contracts/L1/gov/TaikoGovernor.sol b/packages/protocol/contracts/L1/gov/TaikoGovernor.sol deleted file mode 100644 index b8a0082b98..0000000000 --- a/packages/protocol/contracts/L1/gov/TaikoGovernor.sol +++ /dev/null @@ -1,164 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import - "@openzeppelin/contracts-upgradeable/governance/compatibility/GovernorCompatibilityBravoUpgradeable.sol"; -import - "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorVotesQuorumFractionUpgradeable.sol"; -import - "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorTimelockControlUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/governance/extensions/GovernorSettingsUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; - -/// @title TaikoGovernor -/// @custom:security-contact security@taiko.xyz -contract TaikoGovernor is - Ownable2StepUpgradeable, - GovernorCompatibilityBravoUpgradeable, - GovernorSettingsUpgradeable, - GovernorVotesQuorumFractionUpgradeable, - GovernorTimelockControlUpgradeable -{ - uint256[50] private __gap; - - /// @notice Initializes the contract. - /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. - /// @param _token The Taiko token. - /// @param _timelock The timelock contract address. - function init( - address _owner, - IVotesUpgradeable _token, - TimelockControllerUpgradeable _timelock - ) - external - initializer - { - _transferOwnership(_owner == address(0) ? msg.sender : _owner); - __Governor_init("TaikoGovernor"); - __GovernorVotes_init(_token); - __GovernorSettings_init(7200, 50_400, 100_000 ether); // Values respectively: 1day, 1week, - // 0.01% of Taiko Token; - __GovernorVotesQuorumFraction_init(4); - __GovernorTimelockControl_init(_timelock); - } - - /// @dev See {IGovernor-propose} - function propose( - address[] memory _targets, - uint256[] memory _values, - bytes[] memory _calldatas, - string memory _description - ) - public - override(IGovernorUpgradeable, GovernorUpgradeable, GovernorCompatibilityBravoUpgradeable) - returns (uint256) - { - return super.propose(_targets, _values, _calldatas, _description); - } - - /// @dev See {GovernorUpgradeable-supportsInterface} - function supportsInterface(bytes4 _interfaceId) - public - view - override(GovernorUpgradeable, GovernorTimelockControlUpgradeable, IERC165Upgradeable) - returns (bool) - { - return super.supportsInterface(_interfaceId); - } - - /// @dev See {GovernorUpgradeable-state} - function state(uint256 _proposalId) - public - view - override(IGovernorUpgradeable, GovernorUpgradeable, GovernorTimelockControlUpgradeable) - returns (ProposalState) - { - return super.state(_proposalId); - } - - /// @notice How long after a proposal is created should voting power be fixed. A - /// large voting delay gives users time to unstake tokens if necessary. - /// @return The duration of the voting delay. - function votingDelay() - public - view - override(IGovernorUpgradeable, GovernorSettingsUpgradeable) - returns (uint256) - { - return super.votingDelay(); - } - - /// @notice How long does a proposal remain open to votes. - /// @return The duration of the voting period. - function votingPeriod() - public - view - override(IGovernorUpgradeable, GovernorSettingsUpgradeable) - returns (uint256) - { - return super.votingPeriod(); - } - - /// @notice The number of votes required in order for a voter to become a proposer. - /// @return The number of votes required. - function proposalThreshold() - public - view - override(GovernorUpgradeable, GovernorSettingsUpgradeable) - returns (uint256) - { - return super.proposalThreshold(); - } - - /// @dev Cancel a proposal with GovernorBravo logic. - function cancel( - address[] memory targets, - uint256[] memory values, - bytes[] memory calldatas, - bytes32 descriptionHash - ) - public - virtual - override(IGovernorUpgradeable, GovernorUpgradeable, GovernorCompatibilityBravoUpgradeable) - returns (uint256) - { - return GovernorCompatibilityBravoUpgradeable.cancel( - targets, values, calldatas, descriptionHash - ); - } - - function _execute( - uint256 _proposalId, - address[] memory _targets, - uint256[] memory _values, - bytes[] memory _calldatas, - bytes32 _descriptionHash - ) - internal - override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) - { - return super._execute(_proposalId, _targets, _values, _calldatas, _descriptionHash); - } - - function _cancel( - address[] memory _targets, - uint256[] memory _values, - bytes[] memory _calldatas, - bytes32 _descriptionHash - ) - internal - override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) - returns (uint256) - { - return super._cancel(_targets, _values, _calldatas, _descriptionHash); - } - - function _executor() - internal - view - override(GovernorUpgradeable, GovernorTimelockControlUpgradeable) - returns (address) - { - return super._executor(); - } -} diff --git a/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol b/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol deleted file mode 100644 index 0b1b9cbe2a..0000000000 --- a/packages/protocol/contracts/L1/gov/TaikoTimelockController.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "@openzeppelin/contracts-upgradeable/governance/TimelockControllerUpgradeable.sol"; -import "../../common/EssentialContract.sol"; - -/// @title TaikoTimelockController -/// @custom:security-contact security@taiko.xyz -contract TaikoTimelockController is EssentialContract, TimelockControllerUpgradeable { - uint256[50] private __gap; - - /// @notice Initializes the contract. - /// @param _owner The owner of this contract. msg.sender will be used if this value is zero. - /// @param _minDelay The minimal delay. - function init(address _owner, uint256 _minDelay) external initializer { - __Essential_init(_owner); - address[] memory nil = new address[](0); - __TimelockController_init(_minDelay, nil, nil, owner()); - } - - /// @dev Gets the minimum delay for an operation to become valid, allows the admin to get around - /// of the min delay. - /// @return The minimum delay. - function getMinDelay() public view override returns (uint256) { - return hasRole(TIMELOCK_ADMIN_ROLE, msg.sender) ? 0 : super.getMinDelay(); - } -} diff --git a/packages/protocol/contracts/L2/LibL2Config.sol b/packages/protocol/contracts/L2/LibL2Config.sol index 754dfeed32..b3309829cd 100644 --- a/packages/protocol/contracts/L2/LibL2Config.sol +++ b/packages/protocol/contracts/L2/LibL2Config.sol @@ -18,7 +18,7 @@ library LibL2Config { config_.gasTargetPerL1Block = 60_000_000; config_.basefeeAdjustmentQuotient = 8; - // This value is picked to make the min base fee close to but slightly smaller than 0.1gwei - config_.gasExcessMinValue = 18_435_000_000; + // This value is picked to make the min base fee be 0.01gwei + config_.gasExcessMinValue = 17_331_548_325; } } diff --git a/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol b/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol index ba3d6e4363..27240f7249 100644 --- a/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol +++ b/packages/protocol/contracts/automata-attestation/AutomataDcapV3Attestation.sol @@ -17,14 +17,13 @@ import { BytesUtils } from "./utils/BytesUtils.sol"; // External Libraries import { ISigVerifyLib } from "./interfaces/ISigVerifyLib.sol"; +import { EssentialContract } from "../common/EssentialContract.sol"; + /// @title AutomataDcapV3Attestation /// @custom:security-contact security@taiko.xyz -contract AutomataDcapV3Attestation is IAttestation { +contract AutomataDcapV3Attestation is IAttestation, EssentialContract { using BytesUtils for bytes; - ISigVerifyLib public immutable sigVerifyLib; - IPEMCertChainLib public immutable pemCertLib; - // https://github.com/intel/SGXDataCenterAttestationPrimitives/blob/e7604e02331b3377f3766ed3653250e03af72d45/QuoteVerification/QVL/Src/AttestationLibrary/src/CertVerification/X509Constants.h#L64 uint256 internal constant CPUSVN_LENGTH = 16; @@ -35,31 +34,40 @@ contract AutomataDcapV3Attestation is IAttestation { uint8 internal constant INVALID_EXIT_CODE = 255; - bool private _checkLocalEnclaveReport; - mapping(bytes32 enclave => bool trusted) private _trustedUserMrEnclave; - mapping(bytes32 signer => bool trusted) private _trustedUserMrSigner; + ISigVerifyLib public sigVerifyLib; // slot 1 + IPEMCertChainLib public pemCertLib; // slot 2 + + bool private _checkLocalEnclaveReport; // slot 3 + mapping(bytes32 enclave => bool trusted) private _trustedUserMrEnclave; // slot 4 + mapping(bytes32 signer => bool trusted) private _trustedUserMrSigner; // slot 5 // Quote Collateral Configuration // Index definition: // 0 = Quote PCKCrl // 1 = RootCrl - mapping(uint256 idx => mapping(bytes serialNum => bool revoked)) private _serialNumIsRevoked; + mapping(uint256 idx => mapping(bytes serialNum => bool revoked)) private _serialNumIsRevoked; // slot + // 6 // fmspc => tcbInfo - mapping(string fmspc => TCBInfoStruct.TCBInfo tcbInfo) public tcbInfo; - EnclaveIdStruct.EnclaveId public qeIdentity; - - address public immutable owner; - - constructor(address sigVerifyLibAddr, address pemCertLibAddr) { + mapping(string fmspc => TCBInfoStruct.TCBInfo tcbInfo) public tcbInfo; // slot 7 + EnclaveIdStruct.EnclaveId public qeIdentity; // takes 4 slots, slot 8,9,10,11 + + uint256[39] __gap; + + // @notice Initializes the contract. + /// @param sigVerifyLibAddr Address of the signature verification library. + /// @param pemCertLibAddr Address of certificate library. + function init( + address owner, + address sigVerifyLibAddr, + address pemCertLibAddr + ) + external + initializer + { + __Essential_init(owner); sigVerifyLib = ISigVerifyLib(sigVerifyLibAddr); pemCertLib = PEMCertChainLib(pemCertLibAddr); - owner = msg.sender; - } - - modifier onlyOwner() { - require(msg.sender == owner, "onlyOwner"); - _; } function setMrSigner(bytes32 _mrSigner, bool _trusted) external onlyOwner { diff --git a/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol b/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol index 1d597e3d95..3e889e084e 100644 --- a/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol +++ b/packages/protocol/contracts/automata-attestation/lib/EnclaveIdStruct.sol @@ -5,13 +5,13 @@ pragma solidity 0.8.24; /// @custom:security-contact security@taiko.xyz library EnclaveIdStruct { struct EnclaveId { - bytes4 miscselect; + bytes4 miscselect; // Slot 1: bytes4 miscselectMask; uint16 isvprodid; - bytes16 attributes; + bytes16 attributes; // Slot 2 bytes16 attributesMask; - bytes32 mrsigner; - TcbLevel[] tcbLevels; + bytes32 mrsigner; // Slot 3 + TcbLevel[] tcbLevels; // Slot 4 } struct TcbLevel { diff --git a/packages/protocol/contracts/team/TimelockTokenPool.sol b/packages/protocol/contracts/team/TimelockTokenPool.sol deleted file mode 100644 index 09552e56f0..0000000000 --- a/packages/protocol/contracts/team/TimelockTokenPool.sol +++ /dev/null @@ -1,312 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts-upgradeable/utils/cryptography/EIP712Upgradeable.sol"; -import "../common/EssentialContract.sol"; - -/// @title TimelockTokenPool -/// @notice Contract for managing Taiko tokens allocated to different roles and -/// individuals. -/// -/// Manages Taiko tokens through a three-state lifecycle: "allocated" to -/// "granted, owned, and locked," and finally to "granted, owned, and unlocked." -/// Allocation doesn't transfer ownership unless specified by grant settings. -/// Conditional allocated tokens can be canceled by invoking `void()`, making -/// them available for other uses. Once granted and owned, tokens are -/// irreversible and their unlock schedules are immutable. -/// -/// We should deploy multiple instances of this contract for different roles: -/// - investors -/// - team members, advisors, etc. -/// - grant program grantees -/// @custom:security-contact security@taiko.xyz -contract TimelockTokenPool is EssentialContract, EIP712Upgradeable { - using SafeERC20 for IERC20; - - struct Grant { - uint128 amount; - // If non-zero, each TKO (1E18) will need some USD stable to purchase. - uint128 costPerToken; - // If non-zero, indicates the start time for the recipient to receive - // tokens, subject to an unlocking schedule. - uint64 grantStart; - // If non-zero, indicates the time after which the token to be received - // will be actually non-zero - uint64 grantCliff; - // If non-zero, specifies the total seconds required for the recipient - // to fully own all granted tokens. - uint32 grantPeriod; - // If non-zero, indicates the start time for the recipient to unlock - // tokens. - uint64 unlockStart; - // If non-zero, indicates the time after which the unlock will be - // actually non-zero - uint64 unlockCliff; - // If non-zero, specifies the total seconds required for the recipient - // to fully unlock all owned tokens. - uint32 unlockPeriod; - } - - struct Recipient { - uint128 amountWithdrawn; - uint128 costPaid; - Grant grant; - } - - bytes32 public constant TYPED_HASH = keccak256("Withdrawal(address to,uint256 nonce)"); - - /// @notice The Taiko token address. - address public taikoToken; - - /// @notice The cost token address. - address public costToken; - - /// @notice The shared vault address. - address public sharedVault; - - /// @notice The total amount of tokens granted. - uint128 public totalAmountGranted; - - /// @notice The total amount of tokens voided. - uint128 public totalAmountVoided; - - /// @notice The total amount of tokens withdrawn. - uint128 public totalAmountWithdrawn; - - /// @notice The total cost paid. - uint128 public totalCostPaid; - - /// @notice Mapping of recipient address to grant information. - mapping(address recipient => Recipient receipt) public recipients; - - /// @notice Mapping of recipient address to the next withdrawal nonce. - mapping(address recipient => uint256 withdrawalNonce) public withdrawalNonces; - - uint128[43] private __gap; - - /// @notice Emitted when a grant is made. - /// @param recipient The grant recipient address. - /// @param grant The grant. - event Granted(address indexed recipient, Grant grant); - - /// @notice Emitted when a grant is voided. - /// @param recipient The grant recipient address. - /// @param amount The amount of tokens voided. - event Voided(address indexed recipient, uint128 amount); - - /// @notice Emitted when tokens are withdrawn. - /// @param recipient The grant recipient address. - /// @param to The address where the granted and unlocked tokens shall be sent to. - /// @param amount The amount of tokens withdrawn. - /// @param cost The cost. - event Withdrawn(address indexed recipient, address to, uint128 amount, uint128 cost); - - error ALREADY_GRANTED(); - error INVALID_GRANT(); - error INVALID_NONCE(); - error INVALID_PARAM(); - error INVALID_SIGNATURE(); - error NOTHING_TO_VOID(); - - /// @notice Initializes the contract. - /// @param _owner The owner address. - /// @param _taikoToken The Taiko token address. - /// @param _costToken The cost token address. - /// @param _sharedVault The shared vault address. - function init( - address _owner, - address _taikoToken, - address _costToken, - address _sharedVault - ) - external - initializer - { - if (_taikoToken == address(0) || _costToken == address(0) || _sharedVault == address(0)) { - revert INVALID_PARAM(); - } - - __Essential_init(_owner); - __EIP712_init("Taiko TimelockTokenPool", "1"); - - taikoToken = _taikoToken; - costToken = _costToken; - sharedVault = _sharedVault; - } - - /// @notice Gives a grant to a address with its own unlock schedule. - /// This transaction should happen on a regular basis, e.g., quarterly. - /// @param _recipient The grant recipient address. - /// @param _grant The grant struct. - function grant(address _recipient, Grant memory _grant) external onlyOwner nonReentrant { - if (_recipient == address(0)) revert INVALID_PARAM(); - if (recipients[_recipient].grant.amount != 0) revert ALREADY_GRANTED(); - - _validateGrant(_grant); - - totalAmountGranted += _grant.amount; - recipients[_recipient].grant = _grant; - emit Granted(_recipient, _grant); - } - - /// @notice Puts a stop to all grants for a given recipient. Tokens already - /// granted to the recipient will NOT be voided but are subject to the - /// original unlock schedule. - /// @param _recipient The grant recipient address. - function void(address _recipient) external onlyOwner nonReentrant { - Recipient storage r = recipients[_recipient]; - uint128 amountVoided = _voidGrant(r.grant); - - if (amountVoided == 0) revert NOTHING_TO_VOID(); - - totalAmountVoided += amountVoided; - emit Voided(_recipient, amountVoided); - } - - /// @notice Withdraws all withdrawable tokens. - function withdraw() external whenNotPaused nonReentrant { - _withdraw(msg.sender, msg.sender); - } - - /// @notice Withdraws all withdrawable tokens to a designated address. - /// @param _to The address where the granted and unlocked tokens shall be sent to. - /// @param _nonce The nonce to be used. - /// @param _sig Signature provided by the grant recipient. - function withdraw( - address _to, - uint256 _nonce, - bytes calldata _sig - ) - external - whenNotPaused - nonReentrant - { - if (_to == address(0)) revert INVALID_PARAM(); - - address account = ECDSA.recover(getWithdrawalHash(_to, _nonce), _sig); - if (account == address(0)) revert INVALID_SIGNATURE(); - if (withdrawalNonces[account] != _nonce) revert INVALID_NONCE(); - - withdrawalNonces[account] += 1; - _withdraw(account, _to); - } - - /// @notice Gets the hash to be signed to authorize an withdrawal. - /// @param _to The destination address. - /// @param _nonce The withdrawal nonce. - /// @return The hash to be signed. - function getWithdrawalHash(address _to, uint256 _nonce) public view returns (bytes32) { - return _hashTypedDataV4(keccak256(abi.encode(TYPED_HASH, _to, _nonce))); - } - - /// @notice Returns the summary of the grant for a given recipient. - function getMyGrantSummary(address _recipient) - public - view - returns ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) - { - Recipient storage r = recipients[_recipient]; - - amountOwned = _getAmountOwned(r.grant); - amountUnlocked = _getAmountUnlocked(r.grant); - - amountWithdrawn = r.amountWithdrawn; - amountToWithdraw = amountUnlocked - amountWithdrawn; - - // Note: precision is maintained at the token level rather than the wei level, otherwise, - // `costPaid` must be a uint256. Therefore, please ignore - // https://github.com/crytic/slither/wiki/Detector-Documentation#divide-before-multiply - uint128 _amountUnlocked = amountUnlocked / 1e18; // divide first - costToWithdraw = _amountUnlocked * r.grant.costPerToken - r.costPaid; - } - - /// @notice Returns the grant for a given recipient. - /// @param _recipient The grant recipient address. - /// @return The grant. - function getMyGrant(address _recipient) public view returns (Grant memory) { - return recipients[_recipient].grant; - } - - function _withdraw(address _recipient, address _to) private { - Recipient storage r = recipients[_recipient]; - - (,,, uint128 amountToWithdraw, uint128 costToWithdraw) = getMyGrantSummary(_recipient); - - r.amountWithdrawn += amountToWithdraw; - r.costPaid += costToWithdraw; - - totalAmountWithdrawn += amountToWithdraw; - totalCostPaid += costToWithdraw; - - IERC20(taikoToken).safeTransferFrom(sharedVault, _to, amountToWithdraw); - IERC20(costToken).safeTransferFrom(_recipient, sharedVault, costToWithdraw); - - emit Withdrawn(_recipient, _to, amountToWithdraw, costToWithdraw); - } - - function _voidGrant(Grant storage _grant) private returns (uint128 amountVoided) { - uint128 amountOwned = _getAmountOwned(_grant); - - amountVoided = _grant.amount - amountOwned; - _grant.amount = amountOwned; - - _grant.grantStart = 0; - _grant.grantPeriod = 0; - } - - function _getAmountOwned(Grant memory _grant) private view returns (uint128) { - return _calcAmount(_grant.amount, _grant.grantStart, _grant.grantCliff, _grant.grantPeriod); - } - - function _getAmountUnlocked(Grant memory _grant) private view returns (uint128) { - return _calcAmount( - _getAmountOwned(_grant), _grant.unlockStart, _grant.unlockCliff, _grant.unlockPeriod - ); - } - - function _calcAmount( - uint128 _amount, - uint64 _start, - uint64 _cliff, - uint64 _period - ) - private - view - returns (uint128) - { - if (_amount == 0) return 0; - if (_start == 0) return _amount; - if (block.timestamp <= _start) return 0; - - if (_period == 0) return _amount; - if (block.timestamp >= _start + _period) return _amount; - - if (block.timestamp <= _cliff) return 0; - - return _amount * uint64(block.timestamp - _start) / _period; - } - - function _validateGrant(Grant memory _grant) private pure { - if (_grant.amount == 0) revert INVALID_GRANT(); - _validateCliff(_grant.grantStart, _grant.grantCliff, _grant.grantPeriod); - _validateCliff(_grant.unlockStart, _grant.unlockCliff, _grant.unlockPeriod); - } - - function _validateCliff(uint64 _start, uint64 _cliff, uint32 _period) private pure { - if (_start == 0 || _period == 0) { - if (_cliff != 0) revert INVALID_GRANT(); - } else { - if (_cliff != 0 && _cliff <= _start) revert INVALID_GRANT(); - if (_cliff >= _start + _period) revert INVALID_GRANT(); - } - } -} diff --git a/packages/protocol/contracts/tokenvault/BaseVault.sol b/packages/protocol/contracts/tokenvault/BaseVault.sol index 924bb6139a..82544c706e 100644 --- a/packages/protocol/contracts/tokenvault/BaseVault.sol +++ b/packages/protocol/contracts/tokenvault/BaseVault.sol @@ -16,6 +16,8 @@ abstract contract BaseVault is IMessageInvocable, IERC165Upgradeable { + bytes4 internal constant IERC165_INTERFACE_ID = bytes4(keccak256("supportsInterface(bytes4)")); + uint256[50] private __gap; error VAULT_PERMISSION_DENIED(); @@ -32,7 +34,8 @@ abstract contract BaseVault is /// @return true if the contract supports the interface, false otherwise. function supportsInterface(bytes4 _interfaceId) public pure virtual override returns (bool) { return _interfaceId == type(IRecallableSender).interfaceId - || _interfaceId == type(IMessageInvocable).interfaceId; + || _interfaceId == type(IMessageInvocable).interfaceId + || _interfaceId == IERC165_INTERFACE_ID; } /// @notice Returns the name of the vault. diff --git a/packages/protocol/contracts/tokenvault/ERC20Vault.sol b/packages/protocol/contracts/tokenvault/ERC20Vault.sol index 24bf8cd5ca..aa8033a1ca 100644 --- a/packages/protocol/contracts/tokenvault/ERC20Vault.sol +++ b/packages/protocol/contracts/tokenvault/ERC20Vault.sol @@ -355,15 +355,27 @@ contract ERC20Vault is BaseVault { balanceChange_ = _op.amount; } else { // If it's a canonical token - IERC20Metadata meta = IERC20Metadata(_op.token); ctoken_ = CanonicalERC20({ chainId: uint64(block.chainid), addr: _op.token, - decimals: meta.decimals(), - symbol: meta.symbol(), - name: meta.name() + decimals: 0, + symbol: "", + name: "" }); + // Try fill in the boilerplate values, but use try-catch because functions below are + // ERC20-optional only. + IERC20Metadata meta = IERC20Metadata(_op.token); + try meta.decimals() returns (uint8 _decimals) { + ctoken_.decimals = _decimals; + } catch { } + try meta.name() returns (string memory _name) { + ctoken_.name = _name; + } catch { } + try meta.symbol() returns (string memory _symbol) { + ctoken_.symbol = _symbol; + } catch { } + // Query the balance then query it again to get the actual amount of // token transferred into this address, this is more accurate than // simply using `amount` -- some contract may deduct a fee from the diff --git a/packages/protocol/contracts/tokenvault/ERC721Vault.sol b/packages/protocol/contracts/tokenvault/ERC721Vault.sol index 67961a28c6..4726849dd5 100644 --- a/packages/protocol/contracts/tokenvault/ERC721Vault.sol +++ b/packages/protocol/contracts/tokenvault/ERC721Vault.sol @@ -204,10 +204,19 @@ contract ERC721Vault is BaseNFTVault, IERC721Receiver { ctoken_ = CanonicalNFT({ chainId: uint64(block.chainid), addr: _op.token, - symbol: t.symbol(), - name: t.name() + symbol: "", + name: "" }); + // Try fill in the boilerplate values, but use try-catch because functions below are + // ERC20-optional only. + try t.name() returns (string memory _name) { + ctoken_.name = _name; + } catch { } + try t.symbol() returns (string memory _symbol) { + ctoken_.symbol = _symbol; + } catch { } + for (uint256 i; i < _op.tokenIds.length; ++i) { t.safeTransferFrom(msg.sender, address(this), _op.tokenIds[i]); } diff --git a/packages/protocol/docs/how_taiko_proves_blocks.md b/packages/protocol/docs/how_taiko_proves_blocks.md index 838c526d33..0c5d1c3e3e 100644 --- a/packages/protocol/docs/how_taiko_proves_blocks.md +++ b/packages/protocol/docs/how_taiko_proves_blocks.md @@ -68,7 +68,7 @@ Note that the anchor transaction emits an `Anchored` event that may help ZKP to ZKP shall also check the signature of the anchor transaction: - The signer must be _`TaikoL2.GOLDEN_TOUCH_ADDRESS`_. -- The signature must use `1` as the `k` value if the calculated `r` is not `0`, otherwise, `k` must be `2`. See [LibL2Signer.sol](https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/contracts/L2/LibL2Signer.sol). +- The signature must use `1` as the `k` value if the calculated `r` is not `0`, otherwise, `k` must be `2`. See [LibL2Signer.sol](https://github.com/taikoxyz/taiko-mono/blob/main/packages/protocol/test/L2/LibL2Signer.sol). ### Block Metadata diff --git a/packages/protocol/genesis/GenerateGenesis.g.sol b/packages/protocol/genesis/GenerateGenesis.g.sol index 531570fab1..9a9cda53be 100644 --- a/packages/protocol/genesis/GenerateGenesis.g.sol +++ b/packages/protocol/genesis/GenerateGenesis.g.sol @@ -20,8 +20,7 @@ contract TestGenerateGenesis is Test, AddressResolver { vm.readFile(string.concat(vm.projectRoot(), "/deployments/genesis_config.json")); string private genesisAllocJSON = vm.readFile(string.concat(vm.projectRoot(), "/deployments/genesis_alloc.json")); - address private ownerTimelockController = configJSON.readAddress(".ownerTimelockController"); - address private ownerSecurityCouncil = configJSON.readAddress(".ownerSecurityCouncil"); + address private contractOwner = configJSON.readAddress(".contractOwner"); uint256 private l1ChainId = configJSON.readUint(".l1ChainId"); function testSharedContractsDeployment() public { @@ -61,7 +60,7 @@ contract TestGenerateGenesis is Test, AddressResolver { checkDeployedCode("RollupAddressManager"); // check proxy implementations - checkProxyImplementation("TaikoL2", ownerTimelockController); + checkProxyImplementation("TaikoL2", contractOwner); checkProxyImplementation("RollupAddressManager"); // check proxies @@ -73,7 +72,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManagerProxy = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(ownerSecurityCouncil, addressManagerProxy.owner()); + assertEq(contractOwner, addressManagerProxy.owner()); checkSavedAddress(addressManagerProxy, "Bridge", "bridge"); checkSavedAddress(addressManagerProxy, "ERC20Vault", "erc20_vault"); @@ -92,7 +91,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManagerProxy = AddressManager(getPredeployedContractAddress("RollupAddressManager")); - assertEq(ownerSecurityCouncil, addressManagerProxy.owner()); + assertEq(contractOwner, addressManagerProxy.owner()); checkSavedAddress(addressManagerProxy, "TaikoL2", "taiko"); checkSavedAddress(addressManagerProxy, "SignalService", "signal_service"); @@ -107,7 +106,7 @@ contract TestGenerateGenesis is Test, AddressResolver { function testTaikoL2() public { TaikoL2 taikoL2Proxy = TaikoL2(getPredeployedContractAddress("TaikoL2")); - assertEq(ownerTimelockController, taikoL2Proxy.owner()); + assertEq(contractOwner, taikoL2Proxy.owner()); assertEq(l1ChainId, taikoL2Proxy.l1ChainId()); vm.startPrank(taikoL2Proxy.GOLDEN_TOUCH_ADDRESS()); @@ -152,7 +151,7 @@ contract TestGenerateGenesis is Test, AddressResolver { addressManager.setAddress(1, "bridge", bridgeAddress); vm.stopPrank(); - assertEq(ownerSecurityCouncil, bridgeProxy.owner()); + assertEq(contractOwner, bridgeProxy.owner()); vm.expectRevert(Bridge.B_PERMISSION_DENIED.selector); bridgeProxy.processMessage( @@ -174,7 +173,7 @@ contract TestGenerateGenesis is Test, AddressResolver { assertEq(bridgeProxy.paused(), false); - vm.startPrank(ownerSecurityCouncil); + vm.startPrank(contractOwner); bridgeProxy.pause(); assertEq(bridgeProxy.paused(), true); @@ -212,7 +211,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(ownerSecurityCouncil, erc20VaultProxy.owner()); + assertEq(contractOwner, erc20VaultProxy.owner()); vm.startPrank(addressManager.owner()); addressManager.setAddress(1, "bridge", bridgeAddress); @@ -234,7 +233,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(ownerSecurityCouncil, erc721VaultProxy.owner()); + assertEq(contractOwner, erc721VaultProxy.owner()); vm.startPrank(addressManager.owner()); addressManager.setAddress(1, "bridge", bridgeAddress); @@ -256,7 +255,7 @@ contract TestGenerateGenesis is Test, AddressResolver { AddressManager addressManager = AddressManager(getPredeployedContractAddress("SharedAddressManager")); - assertEq(ownerSecurityCouncil, erc1155VaultProxy.owner()); + assertEq(contractOwner, erc1155VaultProxy.owner()); vm.startPrank(addressManager.owner()); addressManager.setAddress(1, "bridge", bridgeProxyAddress); @@ -276,11 +275,11 @@ contract TestGenerateGenesis is Test, AddressResolver { SignalService signalServiceProxy = SignalService(getPredeployedContractAddress("SignalService")); - assertEq(ownerSecurityCouncil, signalServiceProxy.owner()); + assertEq(contractOwner, signalServiceProxy.owner()); signalServiceProxy.sendSignal(keccak256(abi.encodePacked(block.prevrandao))); - vm.startPrank(ownerSecurityCouncil); + vm.startPrank(contractOwner); // SignalService signalService = // SignalService(payable(getPredeployedContractAddress("SignalServiceImpl"))); @@ -314,7 +313,7 @@ contract TestGenerateGenesis is Test, AddressResolver { ) private { - return checkProxyImplementation(proxyName, ownerSecurityCouncil); + return checkProxyImplementation(proxyName, contractOwner); } function checkProxyImplementation( diff --git a/packages/protocol/genesis/test_config.js b/packages/protocol/genesis/test_config.js index c0a90698ed..4363719364 100644 --- a/packages/protocol/genesis/test_config.js +++ b/packages/protocol/genesis/test_config.js @@ -2,8 +2,7 @@ const ADDRESS_LENGTH = 40; module.exports = { - ownerTimelockController: "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", - ownerSecurityCouncil: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + contractOwner: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", l1ChainId: 1, chainId: 167, seedAccounts: [ diff --git a/packages/protocol/package.json b/packages/protocol/package.json index b04c2c2a79..000e97bf07 100644 --- a/packages/protocol/package.json +++ b/packages/protocol/package.json @@ -29,7 +29,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-promise": "^6.1.1", "ethers": "^5.7.2", - "solc": "0.7.3", + "solc": "0.8.24", "solhint": "^4.5.4", "ts-node": "^10.9.2", "typescript": "^5.2.2" diff --git a/packages/protocol/script/AddSGXVerifierInstances.s.sol b/packages/protocol/script/AddSGXVerifierInstances.s.sol index de8c02d4ad..a4abb02152 100644 --- a/packages/protocol/script/AddSGXVerifierInstances.s.sol +++ b/packages/protocol/script/AddSGXVerifierInstances.s.sol @@ -2,12 +2,10 @@ pragma solidity 0.8.24; import "../test/DeployCapability.sol"; -import "../contracts/L1/gov/TaikoTimelockController.sol"; import "../contracts/verifiers/SgxVerifier.sol"; contract AddSGXVerifierInstances is DeployCapability { uint256 public privateKey = vm.envUint("PRIVATE_KEY"); - address public timelockAddress = vm.envAddress("TIMELOCK_ADDRESS"); address public sgxVerifier = vm.envAddress("SGX_VERIFIER"); address[] public instances = vm.envAddress("INSTANCES", ","); @@ -16,27 +14,14 @@ contract AddSGXVerifierInstances is DeployCapability { vm.startBroadcast(privateKey); - updateInstancesByTimelock(timelockAddress); - - vm.stopBroadcast(); - } - - function updateInstancesByTimelock(address timelock) internal { - bytes32 salt = bytes32(block.timestamp); - - bytes memory payload = - abi.encodeWithSelector(bytes4(keccak256("addInstances(address[])")), instances); - - TaikoTimelockController timelockController = TaikoTimelockController(payable(timelock)); - - timelockController.schedule(sgxVerifier, 0, payload, bytes32(0), salt, 0); - - timelockController.execute(sgxVerifier, 0, payload, bytes32(0), salt); + SgxVerifier(sgxVerifier).addInstances(instances); for (uint256 i; i < instances.length; ++i) { console2.log("New instance added:"); console2.log("index: ", i); console2.log("instance: ", instances[0]); } + + vm.stopBroadcast(); } } diff --git a/packages/protocol/script/AuthorizeTaikoForMultihop.s.sol b/packages/protocol/script/AuthorizeTaikoForMultihop.s.sol index 5929e4e0ac..322d83de80 100644 --- a/packages/protocol/script/AuthorizeTaikoForMultihop.s.sol +++ b/packages/protocol/script/AuthorizeTaikoForMultihop.s.sol @@ -2,13 +2,11 @@ pragma solidity 0.8.24; import "../test/DeployCapability.sol"; -import "../contracts/L1/gov/TaikoTimelockController.sol"; import "../contracts/signal/SignalService.sol"; contract AuthorizeTaikoForMultihop is DeployCapability { uint256 public privateKey = vm.envUint("PRIVATE_KEY"); address public sharedSignalService = vm.envAddress("SHARED_SIGNAL_SERVICE"); - address public timelockAddress = vm.envAddress("TIMELOCK_ADDRESS"); // TaikoL1 and TaikoL2 contracts address[] public taikoContracts = vm.envAddress("TAIKO_CONTRACTS", ","); @@ -16,18 +14,8 @@ contract AuthorizeTaikoForMultihop is DeployCapability { require(taikoContracts.length != 0, "invalid taiko contracts"); vm.startBroadcast(privateKey); - for (uint256 i; i < taikoContracts.length; ++i) { - bytes32 salt = bytes32(block.timestamp); - - bytes memory payload = - abi.encodeCall(SignalService.authorize, (taikoContracts[i], true)); - - TaikoTimelockController timelock = TaikoTimelockController(payable(timelockAddress)); - - timelock.schedule(sharedSignalService, 0, payload, bytes32(0), salt, 0); - - timelock.execute(sharedSignalService, 0, payload, bytes32(0), salt); + SignalService(sharedSignalService).authorize(taikoContracts[i], true); } vm.stopBroadcast(); diff --git a/packages/protocol/script/DeployOnL1.s.sol b/packages/protocol/script/DeployOnL1.s.sol index 5f65a2b1eb..bd2b26ef86 100644 --- a/packages/protocol/script/DeployOnL1.s.sol +++ b/packages/protocol/script/DeployOnL1.s.sol @@ -11,8 +11,6 @@ import "../contracts/L1/tiers/DevnetTierProvider.sol"; import "../contracts/L1/tiers/TierProviderV1.sol"; import "../contracts/L1/tiers/TierProviderV2.sol"; import "../contracts/L1/hooks/AssignmentHook.sol"; -import "../contracts/L1/gov/TaikoTimelockController.sol"; -import "../contracts/L1/gov/TaikoGovernor.sol"; import "../contracts/bridge/Bridge.sol"; import "../contracts/tokenvault/ERC20Vault.sol"; import "../contracts/tokenvault/ERC1155Vault.sol"; @@ -36,12 +34,10 @@ import { P256Verifier } from "p256-verifier/src/P256Verifier.sol"; /// @notice This script deploys the core Taiko protocol smart contract on L1, /// initializing the rollup. contract DeployOnL1 is DeployCapability { - uint256 public constant NUM_GUARDIANS = 5; + uint256 public constant NUM_MIN_MAJORITY_GUARDIANS = 7; + uint256 public constant NUM_MIN_MINORITY_GUARDIANS = 2; - address public constant MAINNET_SECURITY_COUNCIL = 0x7C50d60743D3FCe5a39FdbF687AFbAe5acFF49Fd; - - address securityCouncil = - block.chainid == 1 ? MAINNET_SECURITY_COUNCIL : vm.envAddress("SECURITY_COUNCIL"); + address public constant MAINNET_CONTRACT_OWNER = 0x9CBeE534B5D8a6280e01a14844Ee8aF350399C7F; // admin.taiko.eth modifier broadcast() { uint256 privateKey = vm.envUint("PRIVATE_KEY"); @@ -54,16 +50,18 @@ contract DeployOnL1 is DeployCapability { function run() external broadcast { addressNotNull(vm.envAddress("TAIKO_L2_ADDRESS"), "TAIKO_L2_ADDRESS"); addressNotNull(vm.envAddress("L2_SIGNAL_SERVICE"), "L2_SIGNAL_SERVICE"); + addressNotNull(vm.envAddress("CONTRACT_OWNER"), "CONTRACT_OWNER"); + require(vm.envBytes32("L2_GENESIS_HASH") != 0, "L2_GENESIS_HASH"); + address contractOwner = vm.envAddress("CONTRACT_OWNER"); // --------------------------------------------------------------- // Deploy shared contracts - (address sharedAddressManager, address timelock, address governor) = deploySharedContracts(); + (address sharedAddressManager) = deploySharedContracts(contractOwner); console2.log("sharedAddressManager: ", sharedAddressManager); - console2.log("timelock: ", timelock); // --------------------------------------------------------------- // Deploy rollup contracts - address rollupAddressManager = deployRollupContracts(sharedAddressManager, timelock); + address rollupAddressManager = deployRollupContracts(sharedAddressManager, contractOwner); // --------------------------------------------------------------- // Signal service need to authorize the new rollup @@ -92,24 +90,8 @@ contract DeployOnL1 is DeployCapability { console2.log("signalService.owner(): ", signalService.owner()); console2.log("------------------------------------------"); - TaikoTimelockController _timelock = TaikoTimelockController(payable(timelock)); - if (signalService.owner() == msg.sender) { - // Setup time lock roles - // Only the governor can make proposals after holders voting. - _timelock.grantRole(_timelock.PROPOSER_ROLE(), governor); - _timelock.grantRole(_timelock.PROPOSER_ROLE(), msg.sender); - - // Granting address(0) the executor role to allow open execution. - _timelock.grantRole(_timelock.EXECUTOR_ROLE(), address(0)); - _timelock.grantRole(_timelock.EXECUTOR_ROLE(), msg.sender); - - _timelock.grantRole(_timelock.TIMELOCK_ADMIN_ROLE(), securityCouncil); - _timelock.grantRole(_timelock.PROPOSER_ROLE(), securityCouncil); - _timelock.grantRole(_timelock.EXECUTOR_ROLE(), securityCouncil); - - signalService.transferOwnership(timelock); - acceptOwnership(signalServiceAddr, TimelockControllerUpgradeable(payable(timelock))); + signalService.transferOwnership(contractOwner); } else { console2.log("------------------------------------------"); console2.log("Warning - you need to transact manually:"); @@ -138,35 +120,21 @@ contract DeployOnL1 is DeployCapability { // --------------------------------------------------------------- // Deploy other contracts - deployAuxContracts(); + if (block.chainid != 1) { + deployAuxContracts(); + } if (AddressManager(sharedAddressManager).owner() == msg.sender) { - AddressManager(sharedAddressManager).transferOwnership(timelock); - acceptOwnership(sharedAddressManager, TimelockControllerUpgradeable(payable(timelock))); - console2.log("** sharedAddressManager ownership transferred to timelock:", timelock); + AddressManager(sharedAddressManager).transferOwnership(contractOwner); + console2.log("** sharedAddressManager ownership transferred to:", contractOwner); } - AddressManager(rollupAddressManager).transferOwnership(timelock); - acceptOwnership(rollupAddressManager, TimelockControllerUpgradeable(payable(timelock))); - console2.log("** rollupAddressManager ownership transferred to timelock:", timelock); - - _timelock.revokeRole(_timelock.TIMELOCK_ADMIN_ROLE(), address(this)); - _timelock.revokeRole(_timelock.PROPOSER_ROLE(), msg.sender); - _timelock.revokeRole(_timelock.EXECUTOR_ROLE(), msg.sender); - _timelock.transferOwnership(securityCouncil); - _timelock.renounceRole(_timelock.TIMELOCK_ADMIN_ROLE(), msg.sender); + AddressManager(rollupAddressManager).transferOwnership(contractOwner); + console2.log("** rollupAddressManager ownership transferred to:", contractOwner); } - function deploySharedContracts() - internal - returns (address sharedAddressManager, address timelock, address governor) - { - // Deploy the timelock - timelock = deployProxy({ - name: "timelock_controller", - impl: address(new TaikoTimelockController()), - data: abi.encodeCall(TaikoTimelockController.init, (address(0), 7 days)) - }); + function deploySharedContracts(address owner) internal returns (address sharedAddressManager) { + addressNotNull(owner, "owner"); sharedAddressManager = vm.envAddress("SHARED_ADDRESS_MANAGER"); if (sharedAddressManager == address(0)) { @@ -185,7 +153,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall( TaikoToken.init, ( - timelock, + owner, vm.envString("TAIKO_TOKEN_NAME"), vm.envString("TAIKO_TOKEN_SYMBOL"), vm.envAddress("TAIKO_TOKEN_PREMINT_RECIPIENT") @@ -195,19 +163,6 @@ contract DeployOnL1 is DeployCapability { }); } - governor = deployProxy({ - name: "taiko_governor", - impl: address(new TaikoGovernor()), - data: abi.encodeCall( - TaikoGovernor.init, - ( - timelock, - IVotesUpgradeable(taikoToken), - TimelockControllerUpgradeable(payable(timelock)) - ) - ) - }); - // Deploy Bridging contracts deployProxy({ name: "signal_service", @@ -216,13 +171,19 @@ contract DeployOnL1 is DeployCapability { registerTo: sharedAddressManager }); - deployProxy({ + address brdige = deployProxy({ name: "bridge", impl: address(new Bridge()), - data: abi.encodeCall(Bridge.init, (timelock, sharedAddressManager)), + data: abi.encodeCall(Bridge.init, (address(0), sharedAddressManager)), registerTo: sharedAddressManager }); + if (vm.envBool("PAUSE_BRIDGE")) { + Bridge(payable(brdige)).pause(); + } + + Bridge(payable(brdige)).transferOwnership(owner); + console2.log("------------------------------------------"); console2.log( "Warning - you need to register *all* counterparty bridges to enable multi-hop bridging:" @@ -236,21 +197,21 @@ contract DeployOnL1 is DeployCapability { deployProxy({ name: "erc20_vault", impl: address(new ERC20Vault()), - data: abi.encodeCall(ERC20Vault.init, (timelock, sharedAddressManager)), + data: abi.encodeCall(ERC20Vault.init, (owner, sharedAddressManager)), registerTo: sharedAddressManager }); deployProxy({ name: "erc721_vault", impl: address(new ERC721Vault()), - data: abi.encodeCall(ERC721Vault.init, (timelock, sharedAddressManager)), + data: abi.encodeCall(ERC721Vault.init, (owner, sharedAddressManager)), registerTo: sharedAddressManager }); deployProxy({ name: "erc1155_vault", impl: address(new ERC1155Vault()), - data: abi.encodeCall(ERC1155Vault.init, (timelock, sharedAddressManager)), + data: abi.encodeCall(ERC1155Vault.init, (owner, sharedAddressManager)), registerTo: sharedAddressManager }); @@ -277,13 +238,13 @@ contract DeployOnL1 is DeployCapability { function deployRollupContracts( address _sharedAddressManager, - address timelock + address owner ) internal returns (address rollupAddressManager) { addressNotNull(_sharedAddressManager, "sharedAddressManager"); - addressNotNull(timelock, "timelock"); + addressNotNull(owner, "owner"); rollupAddressManager = deployProxy({ name: "rollup_address_manager", @@ -303,7 +264,7 @@ contract DeployOnL1 is DeployCapability { data: abi.encodeCall( TaikoL1.init, ( - timelock, + owner, rollupAddressManager, vm.envBytes32("L2_GENESIS_HASH"), vm.envBool("PAUSE_TAIKO_L1") @@ -315,20 +276,20 @@ contract DeployOnL1 is DeployCapability { deployProxy({ name: "assignment_hook", impl: address(new AssignmentHook()), - data: abi.encodeCall(AssignmentHook.init, (timelock, rollupAddressManager)) + data: abi.encodeCall(AssignmentHook.init, (owner, rollupAddressManager)) }); deployProxy({ name: "tier_provider", impl: deployTierProvider(vm.envString("TIER_PROVIDER")), - data: abi.encodeCall(TierProviderV1.init, (timelock)), + data: abi.encodeCall(TierProviderV1.init, (owner)), registerTo: rollupAddressManager }); deployProxy({ name: "tier_sgx", impl: address(new SgxVerifier()), - data: abi.encodeCall(SgxVerifier.init, (timelock, rollupAddressManager)), + data: abi.encodeCall(SgxVerifier.init, (owner, rollupAddressManager)), registerTo: rollupAddressManager }); @@ -355,26 +316,34 @@ contract DeployOnL1 is DeployCapability { address[] memory guardians = vm.envAddress("GUARDIAN_PROVERS", ","); - GuardianProver(guardianProverMinority).setGuardians(guardians, 1); - GuardianProver(guardianProverMinority).transferOwnership(timelock); + GuardianProver(guardianProverMinority).setGuardians( + guardians, uint8(NUM_MIN_MINORITY_GUARDIANS) + ); + GuardianProver(guardianProverMinority).transferOwnership(owner); - GuardianProver(guardianProver).setGuardians(guardians, uint8(vm.envUint("MIN_GUARDIANS"))); - GuardianProver(guardianProver).transferOwnership(timelock); + GuardianProver(guardianProver).setGuardians(guardians, uint8(NUM_MIN_MAJORITY_GUARDIANS)); + GuardianProver(guardianProver).transferOwnership(owner); // No need to proxy these, because they are 3rd party. If we want to modify, we simply // change the registerAddress("automata_dcap_attestation", address(attestation)); P256Verifier p256Verifier = new P256Verifier(); SigVerifyLib sigVerifyLib = new SigVerifyLib(address(p256Verifier)); PEMCertChainLib pemCertChainLib = new PEMCertChainLib(); - AutomataDcapV3Attestation automateDcapV3Attestation = - new AutomataDcapV3Attestation(address(sigVerifyLib), address(pemCertChainLib)); + address automateDcapV3AttestationImpl = address(new AutomataDcapV3Attestation()); + + address automataProxy = deployProxy({ + name: "automata_dcap_attestation", + impl: automateDcapV3AttestationImpl, + data: abi.encodeCall( + AutomataDcapV3Attestation.init, (owner, address(sigVerifyLib), address(pemCertChainLib)) + ), + registerTo: rollupAddressManager + }); // Log addresses for the user to register sgx instance console2.log("SigVerifyLib", address(sigVerifyLib)); console2.log("PemCertChainLib", address(pemCertChainLib)); - register( - rollupAddressManager, "automata_dcap_attestation", address(automateDcapV3Attestation) - ); + console2.log("AutomataDcapVaAttestation", automataProxy); } function deployTierProvider(string memory tierProviderName) private returns (address) { @@ -400,12 +369,4 @@ contract DeployOnL1 is DeployCapability { function addressNotNull(address addr, string memory err) private pure { require(addr != address(0), err); } - - function acceptOwnership(address proxy, TimelockControllerUpgradeable timelock) internal { - bytes32 salt = bytes32(block.timestamp); - bytes memory payload = abi.encodeCall(Ownable2StepUpgradeable(proxy).acceptOwnership, ()); - - timelock.schedule(proxy, 0, payload, bytes32(0), salt, 0); - timelock.execute(proxy, 0, payload, bytes32(0), salt); - } } diff --git a/packages/protocol/script/SetRemoteBridgeSuites.s.sol b/packages/protocol/script/SetRemoteBridgeSuites.s.sol index ff19ac02b5..a851ff7715 100644 --- a/packages/protocol/script/SetRemoteBridgeSuites.s.sol +++ b/packages/protocol/script/SetRemoteBridgeSuites.s.sol @@ -2,7 +2,6 @@ pragma solidity 0.8.24; import "../test/DeployCapability.sol"; -import "../contracts/L1/gov/TaikoTimelockController.sol"; contract SetRemoteBridgeSuites is DeployCapability { uint256 public privateKey = vm.envUint("PRIVATE_KEY"); @@ -75,17 +74,7 @@ contract SetRemoteBridgeSuites is DeployCapability { ) internal { - bytes32 salt = bytes32(block.timestamp); - - bytes memory payload = - abi.encodeCall(AddressManager.setAddress, (chainId, bytes32(bytes(name)), addr)); - - TaikoTimelockController timelock = TaikoTimelockController(payable(timelockAddress)); - - timelock.schedule(registerTo, 0, payload, bytes32(0), salt, 0); - - timelock.execute(registerTo, 0, payload, bytes32(0), salt); - + AddressManager(registerTo).setAddress(chainId, bytes32(bytes(name)), addr); console2.log("> ", name, "@", registerTo); console2.log("\t addr : ", addr); } diff --git a/packages/protocol/script/test_deploy_on_l1.sh b/packages/protocol/script/test_deploy_on_l1.sh index e63f92771a..85703d3acc 100755 --- a/packages/protocol/script/test_deploy_on_l1.sh +++ b/packages/protocol/script/test_deploy_on_l1.sh @@ -7,17 +7,17 @@ export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f PROPOSER=0x0000000000000000000000000000000000000000 \ TAIKO_TOKEN=0x0000000000000000000000000000000000000000 \ PROPOSER_ONE=0x0000000000000000000000000000000000000000 \ -GUARDIAN_PROVERS="0x1000777700000000000000000000000000000001,0x1000777700000000000000000000000000000002,0x1000777700000000000000000000000000000003,0x1000777700000000000000000000000000000004,0x1000777700000000000000000000000000000005" \ -MIN_GUARDIANS=3 \ +GUARDIAN_PROVERS="0x1000777700000000000000000000000000000001,0x1000777700000000000000000000000000000002,0x1000777700000000000000000000000000000003,0x1000777700000000000000000000000000000004,0x1000777700000000000000000000000000000005,0x1000777700000000000000000000000000000006,0x1000777700000000000000000000000000000007" \ TAIKO_L2_ADDRESS=0x1000777700000000000000000000000000000001 \ L2_SIGNAL_SERVICE=0x1000777700000000000000000000000000000007 \ -SECURITY_COUNCIL=0x60997970C51812dc3A010C7d01b50e0d17dc79C8 \ +CONTRACT_OWNER=0x60997970C51812dc3A010C7d01b50e0d17dc79C8 \ TAIKO_TOKEN_PREMINT_RECIPIENT=0xa0Ee7A142d267C1f36714E4a8F75612F20a79720 \ TAIKO_TOKEN_NAME="Taiko Token Katla" \ TAIKO_TOKEN_SYMBOL=TTKOk \ SHARED_ADDRESS_MANAGER=0x0000000000000000000000000000000000000000 \ L2_GENESIS_HASH=0xee1950562d42f0da28bd4550d88886bc90894c77c9c9eaefef775d4c8223f259 \ PAUSE_TAIKO_L1=true \ +PAUSE_BRIDGE=true \ TIER_PROVIDER="devnet" \ forge script script/DeployOnL1.s.sol:DeployOnL1 \ --fork-url http://localhost:8545 \ diff --git a/packages/protocol/script/upgrade/UpgradeAddressManager.s.sol b/packages/protocol/script/upgrade/UpgradeAddressManager.s.sol index 829ff2590e..c62a98e603 100644 --- a/packages/protocol/script/upgrade/UpgradeAddressManager.s.sol +++ b/packages/protocol/script/upgrade/UpgradeAddressManager.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeAddressManager is UpgradeScript { function run() external setUp { - console2.log("upgrading AddressManager"); - AddressManager newAddressManager = new AddressManager(); - upgrade(address(newAddressManager)); - - console2.log("upgraded AddressManager to", address(newAddressManager)); + upgrade("AddressManager", address(new AddressManager())); } } diff --git a/packages/protocol/script/upgrade/UpgradeAssignmentHook.s.sol b/packages/protocol/script/upgrade/UpgradeAssignmentHook.s.sol index f48779bf9b..6532fd8278 100644 --- a/packages/protocol/script/upgrade/UpgradeAssignmentHook.s.sol +++ b/packages/protocol/script/upgrade/UpgradeAssignmentHook.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeAssignmentHook is UpgradeScript { function run() external setUp { - console2.log("upgrading AssignmentHook"); - AssignmentHook newAssignmentHook = new AssignmentHook(); - upgrade(address(newAssignmentHook)); - - console2.log("upgraded AssignmentHook to", address(newAssignmentHook)); + upgrade("AssignmentHook", address(new AssignmentHook())); } } diff --git a/packages/protocol/script/upgrade/UpgradeBridge.s.sol b/packages/protocol/script/upgrade/UpgradeBridge.s.sol index 9c1ac14e6e..37459f216e 100644 --- a/packages/protocol/script/upgrade/UpgradeBridge.s.sol +++ b/packages/protocol/script/upgrade/UpgradeBridge.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeBridge is UpgradeScript { function run() external setUp { - console2.log("upgrading bridge"); - Bridge newBridge = new Bridge(); - upgrade(address(newBridge)); - - console2.log("upgraded bridge to", address(newBridge)); + upgrade("Bridge", address(new Bridge())); } } diff --git a/packages/protocol/script/upgrade/UpgradeERC1155Vault.s.sol b/packages/protocol/script/upgrade/UpgradeERC1155Vault.s.sol index c819962080..5813f4e58c 100644 --- a/packages/protocol/script/upgrade/UpgradeERC1155Vault.s.sol +++ b/packages/protocol/script/upgrade/UpgradeERC1155Vault.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeERC1155Vault is UpgradeScript { function run() external setUp { - console2.log("upgrading ERC1155Vault"); - ERC1155Vault newERC1155Vault = new ERC1155Vault(); - upgrade(address(newERC1155Vault)); - - console2.log("upgraded ERC1155Vault to", address(newERC1155Vault)); + upgrade("ERC1155Vault", address(new ERC1155Vault())); } } diff --git a/packages/protocol/script/upgrade/UpgradeERC20Vault.s.sol b/packages/protocol/script/upgrade/UpgradeERC20Vault.s.sol index f467241358..33a65c20e0 100644 --- a/packages/protocol/script/upgrade/UpgradeERC20Vault.s.sol +++ b/packages/protocol/script/upgrade/UpgradeERC20Vault.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeERC20Vault is UpgradeScript { function run() external setUp { - console2.log("upgrading ERC20Vault"); - ERC20Vault newERC20Vault = new ERC20Vault(); - upgrade(address(newERC20Vault)); - - console2.log("upgraded ERC20Vault to", address(newERC20Vault)); + upgrade("ERC20Vault", address(new ERC20Vault())); } } diff --git a/packages/protocol/script/upgrade/UpgradeERC721Vault.s.sol b/packages/protocol/script/upgrade/UpgradeERC721Vault.s.sol index 406773cec6..84cbdcaf9e 100644 --- a/packages/protocol/script/upgrade/UpgradeERC721Vault.s.sol +++ b/packages/protocol/script/upgrade/UpgradeERC721Vault.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeERC721Vault is UpgradeScript { function run() external setUp { - console2.log("upgrading ERC721Vault"); - ERC721Vault newERC721Vault = new ERC721Vault(); - upgrade(address(newERC721Vault)); - - console2.log("upgraded ERC721Vault to", address(newERC721Vault)); + upgrade("ERC721Vault", address(new ERC721Vault())); } } diff --git a/packages/protocol/script/upgrade/UpgradeGuardianProver.s.sol b/packages/protocol/script/upgrade/UpgradeGuardianProver.s.sol index cce9a7136b..e86523e49d 100644 --- a/packages/protocol/script/upgrade/UpgradeGuardianProver.s.sol +++ b/packages/protocol/script/upgrade/UpgradeGuardianProver.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeGuardianProver is UpgradeScript { function run() external setUp { - console2.log("upgrading GuardianProver"); - GuardianProver newGuardianProver = new GuardianProver(); - upgrade(address(newGuardianProver)); - - console2.log("upgraded GuardianProver to", address(newGuardianProver)); + upgrade("GuardianProver", address(new GuardianProver())); } } diff --git a/packages/protocol/script/upgrade/UpgradeScript.s.sol b/packages/protocol/script/upgrade/UpgradeScript.s.sol index fa6d833290..3a5d70c18e 100644 --- a/packages/protocol/script/upgrade/UpgradeScript.s.sol +++ b/packages/protocol/script/upgrade/UpgradeScript.s.sol @@ -1,7 +1,6 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.24; -import "../../contracts/L1/gov/TaikoTimelockController.sol"; import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol"; import "forge-std/src/console2.sol"; @@ -9,20 +8,15 @@ import "forge-std/src/Script.sol"; contract UpgradeScript is Script { uint256 public privateKey = vm.envUint("PRIVATE_KEY"); - address public timelockAddress = vm.envAddress("TIMELOCK_ADDRESS"); address public proxyAddress = vm.envAddress("PROXY_ADDRESS"); UUPSUpgradeable proxy; - TaikoTimelockController timelock; modifier setUp() { require(privateKey != 0, "PRIVATE_KEY not set"); require(proxyAddress != address(0), "PROXY_ADDRESS not set"); - require(timelockAddress != address(0), "TIMELOCK_ADDRESS not set"); proxy = UUPSUpgradeable(payable(proxyAddress)); - timelock = TaikoTimelockController(payable(timelockAddress)); - vm.startBroadcast(privateKey); _; @@ -30,14 +24,9 @@ contract UpgradeScript is Script { vm.stopBroadcast(); } - function upgrade(address newImpl) public { - bytes32 salt = bytes32(block.timestamp); - - bytes memory payload = - abi.encodeWithSelector(bytes4(keccak256("upgradeTo(address)")), newImpl); - - timelock.schedule(address(proxy), 0, payload, bytes32(0), salt, 0); - - timelock.execute(address(proxy), 0, payload, bytes32(0), salt); + function upgrade(string memory name, address newImpl) public { + console2.log("Upgrading", name, proxyAddress); + proxy.upgradeTo(newImpl); + console2.log("Upgraded", proxyAddress, "to", newImpl); } } diff --git a/packages/protocol/script/upgrade/UpgradeSignalService.s.sol b/packages/protocol/script/upgrade/UpgradeSignalService.s.sol index 0f5271865a..258b8a8add 100644 --- a/packages/protocol/script/upgrade/UpgradeSignalService.s.sol +++ b/packages/protocol/script/upgrade/UpgradeSignalService.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeSignalService is UpgradeScript { function run() external setUp { - console2.log("upgrading SignalService"); - SignalService newSignalService = new SignalService(); - upgrade(address(newSignalService)); - - console2.log("upgraded SignalService to", address(newSignalService)); + upgrade("SignalService", address(new SignalService())); } } diff --git a/packages/protocol/script/upgrade/UpgradeTaikoGovernor.s.sol b/packages/protocol/script/upgrade/UpgradeTaikoGovernor.s.sol deleted file mode 100644 index 18cf211336..0000000000 --- a/packages/protocol/script/upgrade/UpgradeTaikoGovernor.s.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "forge-std/src/Script.sol"; -import "forge-std/src/console2.sol"; -import "../../contracts/L1/gov/TaikoGovernor.sol"; -import "./UpgradeScript.s.sol"; - -contract UpgradeTaikoGovernor is UpgradeScript { - function run() external setUp { - console2.log("upgrading TaikoGovernor"); - TaikoGovernor newTaikoGovernor = new TaikoGovernor(); - upgrade(address(newTaikoGovernor)); - - console2.log("upgraded TaikoGovernor to", address(newTaikoGovernor)); - } -} diff --git a/packages/protocol/script/upgrade/UpgradeTaikoL1.s.sol b/packages/protocol/script/upgrade/UpgradeTaikoL1.s.sol index b142466aca..6f9b7bfd5b 100644 --- a/packages/protocol/script/upgrade/UpgradeTaikoL1.s.sol +++ b/packages/protocol/script/upgrade/UpgradeTaikoL1.s.sol @@ -8,10 +8,6 @@ import "./UpgradeScript.s.sol"; contract UpgradeTaikoL1 is UpgradeScript { function run() external setUp { - console2.log("upgrading TaikoL1"); - TaikoL1 newTaikoL1 = new TaikoL1(); - upgrade(address(newTaikoL1)); - - console2.log("upgraded TaikoL1 to", address(newTaikoL1)); + upgrade("TaikoL1", address(new TaikoL1())); } } diff --git a/packages/protocol/script/upgrade/UpgradeTierProvider.s.sol b/packages/protocol/script/upgrade/UpgradeTierProvider.s.sol index 2d9082876c..0908967e2c 100644 --- a/packages/protocol/script/upgrade/UpgradeTierProvider.s.sol +++ b/packages/protocol/script/upgrade/UpgradeTierProvider.s.sol @@ -2,47 +2,19 @@ pragma solidity 0.8.24; import "../../test/DeployCapability.sol"; -import "../../contracts/L1/gov/TaikoTimelockController.sol"; import "../../contracts/L1/tiers/ITierProvider.sol"; import "../../contracts/L1/tiers/TierProviderV1.sol"; contract UpgradeTierProvider is DeployCapability { uint256 public privateKey = vm.envUint("PRIVATE_KEY"); - address public timelockAddress = vm.envAddress("TIMELOCK_ADDRESS"); - address public addressManagerAddress = vm.envAddress("ADDRESS_MANAGER_ADDRESS"); + address public addressManager = vm.envAddress("ADDRESS_MANAGER_ADDRESS"); function run() external { vm.startBroadcast(privateKey); - - ITierProvider newTierProvider = new TierProviderV1(); - - registerByTimelock( - addressManagerAddress, "tier_provider", address(newTierProvider), uint64(block.chainid) - ); - + address impl = address(new TierProviderV1()); + AddressManager(addressManager).setAddress(uint64(block.chainid), "tier_provider", impl); vm.stopBroadcast(); - } - - function registerByTimelock( - address registerTo, - string memory name, - address addr, - uint64 chainId - ) - internal - { - bytes32 salt = bytes32(block.timestamp); - - bytes memory payload = - abi.encodeCall(AddressManager.setAddress, (chainId, bytes32(bytes(name)), addr)); - - TaikoTimelockController timelock = TaikoTimelockController(payable(timelockAddress)); - - timelock.schedule(registerTo, 0, payload, bytes32(0), salt, 0); - - timelock.execute(registerTo, 0, payload, bytes32(0), salt); - - console2.log("> ", name, "@", registerTo); - console2.log("\t addr : ", addr); + console2.log("> tier_provider@", addressManager); + console2.log("\t addr : ", impl); } } diff --git a/packages/protocol/script/upgrade/UpgradeTimelockController.s.sol b/packages/protocol/script/upgrade/UpgradeTimelockController.s.sol deleted file mode 100644 index 2dc1430f80..0000000000 --- a/packages/protocol/script/upgrade/UpgradeTimelockController.s.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "forge-std/src/Script.sol"; -import "forge-std/src/console2.sol"; -import "../../contracts/L1/gov/TaikoTimelockController.sol"; -import "./UpgradeScript.s.sol"; - -contract UpgradeTaikoTimelockController is UpgradeScript { - function run() external setUp { - console2.log("upgrading TaikoTimelockController"); - TaikoTimelockController newTaikoTimelockController = new TaikoTimelockController(); - upgrade(address(newTaikoTimelockController)); - - console2.log("upgraded TaikoTimelockController to", address(newTaikoTimelockController)); - } -} diff --git a/packages/protocol/test/L1/gov/TaikoGovernor.t.sol b/packages/protocol/test/L1/gov/TaikoGovernor.t.sol deleted file mode 100644 index e9a42b57de..0000000000 --- a/packages/protocol/test/L1/gov/TaikoGovernor.t.sol +++ /dev/null @@ -1,222 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "../TaikoL1TestBase.sol"; -import "../../../contracts/L1/gov/TaikoGovernor.sol"; -import "../../../contracts/L1/gov/TaikoTimelockController.sol"; -import "@openzeppelin/contracts/governance/IGovernor.sol"; -import "@openzeppelin/contracts/governance/TimelockController.sol"; - -/// @author Kirk Baird -contract TestTaikoGovernor is TaikoL1TestBase { - TaikoGovernor public taikoGovernor; - TaikoTimelockController public taikoTimelockController; - - function deployTaikoL1() internal override returns (TaikoL1) { - return - TaikoL1(payable(deployProxy({ name: "taiko", impl: address(new TaikoL1()), data: "" }))); - } - - function setUp() public override { - // Call the TaikoL1TestBase setUp() - super.setUp(); - - // deploy TaikoTimelockController - taikoTimelockController = TaikoTimelockController( - payable(address(new ERC1967Proxy(address(new TaikoTimelockController()), ""))) - ); - - // init TaikoTimelockController - uint256 minDelay = 0.5 days; - taikoTimelockController.init(address(0), minDelay); - - // deploy TaikoGovernor - - taikoGovernor = - TaikoGovernor(payable(address(new ERC1967Proxy(address(new TaikoGovernor()), "")))); - - // init TaikoGovernor - taikoGovernor.init(address(0), tko, taikoTimelockController); - // Alice delegate voting power to self - vm.startPrank(Alice); - tko.delegate(Alice); - vm.stopPrank(); - - address owner = taikoTimelockController.owner(); - vm.startPrank(owner); - // Owner set access controls for timelock controller - taikoTimelockController.grantRole( - taikoTimelockController.PROPOSER_ROLE(), address(taikoGovernor) - ); - taikoTimelockController.grantRole( - taikoTimelockController.EXECUTOR_ROLE(), address(taikoGovernor) - ); - taikoTimelockController.grantRole( - taikoTimelockController.CANCELLER_ROLE(), address(taikoGovernor) - ); - - // Owner delegate voting power to self - tko.delegate(owner); - - // Transfer Alice double the proposal threshold worth of tokens - uint256 proposalThreshold = taikoGovernor.proposalThreshold(); - tko.transfer(Alice, proposalThreshold * 2); - tko.transfer(Bob, proposalThreshold * 5); - vm.roll(block.number + 1); // increase block number to help facilitate snapshots in - // TaikoToken - - vm.stopPrank(); - } - - function test_init() public { - // GovernorVotesQuorumFractionUpgradeable - assertEq(taikoGovernor.quorumNumerator(), 4, "Incorrect initial quorum numerator"); - assertEq( - taikoGovernor.quorumNumerator(block.number), - 4, - "Incorrect initial block quorum numerator" - ); - assertEq(taikoGovernor.quorumDenominator(), 100, "Incorrect quorum denominator"); - - // GovernorUpgradeable - assertEq(taikoGovernor.name(), "TaikoGovernor", "Incorrect name"); - assertEq(taikoGovernor.version(), "1", "Incorrect version"); - - // GovernorVotesUpgradeable - assertEq(address(taikoGovernor.token()), address(tko), "Incorrect token"); - - // GovernorCompatibilityBravoUpgradeable - assertEq( - taikoGovernor.COUNTING_MODE(), "support=bravo&quorum=bravo", "Incorrect counting mode" - ); - - // GovernorTimelockControlUpgradeable - assertEq(taikoGovernor.timelock(), address(taikoTimelockController), "Incorrect timelock"); - - // Interfaces - assertEq( - taikoGovernor.supportsInterface(type(IGovernorTimelockUpgradeable).interfaceId), - true, - "Incorrect supports interface" - ); - assertEq( - taikoGovernor.supportsInterface(type(IERC1155ReceiverUpgradeable).interfaceId), - true, - "Incorrect supports interface" - ); - - // TaikoGovernor - assertEq(taikoGovernor.votingDelay(), 7200, "Incorrect voting delay"); - assertEq(taikoGovernor.votingPeriod(), 50_400, "Incorrect voting period"); - assertEq(taikoGovernor.proposalThreshold(), 100_000 ether, "Incorrect proposal threshold"); - } - - // Tests `propose()` - function test_propose() public { - // Parameters for `TaikoGovernor.propose()` - address[] memory targets = new address[](1); - targets[0] = Alice; - - uint256[] memory values = new uint256[](1); - values[0] = 1 ether; - - bytes[] memory calldatas = new bytes[](1); - - string memory description = "Send alice an ether"; - - address proposer = Alice; - vm.startPrank(proposer); - - // Prepare for event emission - uint256 startBlock = block.number + taikoGovernor.votingDelay(); - uint256 endBlock = startBlock + taikoGovernor.votingPeriod(); - uint256 calculatedProposalId = - taikoGovernor.hashProposal(targets, values, calldatas, keccak256(bytes(description))); - - vm.expectEmit(true, true, true, true); - emit IGovernor.ProposalCreated( - calculatedProposalId, - Alice, - targets, - values, - new string[](targets.length), - calldatas, - startBlock, - endBlock, - description - ); - - // `propose()` - uint256 proposalId = taikoGovernor.propose(targets, values, calldatas, description); - vm.stopPrank(); - - // Validate proposal - assertEq(proposalId, calculatedProposalId, "Proposal does not have the correct ID"); - assertEq( - taikoGovernor.state(proposalId) == IGovernorUpgradeable.ProposalState.Pending, - true, - "Incorrect proposal state" - ); - assertEq( - taikoGovernor.proposalSnapshot(proposalId), startBlock, "Incorrect proposal snapshot" - ); - assertEq( - taikoGovernor.proposalDeadline(proposalId), endBlock, "Incorrect proposal deadline" - ); - } - - // Tests `castVote()`, `queue()` and `execute()` - function test_execute() public { - // Parameters for `propose()` - address proposer = Alice; - address[] memory targets = new address[](1); - targets[0] = Alice; - uint256[] memory values = new uint256[](1); - values[0] = 1 ether; - bytes[] memory calldatas = new bytes[](1); - string memory description = "Send alice an ether"; - bytes32 descriptionHash = keccak256(bytes(description)); - - // Send the values to the timelock controller for execute - (bool success,) = address(taikoTimelockController).call{ value: values[0] }(""); - - assertEq(success, true, "Transfer funds unsuccessful"); - - // `propose()` - vm.startPrank(proposer); - uint256 proposalId = taikoGovernor.propose(targets, values, calldatas, description); - vm.stopPrank(); - - // Skip to voting start - uint256 startBlock = taikoGovernor.proposalSnapshot(proposalId); - vm.roll(startBlock + 1); - - // `castVote()` - vm.startPrank(tko.owner()); - taikoGovernor.castVote(proposalId, 1); // 1 = for - - // Skip to voting end - uint256 endBlock = taikoGovernor.proposalDeadline(proposalId); - vm.roll(endBlock + 1); - - // `queue()` successful proposal - taikoGovernor.queue(proposalId); - - // Skip delay amount of time - uint256 eta = taikoGovernor.proposalEta(proposalId); - vm.warp(eta + 1); - - // Prepare execute event - bytes32 timelockId = taikoTimelockController.hashOperationBatch( - targets, values, calldatas, 0, descriptionHash - ); - vm.expectEmit(true, true, true, true); - emit TimelockController.CallExecuted(timelockId, 0, targets[0], values[0], calldatas[0]); - - // `execute()` - // taikoGovernor.execute(targets, values, calldatas, descriptionHash); - taikoGovernor.execute(proposalId); - - vm.stopPrank(); - } -} diff --git a/packages/protocol/test/L2/Lib1559Math.t.sol b/packages/protocol/test/L2/Lib1559Math.t.sol index 3dd5743258..84605c7506 100644 --- a/packages/protocol/test/L2/Lib1559Math.t.sol +++ b/packages/protocol/test/L2/Lib1559Math.t.sol @@ -14,16 +14,24 @@ contract TestLib1559Math is TaikoTest { uint256 i; baseFee = Lib1559Math.basefee(config.gasExcessMinValue, adjustmentFactor); - assertEq(baseFee, 99_627_953); // slightly smaller than 0.1gwei - console2.log("gasExcessMinValue:", config.gasExcessMinValue); - console2.log("min base fee:", baseFee); + assertEq(baseFee, 0.01 gwei); // 0.01gwei + console2.log("gasExcessMinValue:", config.gasExcessMinValue, "min base fee:", baseFee); + + for (; baseFee < 0.1 gwei; ++i) { + baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor); + console2.log("base fee:", i, baseFee); + } + + // base fee will reach 1 gwei if gasExcess > 18540000000 + console2.log("base fee will reach 0.1 gwei if gasExcess >", config.gasTargetPerL1Block * i); + assertEq(i, 309); for (; baseFee < 1 gwei; ++i) { baseFee = Lib1559Math.basefee(config.gasTargetPerL1Block * i, adjustmentFactor); console2.log("base fee:", i, baseFee); } - // base fee will reach 1 gwei if gasExcess > 19620000000 + // base fee will reach 10 gwei if gasExcess > 19620000000 console2.log("base fee will reach 1 gwei if gasExcess >", config.gasTargetPerL1Block * i); assertEq(i, 327); @@ -33,7 +41,7 @@ contract TestLib1559Math is TaikoTest { } // base fee will reach 10 gwei if gasExcess > 20760000000 - console2.log("base fee will reach 10 gwei if gasExcess >", config.gasTargetPerL1Block * i); + console2.log("base fee will reach 1 gwei if gasExcess >", config.gasTargetPerL1Block * i); assertEq(i, 346); } } diff --git a/packages/protocol/test/TaikoTest.sol b/packages/protocol/test/TaikoTest.sol index 7fd315bc65..b055be0383 100644 --- a/packages/protocol/test/TaikoTest.sol +++ b/packages/protocol/test/TaikoTest.sol @@ -20,7 +20,6 @@ import "../contracts/L1/provers/GuardianProver.sol"; import "../contracts/L2/DelegateOwner.sol"; -import "../contracts/team/TimelockTokenPool.sol"; import "../contracts/team/airdrop/ERC20Airdrop.sol"; import "../contracts/team/airdrop/ERC20Airdrop2.sol"; import "../contracts/team/airdrop/ERC721Airdrop.sol"; diff --git a/packages/protocol/test/automata-attestation/common/AttestationBase.t.sol b/packages/protocol/test/automata-attestation/common/AttestationBase.t.sol index ca0d470d31..4133197796 100644 --- a/packages/protocol/test/automata-attestation/common/AttestationBase.t.sol +++ b/packages/protocol/test/automata-attestation/common/AttestationBase.t.sol @@ -17,6 +17,8 @@ import { Base64 } from "solady/src/utils/Base64.sol"; import "../utils/DcapTestUtils.t.sol"; import "../utils/V3QuoteParseUtils.t.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + contract AttestationBase is Test, DcapTestUtils, V3QuoteParseUtils { using BytesUtils for bytes; using stdJson for string; @@ -50,7 +52,18 @@ contract AttestationBase is Test, DcapTestUtils, V3QuoteParseUtils { p256Verifier = new P256Verifier(); sigVerifyLib = new SigVerifyLib(address(p256Verifier)); pemCertChainLib = new PEMCertChainLib(); - attestation = new AutomataDcapV3Attestation(address(sigVerifyLib), address(pemCertChainLib)); + + address automateDcapV3AttestationImpl = address(new AutomataDcapV3Attestation()); + + attestation = AutomataDcapV3Attestation( + deployProxy({ + impl: automateDcapV3AttestationImpl, + data: abi.encodeCall( + AutomataDcapV3Attestation.init, + (admin, address(sigVerifyLib), address(pemCertChainLib)) + ) + }) + ); setMrEnclave(address(attestation), mrEnclave); setMrSigner(address(attestation), mrSigner); @@ -127,4 +140,8 @@ contract AttestationBase is Test, DcapTestUtils, V3QuoteParseUtils { uint256 sgxIdx = SgxVerifier(_sgxVerifier).registerInstance(v3quote); console.log("[log] register sgx instance index: %s", sgxIdx); } + + function deployProxy(address impl, bytes memory data) internal returns (address proxy) { + proxy = address(new ERC1967Proxy(impl, data)); + } } diff --git a/packages/protocol/test/team/TimelockTokenPool.t.sol b/packages/protocol/test/team/TimelockTokenPool.t.sol deleted file mode 100644 index 3f2febd275..0000000000 --- a/packages/protocol/test/team/TimelockTokenPool.t.sol +++ /dev/null @@ -1,550 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "../TaikoTest.sol"; - -contract MyERC20 is ERC20 { - constructor(address owner) ERC20("Taiko Token", "TKO") { - _mint(owner, 1_000_000_000e18); - } -} - -contract USDC is ERC20 { - constructor(address recipient) ERC20("USDC", "USDC") { - _mint(recipient, 1_000_000_000e6); - } - - function decimals() public view virtual override returns (uint8) { - return 6; - } -} - -contract TestTimelockTokenPool is TaikoTest { - address internal Vault = randAddress(); - - ERC20 tko = new MyERC20(Vault); - ERC20 usdc = new USDC(Alice); - - uint128 public constant ONE_TKO_UNIT = 1e18; - - // 0.01 USDC if decimals are 6 (as in our test) - uint64 strikePrice1 = uint64(10 ** usdc.decimals() / 100); - // 0.05 USDC if decimals are 6 (as in our test) - uint64 strikePrice2 = uint64(10 ** usdc.decimals() / 20); - - TimelockTokenPool pool; - - function setUp() public { - pool = TimelockTokenPool( - deployProxy({ - name: "time_lock_token_pool", - impl: address(new TimelockTokenPool()), - data: abi.encodeCall( - TimelockTokenPool.init, (address(0), address(tko), address(usdc), Vault) - ) - }) - ); - } - - function test_invalid_granting() public { - vm.expectRevert(TimelockTokenPool.INVALID_GRANT.selector); - pool.grant(Alice, TimelockTokenPool.Grant(0, 0, 0, 0, 0, 0, 0, 0)); - - vm.expectRevert(TimelockTokenPool.INVALID_PARAM.selector); - pool.grant(address(0), TimelockTokenPool.Grant(100e18, 0, 0, 0, 0, 0, 0, 0)); - } - - function test_single_grant_zero_grant_period_zero_unlock_period() public { - pool.grant(Alice, TimelockTokenPool.Grant(10_000e18, 0, 0, 0, 0, 0, 0, 0)); - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 10_000e18); - assertEq(costToWithdraw, 0); - - // Try to void the grant - vm.expectRevert(TimelockTokenPool.NOTHING_TO_VOID.selector); - pool.void(Alice); - - vm.prank(Alice); - pool.withdraw(); - assertEq(tko.balanceOf(Alice), 10_000e18); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 10_000e18); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - } - - function test_single_grant_zero_grant_period_1year_unlock_period() public { - uint64 unlockStart = uint64(block.timestamp); - uint32 unlockPeriod = 365 days; - uint64 unlockCliff = unlockStart + unlockPeriod / 2; - - pool.grant( - Alice, - TimelockTokenPool.Grant( - 10_000e18, strikePrice1, 0, 0, 0, unlockStart, unlockCliff, unlockPeriod - ) - ); - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - vm.prank(Alice); - usdc.approve(address(pool), 10_000e18 / ONE_TKO_UNIT * strikePrice1); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - vm.warp(unlockCliff); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - vm.warp(unlockCliff + 1); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - uint256 amount1 = uint128(10_000e18) * uint64(block.timestamp - unlockStart) / unlockPeriod; - uint256 expectedCost = amount1 / ONE_TKO_UNIT * strikePrice1; - - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, amount1); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, amount1); - assertEq(costToWithdraw, expectedCost); - - vm.prank(Alice); - pool.withdraw(); - - vm.warp(unlockStart + unlockPeriod + 365 days); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - expectedCost = amount1 / ONE_TKO_UNIT * strikePrice1; - - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, amount1); - assertEq(amountToWithdraw, 10_000e18 - amount1); - assertEq(costToWithdraw, expectedCost); - - vm.prank(Alice); - pool.withdraw(); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 10_000e18); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - } - - function test_single_grant_1year_grant_period_zero_unlock_period() public { - uint64 grantStart = uint64(block.timestamp); - uint32 grantPeriod = 365 days; - uint64 grantCliff = grantStart + grantPeriod / 2; - - pool.grant( - Alice, - TimelockTokenPool.Grant( - 10_000e18, strikePrice1, grantStart, grantCliff, grantPeriod, 0, 0, 0 - ) - ); - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - vm.prank(Alice); - usdc.approve(address(pool), 10_000e18 / ONE_TKO_UNIT * strikePrice1); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - vm.warp(grantCliff); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - vm.warp(grantCliff + 1); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - uint256 amount1 = uint128(10_000e18) * uint64(block.timestamp - grantStart) / grantPeriod; - uint256 expectedCost = amount1 / ONE_TKO_UNIT * strikePrice1; - console2.log("expectedCost", expectedCost); - console2.log("costToWithdraw", costToWithdraw); - assertEq(amountOwned, amount1); - assertEq(amountUnlocked, amount1); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, amount1); - assertEq(costToWithdraw, expectedCost); - console2.log("EZ feltt elvileg jo volt"); - - vm.prank(Alice); - pool.withdraw(); - - vm.warp(grantStart + grantPeriod + 365 days); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - expectedCost = amount1 / ONE_TKO_UNIT * strikePrice1; - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, amount1); - assertEq(amountToWithdraw, 10_000e18 - amount1); - assertEq(costToWithdraw, expectedCost); - - vm.prank(Alice); - pool.withdraw(); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 10_000e18); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - } - - function test_single_grant_4year_grant_period_4year_unlock_period() public { - uint64 grantStart = uint64(block.timestamp); - uint32 grantPeriod = 4 * 365 days; - uint64 grantCliff = grantStart + 90 days; - - uint64 unlockStart = grantStart + 365 days; - uint32 unlockPeriod = 4 * 365 days; - uint64 unlockCliff = unlockStart + 365 days; - - pool.grant( - Alice, - TimelockTokenPool.Grant( - 10_000e18, - strikePrice1, - grantStart, - grantCliff, - grantPeriod, - unlockStart, - unlockCliff, - unlockPeriod - ) - ); - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - vm.prank(Alice); - usdc.approve(address(pool), 10_000e18 / ONE_TKO_UNIT * strikePrice1); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - // 90 days later - vm.warp(grantStart + 90 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - // 1 year later - vm.warp(grantStart + 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 2500e18); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - // 2 year later - vm.warp(grantStart + 2 * 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 5000e18); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - // 3 year later - vm.warp(grantStart + 3 * 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - uint256 expectedCost = 3750e18 / ONE_TKO_UNIT * strikePrice1; - - assertEq(amountOwned, 7500e18); - assertEq(amountUnlocked, 3750e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 3750e18); - assertEq(costToWithdraw, expectedCost); - - // 4 year later - vm.warp(grantStart + 4 * 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - expectedCost = 7500e18 / ONE_TKO_UNIT * strikePrice1; - - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 7500e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 7500e18); - assertEq(costToWithdraw, expectedCost); - - // 5 year later - vm.warp(grantStart + 5 * 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - - expectedCost = 10_000e18 / ONE_TKO_UNIT * strikePrice1; - - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 10_000e18); - assertEq(costToWithdraw, expectedCost); - - // 6 year later - vm.warp(grantStart + 6 * 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 10_000e18); - assertEq(costToWithdraw, expectedCost); - } - - function test_void_grant_before_granted() public { - uint64 grantStart = uint64(block.timestamp) + 30 days; - pool.grant(Alice, TimelockTokenPool.Grant(10_000e18, 0, grantStart, 0, 0, 0, 0, 0)); - - vm.expectRevert(TimelockTokenPool.ALREADY_GRANTED.selector); - pool.grant(Alice, TimelockTokenPool.Grant(20_000e18, 0, grantStart, 0, 0, 0, 0, 0)); - - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - // Try to void the grant - pool.void(Alice); - - TimelockTokenPool.Grant memory grant = pool.getMyGrant(Alice); - - assertEq(grant.grantStart, 0); - assertEq(grant.grantPeriod, 0); - assertEq(grant.grantCliff, 0); - assertEq(grant.unlockStart, 0); - assertEq(grant.unlockPeriod, 0); - assertEq(grant.unlockCliff, 0); - assertEq(grant.amount, 0); - } - - function test_void_grant_after_granted() public { - uint64 grantStart = uint64(block.timestamp) + 30 days; - pool.grant(Alice, TimelockTokenPool.Grant(10_000e18, 0, grantStart, 0, 0, 0, 0, 0)); - - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - vm.warp(grantStart + 1); - - // Try to void the grant - vm.expectRevert(TimelockTokenPool.NOTHING_TO_VOID.selector); - pool.void(Alice); - } - - function test_void_grant_in_the_middle() public { - uint64 grantStart = uint64(block.timestamp); - uint32 grantPeriod = 100 days; - pool.grant( - Alice, - TimelockTokenPool.Grant(10_000e18, strikePrice1, grantStart, 0, grantPeriod, 0, 0, 0) - ); - - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - uint256 halfTimeWithdrawCost = 5000e18 / ONE_TKO_UNIT * strikePrice1; - - vm.warp(grantStart + 50 days); - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - - assertEq(amountOwned, 5000e18); - assertEq(amountUnlocked, 5000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 5000e18); - assertEq(costToWithdraw, halfTimeWithdrawCost); - - pool.void(Alice); - - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 5000e18); - assertEq(amountUnlocked, 5000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 5000e18); - assertEq(costToWithdraw, halfTimeWithdrawCost); - - vm.warp(grantStart + 100 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 5000e18); - assertEq(amountUnlocked, 5000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 5000e18); - assertEq(costToWithdraw, halfTimeWithdrawCost); - } - - function test_correct_strike_price() public { - uint64 grantStart = uint64(block.timestamp); - uint32 grantPeriod = 4 * 365 days; - uint64 grantCliff = grantStart + 90 days; - - uint64 unlockStart = grantStart + 365 days; - uint32 unlockPeriod = 4 * 365 days; - uint64 unlockCliff = unlockStart + 365 days; - - uint64 strikePrice = 10_000; // 0.01 USDC if decimals are 6 (as in our test) - - pool.grant( - Alice, - TimelockTokenPool.Grant( - 10_000e18, - strikePrice, - grantStart, - grantCliff, - grantPeriod, - unlockStart, - unlockCliff, - unlockPeriod - ) - ); - vm.prank(Vault); - tko.approve(address(pool), 10_000e18); - - ( - uint128 amountOwned, - uint128 amountUnlocked, - uint128 amountWithdrawn, - uint128 amountToWithdraw, - uint128 costToWithdraw - ) = pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 0); - assertEq(amountUnlocked, 0); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 0); - assertEq(costToWithdraw, 0); - - // When withdraw (5 years later) - check if correct price is deducted - vm.warp(grantStart + 5 * 365 days); - (amountOwned, amountUnlocked, amountWithdrawn, amountToWithdraw, costToWithdraw) = - pool.getMyGrantSummary(Alice); - assertEq(amountOwned, 10_000e18); - assertEq(amountUnlocked, 10_000e18); - assertEq(amountWithdrawn, 0); - assertEq(amountToWithdraw, 10_000e18); - - // 10_000 TKO tokens * strikePrice - uint256 paidUsdc = 10_000 * strikePrice; - - vm.prank(Alice); - usdc.approve(address(pool), paidUsdc); - - vm.prank(Alice); - pool.withdraw(); - assertEq(tko.balanceOf(Alice), 10_000e18); - assertEq(usdc.balanceOf(Alice), 1_000_000_000e6 - paidUsdc); - } -} diff --git a/packages/protocol/utils/generate_genesis/interface.ts b/packages/protocol/utils/generate_genesis/interface.ts index 34b7f337bf..e3a6c2aa9b 100644 --- a/packages/protocol/utils/generate_genesis/interface.ts +++ b/packages/protocol/utils/generate_genesis/interface.ts @@ -1,6 +1,5 @@ export interface Config { - ownerTimelockController: string; - ownerSecurityCouncil: string; + contractOwner: string; l1ChainId: number; chainId: number; seedAccounts: Array<{ diff --git a/packages/protocol/utils/generate_genesis/main.ts b/packages/protocol/utils/generate_genesis/main.ts index d50bd9d9f0..a792c95a1c 100644 --- a/packages/protocol/utils/generate_genesis/main.ts +++ b/packages/protocol/utils/generate_genesis/main.ts @@ -18,15 +18,13 @@ async function main() { : path.join(process.cwd(), process.argv[2]), ); - const ownerTimelockController = config.ownerTimelockController; - const ownerSecurityCouncil = config.ownerSecurityCouncil; + const contractOwner = config.contractOwner; const chainId = config.chainId; const seedAccounts = config.seedAccounts; const predeployERC20 = config.predeployERC20; if ( - !ethers.utils.isAddress(ownerTimelockController) || - !ethers.utils.isAddress(ownerSecurityCouncil) || + !ethers.utils.isAddress(contractOwner) || !Number.isInteger(chainId) || !Array.isArray(seedAccounts) || !seedAccounts.every((seedAccount) => { @@ -40,8 +38,7 @@ async function main() { ) { throw new Error( `invalid input: ${JSON.stringify({ - ownerTimelockController, - ownerSecurityCouncil, + contractOwner, chainId, seedAccounts, })}`, diff --git a/packages/protocol/utils/generate_genesis/taikoL2.ts b/packages/protocol/utils/generate_genesis/taikoL2.ts index c76864a69d..f9d02b79d5 100644 --- a/packages/protocol/utils/generate_genesis/taikoL2.ts +++ b/packages/protocol/utils/generate_genesis/taikoL2.ts @@ -14,13 +14,7 @@ export async function deployTaikoL2( config: Config, result: Result, ): Promise { - const { - ownerTimelockController, - ownerSecurityCouncil, - l1ChainId, - chainId, - seedAccounts, - } = config; + const { contractOwner, l1ChainId, chainId, seedAccounts } = config; const alloc: any = {}; @@ -45,8 +39,7 @@ export async function deployTaikoL2( console.log("\n"); const contractConfigs: any = await generateContractConfigs( - ownerTimelockController, - ownerSecurityCouncil, + contractOwner, l1ChainId, chainId, config.contractAddresses, @@ -117,8 +110,7 @@ export async function deployTaikoL2( // generateContractConfigs returns all L2 contracts address, deployedBytecode, // and initialized variables. async function generateContractConfigs( - ownerTimelockController: string, - ownerSecurityCouncil: string, + contractOwner: string, l1ChainId: number, chainId: number, hardCodedAddresses: any, @@ -205,7 +197,7 @@ async function generateContractConfigs( addressMap[contractName] = hardCodedAddresses[contractName]; } else { addressMap[contractName] = ethers.utils.getCreate2Address( - ownerSecurityCouncil, + contractOwner, ethers.utils.keccak256( ethers.utils.toUtf8Bytes(`${chainId}${contractName}`), ), @@ -230,7 +222,7 @@ async function generateContractConfigs( ), ).deployedBytecode.object, variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, SharedAddressManager: { @@ -245,7 +237,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // AddressManager __addresses: { [chainId]: { @@ -292,7 +284,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, Bridge: { @@ -306,7 +298,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // EssentialContract => AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -326,7 +318,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, ERC20Vault: { @@ -341,7 +333,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // EssentialContract => AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -361,7 +353,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, ERC721Vault: { @@ -376,7 +368,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // EssentialContract => AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -396,7 +388,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, ERC1155Vault: { @@ -411,7 +403,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // EssentialContract => AddressResolver addressManager: addressMap.SharedAddressManager, }, @@ -422,27 +414,36 @@ async function generateContractConfigs( }, BridgedERC20: { address: addressMap.BridgedERC20Impl, - deployedBytecode: linkContractLibs(replaceUUPSImmutableValues( - contractArtifacts.BridgedERC20Impl, - uupsImmutableReferencesMap, - ethers.utils.hexZeroPad(addressMap.BridgedERC20Impl, 32), - ), addressMap), + deployedBytecode: linkContractLibs( + replaceUUPSImmutableValues( + contractArtifacts.BridgedERC20Impl, + uupsImmutableReferencesMap, + ethers.utils.hexZeroPad(addressMap.BridgedERC20Impl, 32), + ), + addressMap, + ), }, BridgedERC721: { address: addressMap.BridgedERC721Impl, - deployedBytecode: linkContractLibs(replaceUUPSImmutableValues( - contractArtifacts.BridgedERC721Impl, - uupsImmutableReferencesMap, - ethers.utils.hexZeroPad(addressMap.BridgedERC721Impl, 32), - ), addressMap), + deployedBytecode: linkContractLibs( + replaceUUPSImmutableValues( + contractArtifacts.BridgedERC721Impl, + uupsImmutableReferencesMap, + ethers.utils.hexZeroPad(addressMap.BridgedERC721Impl, 32), + ), + addressMap, + ), }, BridgedERC1155: { address: addressMap.BridgedERC1155Impl, - deployedBytecode: linkContractLibs(replaceUUPSImmutableValues( - contractArtifacts.BridgedERC1155Impl, - uupsImmutableReferencesMap, - ethers.utils.hexZeroPad(addressMap.BridgedERC1155Impl, 32), - ), addressMap), + deployedBytecode: linkContractLibs( + replaceUUPSImmutableValues( + contractArtifacts.BridgedERC1155Impl, + uupsImmutableReferencesMap, + ethers.utils.hexZeroPad(addressMap.BridgedERC1155Impl, 32), + ), + addressMap, + ), }, SignalServiceImpl: { address: addressMap.SignalServiceImpl, @@ -455,7 +456,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, SignalService: { @@ -470,7 +471,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // EssentialContract => AddressResolver addressManager: addressMap.SharedAddressManager, isAuthorized: { @@ -494,7 +495,7 @@ async function generateContractConfigs( addressMap, ), variables: { - _owner: ownerTimelockController, + _owner: contractOwner, }, }, TaikoL2: { @@ -508,7 +509,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerTimelockController, + _owner: contractOwner, // EssentialContract => AddressResolver addressManager: addressMap.RollupAddressManager, // TaikoL2 => CrossChainOwned @@ -545,7 +546,7 @@ async function generateContractConfigs( ), ).deployedBytecode.object, variables: { - _owner: ownerSecurityCouncil, + _owner: contractOwner, }, }, RollupAddressManager: { @@ -560,7 +561,7 @@ async function generateContractConfigs( _initialized: 1, _initializing: false, // EssentialContract => Ownable2StepUpgradeable - _owner: ownerSecurityCouncil, + _owner: contractOwner, // AddressManager __addresses: { [chainId]: { @@ -584,7 +585,8 @@ async function generateContractConfigs( // Libraries LibNetwork: { address: addressMap.LibNetwork, - deployedBytecode: contractArtifacts.LibNetwork.deployedBytecode.object, + deployedBytecode: + contractArtifacts.LibNetwork.deployedBytecode.object, }, }; } diff --git a/packages/relayer/cmd/flags/processor.go b/packages/relayer/cmd/flags/processor.go index b55f9ca3a1..72ea928ac4 100644 --- a/packages/relayer/cmd/flags/processor.go +++ b/packages/relayer/cmd/flags/processor.go @@ -129,6 +129,13 @@ var ( Required: false, EnvVars: []string{"UNPROFITABLE_MESSAGE_QUEUE_EXPIRATION"}, } + MaxMessageRetries = &cli.Uint64Flag{ + Name: "maxMessageRetries", + Usage: "How many times to retry a message due to unprofitability", + Category: processorCategory, + Value: 5, + EnvVars: []string{"MAX_MESSAGE_RETRIES"}, + } ) var ProcessorFlags = MergeFlags(CommonFlags, QueueFlags, TxmgrFlags, []cli.Flag{ @@ -151,4 +158,5 @@ var ProcessorFlags = MergeFlags(CommonFlags, QueueFlags, TxmgrFlags, []cli.Flag{ TargetTxHash, CacheOption, UnprofitableMessageQueueExpiration, + MaxMessageRetries, }) diff --git a/packages/relayer/indexer/handle_message_processed_event.go b/packages/relayer/indexer/handle_message_processed_event.go index 453ab7e837..dd232374dc 100644 --- a/packages/relayer/indexer/handle_message_processed_event.go +++ b/packages/relayer/indexer/handle_message_processed_event.go @@ -98,7 +98,7 @@ func (i *Indexer) handleMessageProcessedEvent( // we add it to the queue, so the processor can pick up and attempt to process // the message onchain. - if err := i.queue.Publish(ctx, i.queueName(), marshalledMsg, nil); err != nil { + if err := i.queue.Publish(ctx, i.queueName(), marshalledMsg, nil, nil); err != nil { return errors.Wrap(err, "i.queue.Publish") } diff --git a/packages/relayer/indexer/handle_message_sent_event.go b/packages/relayer/indexer/handle_message_sent_event.go index 8ced106e5e..d7d541baf8 100644 --- a/packages/relayer/indexer/handle_message_sent_event.go +++ b/packages/relayer/indexer/handle_message_sent_event.go @@ -113,7 +113,7 @@ func (i *Indexer) handleMessageSentEvent( // we add it to the queue, so the processor can pick up and attempt to process // the message onchain. - if err := i.queue.Publish(ctx, i.queueName(), marshalledMsg, nil); err != nil { + if err := i.queue.Publish(ctx, i.queueName(), marshalledMsg, nil, nil); err != nil { return errors.Wrap(err, "i.queue.Publish") } diff --git a/packages/relayer/pkg/mock/queue.go b/packages/relayer/pkg/mock/queue.go index fccaa521f8..bd23bca632 100644 --- a/packages/relayer/pkg/mock/queue.go +++ b/packages/relayer/pkg/mock/queue.go @@ -22,7 +22,13 @@ func (r *Queue) Notify(ctx context.Context, wg *sync.WaitGroup) error { return nil } -func (r *Queue) Publish(ctx context.Context, queueName string, msg []byte, expiration *string) error { +func (r *Queue) Publish( + ctx context.Context, + queueName string, + msg []byte, + headers map[string]interface{}, + expiration *string, +) error { return nil } diff --git a/packages/relayer/pkg/queue/queue.go b/packages/relayer/pkg/queue/queue.go index 85a15cbe07..9a436de3e0 100644 --- a/packages/relayer/pkg/queue/queue.go +++ b/packages/relayer/pkg/queue/queue.go @@ -15,7 +15,13 @@ var ( type Queue interface { Start(ctx context.Context, queueName string) error Close(ctx context.Context) - Publish(ctx context.Context, queueName string, msg []byte, expiration *string) error + Publish( + ctx context.Context, + queueName string, + msg []byte, + headers map[string]interface{}, + expiration *string, + ) error Notify(ctx context.Context, wg *sync.WaitGroup) error Subscribe(ctx context.Context, msgs chan<- Message, wg *sync.WaitGroup) error Ack(ctx context.Context, msg Message) error @@ -23,8 +29,9 @@ type Queue interface { } type QueueMessageSentBody struct { - Event *bridge.BridgeMessageSent - ID int + Event *bridge.BridgeMessageSent + ID int + TimesRetried uint64 } type QueueMessageProcessedBody struct { @@ -33,9 +40,8 @@ type QueueMessageProcessedBody struct { } type Message struct { - Body []byte - Internal interface{} - TimesRetried int64 + Body []byte + Internal interface{} } type NewQueueOpts struct { diff --git a/packages/relayer/pkg/queue/rabbitmq/queue.go b/packages/relayer/pkg/queue/rabbitmq/queue.go index 1e5814a55a..37cd868007 100644 --- a/packages/relayer/pkg/queue/rabbitmq/queue.go +++ b/packages/relayer/pkg/queue/rabbitmq/queue.go @@ -242,7 +242,13 @@ func (r *RabbitMQ) Close(ctx context.Context) { slog.Info("closed rabbitmq connection") } -func (r *RabbitMQ) Publish(ctx context.Context, queueName string, msg []byte, expiration *string) error { +func (r *RabbitMQ) Publish( + ctx context.Context, + queueName string, + msg []byte, + headers map[string]interface{}, + expiration *string, +) error { slog.Info("publishing rabbitmq msg to queue", "queue", r.queue.Name) p := amqp.Publishing{ @@ -250,6 +256,7 @@ func (r *RabbitMQ) Publish(ctx context.Context, queueName string, msg []byte, ex Body: msg, MessageId: uuid.New().String(), DeliveryMode: 2, // persistent messages, saved to disk to survive server restart + Headers: headers, } if expiration != nil { @@ -274,7 +281,7 @@ func (r *RabbitMQ) Publish(ctx context.Context, queueName string, msg []byte, ex return err } - return r.Publish(ctx, queueName, msg, expiration) + return r.Publish(ctx, queueName, msg, headers, expiration) } else { return err } @@ -372,7 +379,7 @@ func (r *RabbitMQ) Notify(ctx context.Context, wg *sync.WaitGroup) error { slog.Error("rabbitmq notify return", "id", returnMsg.MessageId, "err", returnMsg.ReplyText) slog.Info("rabbitmq attempting republish of returned msg", "id", returnMsg.MessageId) - if err := r.Publish(ctx, r.queue.Name, returnMsg.Body, &returnMsg.Expiration); err != nil { + if err := r.Publish(ctx, r.queue.Name, returnMsg.Body, returnMsg.Headers, &returnMsg.Expiration); err != nil { slog.Error("error publishing msg", "err", err.Error()) } } @@ -455,45 +462,9 @@ func (r *RabbitMQ) Subscribe(ctx context.Context, msgChan chan<- queue.Message, if d.Body != nil { slog.Info("rabbitmq message found", "msgId", d.MessageId) - - var timesRetried int64 = 0 - - var maxRetries int64 = 3 - - xDeath, exists := d.Headers["x-death"].([]interface{}) - - if exists { - // message was rejected before - c := xDeath[0].(amqp.Table)["count"].(int64) - - timesRetried = c - - if timesRetried > 0 { - relayer.MessageSentEventsRetries.Inc() - } - } - - if timesRetried > 0 { - slog.Info("rabbitmq message times retried", - "msgId", d.MessageId, - "timesRetried", timesRetried, - ) - } - - if timesRetried >= int64(maxRetries) { - slog.Info("msg has reached max retries", "id", d.MessageId) - - relayer.MessageSentEventsMaxRetriesReached.Inc() - - if err := d.Ack(false); err != nil { - slog.Error("error acking msg after max retries") - } - } else { - msgChan <- queue.Message{ - Body: d.Body, - Internal: d, - TimesRetried: timesRetried, - } + msgChan <- queue.Message{ + Body: d.Body, + Internal: d, } } else { slog.Info("nil body message, queue is closed") diff --git a/packages/relayer/processor/config.go b/packages/relayer/processor/config.go index 8ca912c36a..ab116091f4 100644 --- a/packages/relayer/processor/config.go +++ b/packages/relayer/processor/config.go @@ -83,6 +83,8 @@ type Config struct { UnprofitableMessageQueueExpiration *string TxmgrConfigs *txmgr.CLIConfig + + MaxMessageRetries uint64 } // NewConfigFromCliContext creates a new config instance from command line flags. @@ -166,6 +168,7 @@ func NewConfigFromCliContext(c *cli.Context) (*Config, error) { processorPrivateKey, c, ), + MaxMessageRetries: c.Uint64(flags.MaxMessageRetries.Name), OpenDBFunc: func() (DB, error) { return db.OpenDBConnection(db.DBConnectionOpts{ Name: c.String(flags.DatabaseUsername.Name), diff --git a/packages/relayer/processor/process_message.go b/packages/relayer/processor/process_message.go index 832b965d0f..2288470abb 100644 --- a/packages/relayer/processor/process_message.go +++ b/packages/relayer/processor/process_message.go @@ -60,17 +60,23 @@ func (p *Processor) eventStatusFromMsgHash( func (p *Processor) processMessage( ctx context.Context, msg queue.Message, -) (bool, error) { +) (bool, uint64, error) { msgBody := &queue.QueueMessageSentBody{} if err := json.Unmarshal(msg.Body, msgBody); err != nil { - return false, errors.Wrap(err, "json.Unmarshal") + return false, 0, errors.Wrap(err, "json.Unmarshal") } slog.Info("message received", "srcTxHash", msgBody.Event.Raw.TxHash.Hex()) + if msgBody.TimesRetried >= p.maxMessageRetries { + slog.Warn("max retries reached", "timesRetried", msgBody.TimesRetried) + + return false, msgBody.TimesRetried, nil + } + eventStatus, err := p.eventStatusFromMsgHash(ctx, msgBody.Event.MsgHash) if err != nil { - return false, errors.Wrap(err, "p.eventStatusFromMsgHash") + return false, msgBody.TimesRetried, errors.Wrap(err, "p.eventStatusFromMsgHash") } if !canProcessMessage( @@ -80,32 +86,32 @@ func (p *Processor) processMessage( p.relayerAddr, uint64(msgBody.Event.Message.GasLimit), ) { - return false, nil + return false, msgBody.TimesRetried, nil } if err := p.waitForConfirmations(ctx, msgBody.Event.Raw.TxHash, msgBody.Event.Raw.BlockNumber); err != nil { - return false, err + return false, msgBody.TimesRetried, err } encodedSignalProof, err := p.generateEncodedSignalProof(ctx, msgBody.Event) if err != nil { - return false, err + return false, msgBody.TimesRetried, err } receipt, err := p.sendProcessMessageCall(ctx, msgBody.Event, encodedSignalProof) if err != nil { - return false, err + return false, msgBody.TimesRetried, err } if receipt.Status != types.ReceiptStatusSuccessful { - return false, err + return false, msgBody.TimesRetried, err } messageStatus, err := p.destBridge.MessageStatus(&bind.CallOpts{ Context: ctx, }, msgBody.Event.MsgHash) if err != nil { - return false, errors.Wrap(err, "p.destBridge.GetMessageStatus") + return false, msgBody.TimesRetried, errors.Wrap(err, "p.destBridge.GetMessageStatus") } slog.Info( @@ -125,11 +131,11 @@ func (p *Processor) processMessage( if msg.Internal != nil { // update message status if err := p.eventRepo.UpdateStatus(ctx, msgBody.ID, relayer.EventStatus(messageStatus)); err != nil { - return false, err + return false, msgBody.TimesRetried, err } } - return false, nil + return false, msgBody.TimesRetried, nil } // generateEncodedSignalproof takes a MessageSent event and calls a diff --git a/packages/relayer/processor/process_message_test.go b/packages/relayer/processor/process_message_test.go index e00b414581..2b6c02eb21 100644 --- a/packages/relayer/processor/process_message_test.go +++ b/packages/relayer/processor/process_message_test.go @@ -73,7 +73,7 @@ func Test_ProcessMessage_messageUnprocessable(t *testing.T) { Body: marshalled, } - shouldRequeue, err := p.processMessage(context.Background(), msg) + shouldRequeue, _, err := p.processMessage(context.Background(), msg) assert.Nil(t, err) @@ -117,7 +117,7 @@ func Test_ProcessMessage_unprofitable(t *testing.T) { Body: marshalled, } - shouldRequeue, err := p.processMessage(context.Background(), msg) + shouldRequeue, _, err := p.processMessage(context.Background(), msg) assert.Equal( t, diff --git a/packages/relayer/processor/process_single.go b/packages/relayer/processor/process_single.go index 2e130d0f6e..07e9ed7189 100644 --- a/packages/relayer/processor/process_single.go +++ b/packages/relayer/processor/process_single.go @@ -47,7 +47,7 @@ func (p *Processor) processSingle(ctx context.Context) error { return err } - if _, err := p.processMessage(ctx, queue.Message{ + if _, _, err := p.processMessage(ctx, queue.Message{ Body: marshalledMsg, }); err != nil { return err diff --git a/packages/relayer/processor/processor.go b/packages/relayer/processor/processor.go index 40cae8d531..117cc6116a 100644 --- a/packages/relayer/processor/processor.go +++ b/packages/relayer/processor/processor.go @@ -128,6 +128,8 @@ type Processor struct { cfg *Config txmgr txmgr.TxManager + + maxMessageRetries uint64 } // InitFromCli creates a new processor from a cli context @@ -349,6 +351,8 @@ func InitFromConfig(ctx context.Context, p *Processor, cfg *Config) error { p.targetTxHash = cfg.TargetTxHash + p.maxMessageRetries = cfg.MaxMessageRetries + return nil } @@ -432,7 +436,7 @@ func (p *Processor) eventLoop(ctx context.Context) { return case msg := <-p.msgCh: go func(m queue.Message) { - shouldRequeue, err := p.processMessage(ctx, m) + shouldRequeue, timesRetried, err := p.processMessage(ctx, m) if err != nil { switch { @@ -443,10 +447,15 @@ func (p *Processor) eventLoop(ctx context.Context) { case errors.Is(err, relayer.ErrUnprofitable): slog.Info("publishing to unprofitable queue") + headers := make(map[string]interface{}, 0) + + headers["retries"] = timesRetried + 1 + if err := p.queue.Publish( ctx, fmt.Sprintf("%v-unprofitable", p.queueName()), m.Body, + headers, p.cfg.UnprofitableMessageQueueExpiration, ); err != nil { slog.Error("error publishing to unprofitable queue", "error", err) diff --git a/packages/relayer/processor/processor_test.go b/packages/relayer/processor/processor_test.go index b458a56e9d..4fc61cdc40 100644 --- a/packages/relayer/processor/processor_test.go +++ b/packages/relayer/processor/processor_test.go @@ -46,5 +46,6 @@ func newTestProcessor(profitableOnly bool) *Processor { cfg: &Config{ DestBridgeAddress: common.HexToAddress("0xC4279588B8dA563D264e286E2ee7CE8c244444d6"), }, + maxMessageRetries: 5, } } diff --git a/packages/supplementary-contracts/contracts/TokenUnlocking.sol b/packages/supplementary-contracts/contracts/tokenUnlocking/TokenUnlocking.sol similarity index 100% rename from packages/supplementary-contracts/contracts/TokenUnlocking.sol rename to packages/supplementary-contracts/contracts/tokenUnlocking/TokenUnlocking.sol diff --git a/packages/supplementary-contracts/foundry.toml b/packages/supplementary-contracts/foundry.toml index fdbe124480..46da7f75b7 100644 --- a/packages/supplementary-contracts/foundry.toml +++ b/packages/supplementary-contracts/foundry.toml @@ -28,6 +28,7 @@ block_gas_limit = 80_000_000 fs_permissions = [ { access = "read", path = "./out" }, { access = "read-write", path = "./deployments" }, + { access = "read", path = "./script" }, { access = "read", path = "./test" }, { access = "read", path = "./genesis" }, ] diff --git a/packages/supplementary-contracts/package.json b/packages/supplementary-contracts/package.json index d158e97279..c1343a79d6 100644 --- a/packages/supplementary-contracts/package.json +++ b/packages/supplementary-contracts/package.json @@ -22,7 +22,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-promise": "^6.1.1", "ethers": "^5.7.2", - "solc": "0.7.3", + "solc": "0.8.24", "solhint": "^4.5.4", "ts-node": "^10.9.2", "typescript": "^5.2.2" diff --git a/packages/supplementary-contracts/script/DeployTokenUnlocking.s.sol b/packages/supplementary-contracts/script/DeployTokenUnlocking.s.sol deleted file mode 100644 index 90287bae61..0000000000 --- a/packages/supplementary-contracts/script/DeployTokenUnlocking.s.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.8.24; - -import "forge-std/src/Script.sol"; -import "forge-std/src/console2.sol"; - -import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; - -import "../contracts/TokenUnlocking.sol"; - -contract DeployTokenUnlocking is Script { - address public OWNER = vm.envAddress("OWNER"); - address public TAIKO_TOKEN = vm.envAddress("TAIKO_TOKEN"); - address public RECIPIENT = vm.envAddress("RECIPIENT"); - uint256 public TGE = vm.envUint("TGE_TIMESTAMP"); - - address tokenUnlocking; - - function setUp() public { } - - function run() external { - vm.startBroadcast(); - tokenUnlocking = deployProxy({ - impl: address(new TokenUnlocking()), - data: abi.encodeCall(TokenUnlocking.init, (OWNER, TAIKO_TOKEN, RECIPIENT, uint64(TGE))) - }); - vm.stopBroadcast(); - } - - function deployProxy(address impl, bytes memory data) public returns (address proxy) { - proxy = address(new ERC1967Proxy(impl, data)); - - console2.log(" proxy :", proxy); - console2.log(" impl :", impl); - } -} diff --git a/packages/supplementary-contracts/script/tokenVesting/Vest.data.json b/packages/supplementary-contracts/script/tokenVesting/Vest.data.json new file mode 100644 index 0000000000..4152673abb --- /dev/null +++ b/packages/supplementary-contracts/script/tokenVesting/Vest.data.json @@ -0,0 +1,20 @@ +[ + { + "name": "Alice", + "recipient": "0xa48dEBc18D5e63F1FB94DD513f643e412684f8a4", + "proxy": "0x33A270541f383A4A48dB6C5f1f00A161b8F79e2a", + "vestAmount": 35000 + }, + { + "name": "Bob", + "recipient": "0xa48dEBc18D5e63F1FB94DD513f643e412684f8a4", + "proxy": "0x33A270541f383A4A48dB6C5f1f00A161b8F79e2a", + "vestAmount": 25000 + }, + { + "name": "Carol", + "recipient": "0xa48dEBc18D5e63F1FB94DD513f643e412684f8a4", + "proxy": "0x33A270541f383A4A48dB6C5f1f00A161b8F79e2a", + "vestAmount": 15000 + } +] diff --git a/packages/supplementary-contracts/script/tokenVesting/Vest.s.sol b/packages/supplementary-contracts/script/tokenVesting/Vest.s.sol new file mode 100644 index 0000000000..59602306db --- /dev/null +++ b/packages/supplementary-contracts/script/tokenVesting/Vest.s.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import "forge-std/src/Script.sol"; +import "forge-std/src/console2.sol"; + +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +import "../../contracts/tokenUnlocking/TokenUnlocking.sol"; + +contract VestTokenUnlocking is Script { + using stdJson for string; + + struct VestingItem { + bytes32 name; // Conversion from json "string" to bytes32 will take place in foundry, + // cannot use string here, as json parser cannot interpret string from json, everything + // is bytes-chunks. It is more of informational to script executor anyways. + address recipient; + address proxy; + uint256 vestAmount; + } + + ERC20 private tko = ERC20(vm.envAddress("TAIKO_TOKEN")); + + function run() external { + vm.startBroadcast(); + + string memory path = "/script/tokenVesting/Vest.data.json"; + VestingItem[] memory items = abi.decode( + vm.parseJson(vm.readFile(string.concat(vm.projectRoot(), path))), (VestingItem[]) + ); + + for (uint256 i; i < items.length; i++) { + address proxy = items[i].proxy; + console2.logBytes32(items[i].name); + console2.log("Grantee unlocking contract address:", proxy); + console2.log("Vest amount (TKO):", items[i].vestAmount); + + require(TokenUnlocking(proxy).owner() == msg.sender, "msg.sender not owner"); + require( + TokenUnlocking(proxy).recipient() == items[i].recipient, "inconsistent recipient" + ); + + uint128 vestAmount = uint128(items[i].vestAmount * 1e18); + require(tko.balanceOf(msg.sender) >= vestAmount, "insufficient TKO balance"); + + tko.approve(proxy, vestAmount); + TokenUnlocking(proxy).vest(vestAmount); + + console2.log("Vested!\n"); + } + + vm.stopBroadcast(); + } +} diff --git a/packages/supplementary-contracts/script/tokenunlocking/Deploy.data.json b/packages/supplementary-contracts/script/tokenunlocking/Deploy.data.json new file mode 100644 index 0000000000..a2203365ee --- /dev/null +++ b/packages/supplementary-contracts/script/tokenunlocking/Deploy.data.json @@ -0,0 +1,5 @@ +[ + "0xa48dEBc18D5e63F1FB94DD513f643e412684f8a4", + "0x33A270541f383A4A48dB6C5f1f00A161b8F79e2a", + "0x5486893fE4b289e3395E382fDdF203238cBa857e" +] diff --git a/packages/supplementary-contracts/script/tokenunlocking/Deploy.s.sol b/packages/supplementary-contracts/script/tokenunlocking/Deploy.s.sol new file mode 100644 index 0000000000..c06b7e4063 --- /dev/null +++ b/packages/supplementary-contracts/script/tokenunlocking/Deploy.s.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.24; + +import "forge-std/src/Script.sol"; +import "forge-std/src/console2.sol"; + +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +import "../../contracts/tokenUnlocking/TokenUnlocking.sol"; + +contract DeployTokenUnlocking is Script { + using stdJson for string; + + uint256 public PRIVATE_KEY = vm.envUint("PRIVATE_KEY"); // deployer + address public OWNER = vm.envAddress("OWNER"); + address public TAIKO_TOKEN = vm.envAddress("TAIKO_TOKEN"); + uint256 public TGE = vm.envUint("TGE_TIMESTAMP"); + address public IMPL = vm.envAddress("TOKEN_VESTING_IMPL"); + + function setUp() public { } + + function run() external { + address impl = IMPL == address(0) ? address(new TokenUnlocking()) : IMPL; + + string memory path = "/script/tokenUnlocking/Deploy.data.json"; + address[] memory recipients = abi.decode( + vm.parseJson(vm.readFile(string.concat(vm.projectRoot(), path))), (address[]) + ); + + for (uint256 i; i < recipients.length; i++) { + console2.log("Grantee:", recipients[i]); + + vm.startBroadcast(PRIVATE_KEY); + deployProxy({ + impl: impl, + data: abi.encodeCall( + TokenUnlocking.init, (OWNER, TAIKO_TOKEN, recipients[i], uint64(TGE)) + ) + }); + vm.stopBroadcast(); + console2.log("Deployed!\n"); + } + } + + function deployProxy(address impl, bytes memory data) public returns (address proxy) { + proxy = address(new ERC1967Proxy(impl, data)); + console2.log(" proxy :", proxy); + console2.log(" impl :", impl); + } +} diff --git a/packages/supplementary-contracts/test/TokenUnlocking.t.sol b/packages/supplementary-contracts/test/tokenUnlocking/TokenUnlocking.t.sol similarity index 99% rename from packages/supplementary-contracts/test/TokenUnlocking.t.sol rename to packages/supplementary-contracts/test/tokenUnlocking/TokenUnlocking.t.sol index 8860e927a6..a6df2aa45f 100644 --- a/packages/supplementary-contracts/test/TokenUnlocking.t.sol +++ b/packages/supplementary-contracts/test/tokenUnlocking/TokenUnlocking.t.sol @@ -7,7 +7,7 @@ import "forge-std/src/console2.sol"; import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Votes.sol"; -import "../contracts/TokenUnlocking.sol"; +import "../../contracts/tokenUnlocking/TokenUnlocking.sol"; contract MyERC20 is ERC20, ERC20Votes { constructor(address owner) ERC20("Taiko Token", "TKO") ERC20Permit("Taiko Token") { diff --git a/packages/taikoon-ui/.env.example b/packages/taikoon-ui/.env.example new file mode 100644 index 0000000000..a9f2216670 --- /dev/null +++ b/packages/taikoon-ui/.env.example @@ -0,0 +1,2 @@ +PUBLIC_WALLETCONNECT_PROJECT_ID= +PUBLIC_IPFS_GATEWAY= diff --git a/packages/taikoon-ui/.eslintignore b/packages/taikoon-ui/.eslintignore new file mode 100644 index 0000000000..c26e640c61 --- /dev/null +++ b/packages/taikoon-ui/.eslintignore @@ -0,0 +1,20 @@ +.DS_Store +node_modules +coverage +/build +/.svelte-kit +/package +.env +.env.* +!.env.example + +# Generated files +/src/abi/* +CHANGELOG.md + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock + +src/generated/* diff --git a/packages/taikoon-ui/.eslintrc.cjs b/packages/taikoon-ui/.eslintrc.cjs new file mode 100644 index 0000000000..a0d9e11c97 --- /dev/null +++ b/packages/taikoon-ui/.eslintrc.cjs @@ -0,0 +1,49 @@ +module.exports = { + root: true, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:svelte/recommended', + 'prettier', + ], + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'simple-import-sort'], + rules: { + 'linebreak-style': ['error', 'unix'], + 'simple-import-sort/imports': 'error', + 'simple-import-sort/exports': 'error', + 'no-console': ['error', { allow: ['warn', 'error'] }], + 'no-irregular-whitespace': 'off' + }, + parserOptions: { + sourceType: 'module', + ecmaVersion: 2020, + extraFileExtensions: ['.svelte'], + }, + env: { + browser: true, + es2017: true, + node: true, + }, + overrides: [ + { + files: ['*.svelte'], + parser: 'svelte-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + }, + }, + { + files: ['*.ts', '*.svelte'], + rules: { + // TS will take care of this potential error. For more information please visit: + // https://typescript-eslint.io/linting/troubleshooting/#i-get-errors-from-the-no-undef-rule-about-global-variables-not-being-defined-even-though-there-are-no-typescript-errors + 'no-undef': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-explicit-any': 'off', + + + }, + }, + ], +} diff --git a/packages/taikoon-ui/.gitignore b/packages/taikoon-ui/.gitignore new file mode 100644 index 0000000000..6635cf5542 --- /dev/null +++ b/packages/taikoon-ui/.gitignore @@ -0,0 +1,10 @@ +.DS_Store +node_modules +/build +/.svelte-kit +/package +.env +.env.* +!.env.example +vite.config.js.timestamp-* +vite.config.ts.timestamp-* diff --git a/packages/taikoon-ui/.prettierignore b/packages/taikoon-ui/.prettierignore new file mode 100644 index 0000000000..cc41cea9b2 --- /dev/null +++ b/packages/taikoon-ui/.prettierignore @@ -0,0 +1,4 @@ +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/packages/taikoon-ui/.prettierrc b/packages/taikoon-ui/.prettierrc new file mode 100644 index 0000000000..68829af182 --- /dev/null +++ b/packages/taikoon-ui/.prettierrc @@ -0,0 +1,18 @@ +{ + "semi": true, + "tabWidth": 2, + "useTabs": false, + "printWidth": 120, + "singleQuote": true, + "trailingComma": "all", + "bracketSameLine": true, + "plugins": ["prettier-plugin-svelte"], + "overrides": [ + { + "files": "*.svelte", + "options": { + "parser": "svelte" + } + } + ] + } diff --git a/packages/taikoon-ui/README.md b/packages/taikoon-ui/README.md new file mode 100644 index 0000000000..64812e0dfe --- /dev/null +++ b/packages/taikoon-ui/README.md @@ -0,0 +1,58 @@ +# Frontend + +## Install + +```bash +npm install +``` + +## Run + +Start the development server: + +```bash +npm start +``` + +## Storybook + +Tool to develop UI components in isolation. Run the following command to start the storybook server: + +```bash +npm run storybook +``` + +--- + +## Status Tracker + +### Pages + +| Page | Status | Notes | +| ------------- | ------ | ----- | +| Countdown | | | +| Landing | | | +| Mint | | | +| Auction | | | +| Explore | | | +| Your Taikoons | | | + +### Components + +| Component | Status | Notes | +| -------------- | --------------------- | ----- | +| Header | | | +| Countdown | | | +| NFT Renderer | | | +| Background | | | +| Landing Header | Design Ready | | +| Landing Text | Design Ready | | +| Landing FAQ | Design Ready | | +| Landing Links | Design Ready | | +| Footer | Design Ready | | +| Mint Form | Design Ready | | +| Auction Form | Design Ready | | +| Card | In Storybook | | +| Button | In Storybook | | +| Text Input | Implemented on Weblab | | +| Spinner | In Storybook | diff --git a/packages/taikoon-ui/package.json b/packages/taikoon-ui/package.json new file mode 100644 index 0000000000..9931954424 --- /dev/null +++ b/packages/taikoon-ui/package.json @@ -0,0 +1,72 @@ +{ + "name": "taikoon-ui", + "version": "0.0.1", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview", + "test": "npm run test:integration && npm run test:unit", + "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", + "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", + "lint": "prettier --check ./src && eslint ./src --fix", + "format": "prettier --write ./src", + "test:integration": "playwright test", + "test:unit": "vitest", + "start": "npm run generate:abi && vite dev --open", + "generate:abi": "cd ../taikoon && pnpm compile && cd - && wagmi generate" + }, + "devDependencies": { + "@chromatic-com/storybook": "^1.3.1", + "@playwright/test": "^1.28.1", + "@sveltejs/adapter-auto": "^3.0.0", + "@sveltejs/kit": "^2.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0", + "@types/eslint": "^8.56.0", + "@types/node": "^20.12.7", + "@typescript-eslint/eslint-plugin": "^7.0.0", + "@typescript-eslint/parser": "^7.0.0", + "convert-csv-to-json": "^2.44.0", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-simple-import-sort": "^12.0.0", + "eslint-plugin-storybook": "^0.8.0", + "eslint-plugin-svelte": "^2.38.0", + "p-map": "^7.0.2", + "prettier": "^3.1.1", + "prettier-plugin-svelte": "^3.1.2", + "raw-body": "^2.5.2", + "svelte": "^4.2.7", + "svelte-check": "^3.6.0", + "svelte-copy": "^1.4.2", + "svelte-i18n": "^4.0.0", + "svelte-scrolling": "^1.4.0", + "tailwindcss-image-rendering": "^1.0.2", + "tslib": "^2.4.1", + "typescript": "^5.0.0", + "vite": "^5.0.3", + "vite-tsconfig-paths": "^4.3.2", + "vitest": "^1.2.0", + "which": "^4.0.0" + }, + "type": "module", + "dependencies": { + "@openzeppelin/merkle-tree": "^1.0.6", + "@wagmi/cli": "^2.1.4", + "@wagmi/connectors": "^4.1.18", + "@wagmi/core": "^2.8.0", + "@web3modal/common": "^4.1.1", + "@web3modal/ui": "^4.1.1", + "@web3modal/wagmi": "^4.1.1", + "@zerodevx/svelte-toast": "^0.9.5", + "autoprefixer": "^10.4.19", + "daisyui": "^4.10.1", + "dayjs": "^1.11.10", + "debug": "^4.3.4", + "minidenticons": "^4.2.1", + "postcss": "^8.4.38", + "svelte-countdown": "^1.1.2", + "tailwindcss": "^3.4.3", + "viem": "^2.9.26" + } +} diff --git a/packages/taikoon-ui/playwright.config.ts b/packages/taikoon-ui/playwright.config.ts new file mode 100644 index 0000000000..e946ece9d7 --- /dev/null +++ b/packages/taikoon-ui/playwright.config.ts @@ -0,0 +1,12 @@ +import type { PlaywrightTestConfig } from '@playwright/test' + +const config: PlaywrightTestConfig = { + webServer: { + command: 'npm run build && npm run preview', + port: 4173, + }, + testDir: 'tests', + testMatch: /(.+\.)?(test|spec)\.[jt]s/, +} + +export default config diff --git a/packages/taikoon-ui/postcss.config.js b/packages/taikoon-ui/postcss.config.js new file mode 100644 index 0000000000..d41ad63557 --- /dev/null +++ b/packages/taikoon-ui/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/packages/taikoon-ui/src/app.config.ts b/packages/taikoon-ui/src/app.config.ts new file mode 100644 index 0000000000..8d73e529a2 --- /dev/null +++ b/packages/taikoon-ui/src/app.config.ts @@ -0,0 +1,62 @@ +export const recommendedProcessingFee = { + ethGasLimit: BigInt(900_000), + erc20NotDeployedGasLimit: BigInt(3_100_000), + erc20DeployedGasLimit: BigInt(1_100_000), + erc721NotDeployedGasLimit: BigInt(2_400_000), + erc721DeployedGasLimit: BigInt(1_100_000), + erc1155NotDeployedGasLimit: BigInt(2_600_000), + erc1155DeployedGasLimit: BigInt(1_100_000), +}; + +export const processingFeeComponent = { + closingDelayOptionClick: 300, + intervalComputeRecommendedFee: 20_000, +}; + +export const bridgeService = { + noOwnerGasLimit: BigInt(140_000), + noERC20TokenDeployedGasLimit: BigInt(3_000_000), + erc20GasLimitThreshold: BigInt(2_500_000), + + noERC721TokenDeployedGasLimit: BigInt(2_400_000), + erc721GasLimitThreshold: BigInt(3_000_000), + + noERC1155TokenDeployedGasLimit: BigInt(2_600_000), + erc1155GasLimitThreshold: BigInt(3_000_000), +}; + +export const pendingTransaction = { + waitTimeout: 300_000, +}; + +export const storageService = { + bridgeTxPrefix: 'transactions', + customTokenPrefix: 'custom-tokens', +}; + +export const bridgeTransactionPoller = { + interval: 20_000, +}; + +export const statusComponent = { + minimumEthToClaim: 0.0001, +}; + +export const transactionConfig = { + pageSizeDesktop: 6, + pageSizeMobile: 5, + blurTransitionTime: 300, +}; + +export const toastConfig = { + duration: 5000, +}; + +export const apiService = { + timeout: 5000, +}; + +export const ipfsConfig = { + gatewayTimeout: 200, + overallTimeout: 5000, +}; diff --git a/packages/taikoon-ui/src/app.css b/packages/taikoon-ui/src/app.css new file mode 100644 index 0000000000..bcc3a681dd --- /dev/null +++ b/packages/taikoon-ui/src/app.css @@ -0,0 +1,104 @@ +@import './styles/base.css'; +@import './styles/components.css'; +@import './styles/utilities.css'; +@import './styles/override.css'; +@import './styles/gimmicks.css'; + +@layer base { + /** +* @license +* +* Font Family: Clash Grotesk +* Designed by: Indian Type Foundry +* URL: https://www.fontshare.com/fonts/clash-grotesk +* © 2024 Indian Type Foundry +* +* Clash Grotesk Extralight +* Clash Grotesk Light +* Clash Grotesk Regular +* Clash Grotesk Medium +* Clash Grotesk Semibold +* Clash Grotesk Bold +* Clash Grotesk Variable (Variable font) + +* +*/ + @font-face { + font-family: 'ClashGrotesk-Extralight'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.ttf) format('truetype'); + font-weight: 200; + font-display: swap; + font-style: normal; + } + @font-face { + font-family: 'ClashGrotesk-Light'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Light.ttf) format('truetype'); + font-weight: 300; + font-display: swap; + font-style: normal; + } + @font-face { + font-family: 'ClashGrotesk-Regular'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.ttf) format('truetype'); + font-weight: 400; + font-display: swap; + font-style: normal; + } + @font-face { + font-family: 'ClashGrotesk-Medium'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.ttf) format('truetype'); + font-weight: 500; + font-display: swap; + font-style: normal; + } + @font-face { + font-family: 'ClashGrotesk-Semibold'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.ttf) format('truetype'); + font-weight: 600; + font-display: swap; + font-style: normal; + } + @font-face { + font-family: 'ClashGrotesk-Bold'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.ttf) format('truetype'); + font-weight: 700; + font-display: swap; + font-style: normal; + } + /** + * This is a variable font + * You can control variable axes as shown below: + * font-variation-settings: wght 700.0; + * + * available axes: + 'wght' (range from 200.0 to 700.0 + */ + @font-face { + font-family: 'ClashGrotesk-Variable'; + src: + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff2) format('woff2'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff) format('woff'), + url(/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.ttf) format('truetype'); + font-weight: 200 700; + font-display: swap; + font-style: normal; + } +} diff --git a/packages/taikoon-ui/src/app.d.ts b/packages/taikoon-ui/src/app.d.ts new file mode 100644 index 0000000000..ede601ab93 --- /dev/null +++ b/packages/taikoon-ui/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://kit.svelte.dev/docs/types#app +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/packages/taikoon-ui/src/app.html b/packages/taikoon-ui/src/app.html new file mode 100644 index 0000000000..40b3466f42 --- /dev/null +++ b/packages/taikoon-ui/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/taikoon-ui/src/assets/icons/ArrowDown.svg b/packages/taikoon-ui/src/assets/icons/ArrowDown.svg new file mode 100644 index 0000000000..600676ea6f --- /dev/null +++ b/packages/taikoon-ui/src/assets/icons/ArrowDown.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/taikoon-ui/src/assets/taikoon-black-frame.png b/packages/taikoon-ui/src/assets/taikoon-black-frame.png new file mode 100644 index 0000000000..d1f84b41da Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoon-black-frame.png differ diff --git a/packages/taikoon-ui/src/assets/taikoon-black.png b/packages/taikoon-ui/src/assets/taikoon-black.png new file mode 100644 index 0000000000..78688dce58 Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoon-black.png differ diff --git a/packages/taikoon-ui/src/assets/taikoon-white-frame.png b/packages/taikoon-ui/src/assets/taikoon-white-frame.png new file mode 100644 index 0000000000..5ab7a16124 Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoon-white-frame.png differ diff --git a/packages/taikoon-ui/src/assets/taikoon-white.png b/packages/taikoon-ui/src/assets/taikoon-white.png new file mode 100644 index 0000000000..1fed11b3dd Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoon-white.png differ diff --git a/packages/taikoon-ui/src/assets/taikoons-big-black.png b/packages/taikoon-ui/src/assets/taikoons-big-black.png new file mode 100644 index 0000000000..d61283fe77 Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoons-big-black.png differ diff --git a/packages/taikoon-ui/src/assets/taikoons-big-white.png b/packages/taikoon-ui/src/assets/taikoons-big-white.png new file mode 100644 index 0000000000..aa3bbd5e39 Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoons-big-white.png differ diff --git a/packages/taikoon-ui/src/assets/taikoons-icon.png b/packages/taikoon-ui/src/assets/taikoons-icon.png new file mode 100644 index 0000000000..17f619da29 Binary files /dev/null and b/packages/taikoon-ui/src/assets/taikoons-icon.png differ diff --git a/packages/taikoon-ui/src/assets/test-taikoon.png b/packages/taikoon-ui/src/assets/test-taikoon.png new file mode 100644 index 0000000000..02853c76bf Binary files /dev/null and b/packages/taikoon-ui/src/assets/test-taikoon.png differ diff --git a/packages/taikoon-ui/src/components/AccountConnectionToast/AccountConnectionToast.svelte b/packages/taikoon-ui/src/components/AccountConnectionToast/AccountConnectionToast.svelte new file mode 100644 index 0000000000..3946d6a938 --- /dev/null +++ b/packages/taikoon-ui/src/components/AccountConnectionToast/AccountConnectionToast.svelte @@ -0,0 +1,33 @@ + + + diff --git a/packages/taikoon-ui/src/components/AccountConnectionToast/index.ts b/packages/taikoon-ui/src/components/AccountConnectionToast/index.ts new file mode 100644 index 0000000000..6a77313626 --- /dev/null +++ b/packages/taikoon-ui/src/components/AccountConnectionToast/index.ts @@ -0,0 +1 @@ +export { default as AccountConnectionToast } from './AccountConnectionToast.svelte'; diff --git a/packages/taikoon-ui/src/components/AnimatedTaikoon/AnimatedTaikoon.svelte b/packages/taikoon-ui/src/components/AnimatedTaikoon/AnimatedTaikoon.svelte new file mode 100644 index 0000000000..303172f75f --- /dev/null +++ b/packages/taikoon-ui/src/components/AnimatedTaikoon/AnimatedTaikoon.svelte @@ -0,0 +1,87 @@ + + + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + + + + + diff --git a/packages/taikoon-ui/src/components/AnimatedTaikoon/index.ts b/packages/taikoon-ui/src/components/AnimatedTaikoon/index.ts new file mode 100644 index 0000000000..284d1a2114 --- /dev/null +++ b/packages/taikoon-ui/src/components/AnimatedTaikoon/index.ts @@ -0,0 +1 @@ +export { default as AnimatedTaikoon } from './AnimatedTaikoon.svelte'; diff --git a/packages/taikoon-ui/src/components/Collection/Collection.svelte b/packages/taikoon-ui/src/components/Collection/Collection.svelte new file mode 100644 index 0000000000..c447594157 --- /dev/null +++ b/packages/taikoon-ui/src/components/Collection/Collection.svelte @@ -0,0 +1,73 @@ + + + + +
+ {#if windowSize !== 'sm'} + + {/if} +
+
+ + + + + + diff --git a/packages/taikoon-ui/src/components/ThemeButton/index.ts b/packages/taikoon-ui/src/components/ThemeButton/index.ts new file mode 100644 index 0000000000..8f235e7155 --- /dev/null +++ b/packages/taikoon-ui/src/components/ThemeButton/index.ts @@ -0,0 +1 @@ +export { default as ThemeButton } from './ThemeButton.svelte'; diff --git a/packages/taikoon-ui/src/components/core/AnimatedBackground/AnimatedBackground.svelte b/packages/taikoon-ui/src/components/core/AnimatedBackground/AnimatedBackground.svelte new file mode 100644 index 0000000000..0811a2c0e4 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/AnimatedBackground/AnimatedBackground.svelte @@ -0,0 +1,72 @@ + + + + +
+ + {#each Array.from({ length: rows * cols }) as _, i} + {#if animated} + {@const rnd = Math.floor(Math.random() * 50)} + {#if i % 50 === rnd} + {@const classes = classNames(primaryCell, getRandomAnimation())} +
+ {:else if i % 40 === rnd} + {@const classes = classNames(secondaryCell, getRandomAnimation())} + +
+ {:else} +
+ {/if} + {:else} +
+ {/if} + {/each} +
diff --git a/packages/taikoon-ui/src/components/core/AnimatedBackground/index.ts b/packages/taikoon-ui/src/components/core/AnimatedBackground/index.ts new file mode 100644 index 0000000000..6c6c5c1f0f --- /dev/null +++ b/packages/taikoon-ui/src/components/core/AnimatedBackground/index.ts @@ -0,0 +1 @@ +export { default as AnimatedBackground } from './AnimatedBackground.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Button/Button.svelte b/packages/taikoon-ui/src/components/core/Button/Button.svelte new file mode 100644 index 0000000000..601b8f742e --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Button/Button.svelte @@ -0,0 +1,153 @@ + + +{#if href} + + {#if loading} + + {:else if iconLeft} + + {/if} + {#if label} + {label} + {:else} + + {/if} + {#if iconRight} + + {/if} + +{:else} + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Button/index.ts b/packages/taikoon-ui/src/components/core/Button/index.ts new file mode 100644 index 0000000000..ae34e39ce5 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Button/index.ts @@ -0,0 +1 @@ +export { default as Button } from './Button.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Button/states.ts b/packages/taikoon-ui/src/components/core/Button/states.ts new file mode 100644 index 0000000000..7f82d6d773 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Button/states.ts @@ -0,0 +1,5 @@ +export const enum ButtonState { + DEFAULT, + LOADING, + DISABLED, +} diff --git a/packages/taikoon-ui/src/components/core/Button/types.ts b/packages/taikoon-ui/src/components/core/Button/types.ts new file mode 100644 index 0000000000..b83a01cf49 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Button/types.ts @@ -0,0 +1 @@ +export type ActionButtonType = 'primary' | 'secondary'; diff --git a/packages/taikoon-ui/src/components/core/Chip/Chip.svelte b/packages/taikoon-ui/src/components/core/Chip/Chip.svelte new file mode 100644 index 0000000000..d3e4d8b6f6 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Chip/Chip.svelte @@ -0,0 +1,8 @@ + + + + + diff --git a/packages/taikoon-ui/src/components/core/Chip/index.ts b/packages/taikoon-ui/src/components/core/Chip/index.ts new file mode 100644 index 0000000000..8bdd50ebae --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Chip/index.ts @@ -0,0 +1 @@ +export { default as Chip } from './Chip.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Copyright/Copyright.svelte b/packages/taikoon-ui/src/components/core/Copyright/Copyright.svelte new file mode 100644 index 0000000000..498bc5dad9 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Copyright/Copyright.svelte @@ -0,0 +1,8 @@ + + +
+ {$t('content.sections.footer.copyright', { values: { year: currentYear } })} +
diff --git a/packages/taikoon-ui/src/components/core/Copyright/index.ts b/packages/taikoon-ui/src/components/core/Copyright/index.ts new file mode 100644 index 0000000000..bdfc0bbb94 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Copyright/index.ts @@ -0,0 +1 @@ +export { default as Copyright } from './Copyright.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Divider/Divider.svelte b/packages/taikoon-ui/src/components/core/Divider/Divider.svelte new file mode 100644 index 0000000000..fc8414d932 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Divider/Divider.svelte @@ -0,0 +1,7 @@ + + +
diff --git a/packages/taikoon-ui/src/components/core/Divider/index.ts b/packages/taikoon-ui/src/components/core/Divider/index.ts new file mode 100644 index 0000000000..1503c7f1dc --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Divider/index.ts @@ -0,0 +1 @@ +export { default as Divider } from './Divider.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Dropdown/Dropdown.svelte b/packages/taikoon-ui/src/components/core/Dropdown/Dropdown.svelte new file mode 100644 index 0000000000..39f04f38bf --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Dropdown/Dropdown.svelte @@ -0,0 +1,29 @@ + + +
(displayPanel = true)} + on:focus={() => (displayPanel = true)} + on:mouseleave={() => (displayPanel = false)} + role="button" + tabindex="0"> + + + {#if displayPanel} + + {/if} +
diff --git a/packages/taikoon-ui/src/components/core/Dropdown/DropdownPanel.svelte b/packages/taikoon-ui/src/components/core/Dropdown/DropdownPanel.svelte new file mode 100644 index 0000000000..6dd2ba2bd1 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Dropdown/DropdownPanel.svelte @@ -0,0 +1,37 @@ + + +
+ {#each options as option} + {@const Icon = Icons[option.icon]} + + + + {option.label} + + {/each} +
diff --git a/packages/taikoon-ui/src/components/core/Dropdown/index.ts b/packages/taikoon-ui/src/components/core/Dropdown/index.ts new file mode 100644 index 0000000000..00bd5c6d3d --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Dropdown/index.ts @@ -0,0 +1 @@ +export { default as Dropdown } from './Dropdown.svelte'; diff --git a/packages/taikoon-ui/src/components/core/IconButton/IconButton.svelte b/packages/taikoon-ui/src/components/core/IconButton/IconButton.svelte new file mode 100644 index 0000000000..5216afe9c0 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/IconButton/IconButton.svelte @@ -0,0 +1,68 @@ + + + diff --git a/packages/taikoon-ui/src/components/core/IconButton/index.ts b/packages/taikoon-ui/src/components/core/IconButton/index.ts new file mode 100644 index 0000000000..8ba804f0d1 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/IconButton/index.ts @@ -0,0 +1 @@ +export { default as IconButton } from './IconButton.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Icons/AngleDownSolid.svelte b/packages/taikoon-ui/src/components/core/Icons/AngleDownSolid.svelte new file mode 100644 index 0000000000..2d00d79e9e --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/AngleDownSolid.svelte @@ -0,0 +1,86 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{/if} + + diff --git a/packages/taikoon-ui/src/components/core/Icons/ArrowDown.svelte b/packages/taikoon-ui/src/components/core/Icons/ArrowDown.svelte new file mode 100644 index 0000000000..8b1857d28f --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/ArrowDown.svelte @@ -0,0 +1,97 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/ArrowRightFilled.svelte b/packages/taikoon-ui/src/components/core/Icons/ArrowRightFilled.svelte new file mode 100644 index 0000000000..2bc92dc387 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/ArrowRightFilled.svelte @@ -0,0 +1,103 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/CircleUserRegular.svelte b/packages/taikoon-ui/src/components/core/Icons/CircleUserRegular.svelte new file mode 100644 index 0000000000..61ed728de9 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/CircleUserRegular.svelte @@ -0,0 +1,86 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{/if} + + diff --git a/packages/taikoon-ui/src/components/core/Icons/DiscordLogo.svelte b/packages/taikoon-ui/src/components/core/Icons/DiscordLogo.svelte new file mode 100644 index 0000000000..52304f1f63 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/DiscordLogo.svelte @@ -0,0 +1,75 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/Menu.svelte b/packages/taikoon-ui/src/components/core/Icons/Menu.svelte new file mode 100644 index 0000000000..451fc22324 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/Menu.svelte @@ -0,0 +1,73 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/MinusSign.svelte b/packages/taikoon-ui/src/components/core/Icons/MinusSign.svelte new file mode 100644 index 0000000000..553d48c777 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/MinusSign.svelte @@ -0,0 +1,79 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/MirrorLogo.svelte b/packages/taikoon-ui/src/components/core/Icons/MirrorLogo.svelte new file mode 100644 index 0000000000..8669c600a4 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/MirrorLogo.svelte @@ -0,0 +1,113 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + + + + + + + + + + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + + + + + + + + + + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/Moon.svelte b/packages/taikoon-ui/src/components/core/Icons/Moon.svelte new file mode 100644 index 0000000000..7494cf7d9c --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/Moon.svelte @@ -0,0 +1,79 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/PlusSign.svelte b/packages/taikoon-ui/src/components/core/Icons/PlusSign.svelte new file mode 100644 index 0000000000..cc059626fa --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/PlusSign.svelte @@ -0,0 +1,79 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/Sun.svelte b/packages/taikoon-ui/src/components/core/Icons/Sun.svelte new file mode 100644 index 0000000000..92eb46e271 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/Sun.svelte @@ -0,0 +1,123 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + + + + + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + + + + + + + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/TaikoLogo.svelte b/packages/taikoon-ui/src/components/core/Icons/TaikoLogo.svelte new file mode 100644 index 0000000000..967e940121 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/TaikoLogo.svelte @@ -0,0 +1,75 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/TwitterLogo.svelte b/packages/taikoon-ui/src/components/core/Icons/TwitterLogo.svelte new file mode 100644 index 0000000000..88e4f8e796 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/TwitterLogo.svelte @@ -0,0 +1,75 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/UpRightArrow.svelte b/packages/taikoon-ui/src/components/core/Icons/UpRightArrow.svelte new file mode 100644 index 0000000000..b4ad79d818 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/UpRightArrow.svelte @@ -0,0 +1,79 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/XSolid.svelte b/packages/taikoon-ui/src/components/core/Icons/XSolid.svelte new file mode 100644 index 0000000000..b422ceb5fc --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/XSolid.svelte @@ -0,0 +1,100 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/YoutubeLogo.svelte b/packages/taikoon-ui/src/components/core/Icons/YoutubeLogo.svelte new file mode 100644 index 0000000000..df8b2c7318 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/YoutubeLogo.svelte @@ -0,0 +1,73 @@ + + +{#if withEvents} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{:else} + + {#if title.id && title.title} + {title.title} + {/if} + {#if desc.id && desc.desc} + {desc.desc} + {/if} + + +{/if} diff --git a/packages/taikoon-ui/src/components/core/Icons/index.ts b/packages/taikoon-ui/src/components/core/Icons/index.ts new file mode 100644 index 0000000000..93f0757e48 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Icons/index.ts @@ -0,0 +1,37 @@ +import { default as AngleDownSolid } from './AngleDownSolid.svelte'; +import { default as ArrowDown } from './ArrowDown.svelte'; +import { default as ArrowRightFilled } from './ArrowRightFilled.svelte'; +import { default as CircleUserRegular } from './CircleUserRegular.svelte'; +import { default as DiscordLogo } from './DiscordLogo.svelte'; +import { default as Menu } from './Menu.svelte'; +import { default as MinusSign } from './MinusSign.svelte'; +import { default as MirrorLogo } from './MirrorLogo.svelte'; +import { default as Moon } from './Moon.svelte'; +import { default as PlusSign } from './PlusSign.svelte'; +import { default as Sun } from './Sun.svelte'; +import { default as TaikoLogo } from './TaikoLogo.svelte'; +import { default as TwitterLogo } from './TwitterLogo.svelte'; +import { default as UpRightArrow } from './UpRightArrow.svelte'; +import { default as XSolid } from './XSolid.svelte'; +import { default as YoutubeLogo } from './YoutubeLogo.svelte'; + +export const Icons = { + CircleUserRegular, + AngleDownSolid, + Menu, + ArrowDown, + ArrowRightFilled, + DiscordLogo, + MinusSign, + MirrorLogo, + Moon, + PlusSign, + Sun, + TaikoLogo, + TwitterLogo, + UpRightArrow, + XSolid, + YoutubeLogo, +}; + +export type IconType = keyof typeof Icons; diff --git a/packages/taikoon-ui/src/components/core/Identicon/Identicon.svelte b/packages/taikoon-ui/src/components/core/Identicon/Identicon.svelte new file mode 100644 index 0000000000..f22afbde63 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Identicon/Identicon.svelte @@ -0,0 +1,25 @@ + + +{`identicon-${seed}`} diff --git a/packages/taikoon-ui/src/components/core/Identicon/index.ts b/packages/taikoon-ui/src/components/core/Identicon/index.ts new file mode 100644 index 0000000000..a97dfe2529 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Identicon/index.ts @@ -0,0 +1 @@ +export { default as Identicon } from './Identicon.svelte'; diff --git a/packages/taikoon-ui/src/components/core/InfoRow/InfoRow.svelte b/packages/taikoon-ui/src/components/core/InfoRow/InfoRow.svelte new file mode 100644 index 0000000000..aded7362ba --- /dev/null +++ b/packages/taikoon-ui/src/components/core/InfoRow/InfoRow.svelte @@ -0,0 +1,26 @@ + + +
+

{label}

+ + {#if loading} + + {:else} + {value} + {/if} + +
diff --git a/packages/taikoon-ui/src/components/core/InfoRow/index.ts b/packages/taikoon-ui/src/components/core/InfoRow/index.ts new file mode 100644 index 0000000000..daf538780d --- /dev/null +++ b/packages/taikoon-ui/src/components/core/InfoRow/index.ts @@ -0,0 +1 @@ +export { default as InfoRow } from './InfoRow.svelte'; diff --git a/packages/taikoon-ui/src/components/core/InputBox/InputBox.svelte b/packages/taikoon-ui/src/components/core/InputBox/InputBox.svelte new file mode 100644 index 0000000000..2031bc6efa --- /dev/null +++ b/packages/taikoon-ui/src/components/core/InputBox/InputBox.svelte @@ -0,0 +1,42 @@ + + + diff --git a/packages/taikoon-ui/src/components/core/InputBox/index.ts b/packages/taikoon-ui/src/components/core/InputBox/index.ts new file mode 100644 index 0000000000..2ed256a873 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/InputBox/index.ts @@ -0,0 +1 @@ +export { default as InputBox } from './InputBox.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Modal/Modal.svelte b/packages/taikoon-ui/src/components/core/Modal/Modal.svelte new file mode 100644 index 0000000000..668f5cf01c --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Modal/Modal.svelte @@ -0,0 +1,80 @@ + + +{#if open} +
{}} + aria-label="Close modal" + class={backdropClasses} + on:click={onBackdropClick}> +
+
+ + + {#if canClose} + { + handleClose(); + }} + size="sm" + class={closeButtonClasses} + icon="XSolid" + shape="circle" /> + {/if} +
+
+
+{/if} diff --git a/packages/taikoon-ui/src/components/core/Modal/ModalBody.svelte b/packages/taikoon-ui/src/components/core/Modal/ModalBody.svelte new file mode 100644 index 0000000000..97827fb370 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Modal/ModalBody.svelte @@ -0,0 +1,8 @@ + + +
+ +
diff --git a/packages/taikoon-ui/src/components/core/Modal/ModalFooter.svelte b/packages/taikoon-ui/src/components/core/Modal/ModalFooter.svelte new file mode 100644 index 0000000000..cec305d178 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Modal/ModalFooter.svelte @@ -0,0 +1,16 @@ + + +
+ +
diff --git a/packages/taikoon-ui/src/components/core/Modal/ModalTitle.svelte b/packages/taikoon-ui/src/components/core/Modal/ModalTitle.svelte new file mode 100644 index 0000000000..8fd37aff72 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Modal/ModalTitle.svelte @@ -0,0 +1,24 @@ + + +
+
+ +
+
diff --git a/packages/taikoon-ui/src/components/core/Modal/index.ts b/packages/taikoon-ui/src/components/core/Modal/index.ts new file mode 100644 index 0000000000..00e500f1c3 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Modal/index.ts @@ -0,0 +1,4 @@ +export { default as Modal } from './Modal.svelte'; +export { default as ModalBody } from './ModalBody.svelte'; +export { default as ModalFooter } from './ModalFooter.svelte'; +export { default as ModalTitle } from './ModalTitle.svelte'; diff --git a/packages/taikoon-ui/src/components/core/NumberInput/NumberInput.svelte b/packages/taikoon-ui/src/components/core/NumberInput/NumberInput.svelte new file mode 100644 index 0000000000..d697ad1a53 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/NumberInput/NumberInput.svelte @@ -0,0 +1,43 @@ + + +
+

{label}

+ +
+ + + + + +
+
diff --git a/packages/taikoon-ui/src/components/core/NumberInput/index.ts b/packages/taikoon-ui/src/components/core/NumberInput/index.ts new file mode 100644 index 0000000000..59a5ae7657 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/NumberInput/index.ts @@ -0,0 +1 @@ +export { default as NumberInput } from './NumberInput.svelte'; diff --git a/packages/taikoon-ui/src/components/core/ProgressBar/ProgressBar.svelte b/packages/taikoon-ui/src/components/core/ProgressBar/ProgressBar.svelte new file mode 100644 index 0000000000..38342db396 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/ProgressBar/ProgressBar.svelte @@ -0,0 +1,23 @@ + + +
+
+
diff --git a/packages/taikoon-ui/src/components/core/ProgressBar/index.ts b/packages/taikoon-ui/src/components/core/ProgressBar/index.ts new file mode 100644 index 0000000000..423ae6f3a9 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/ProgressBar/index.ts @@ -0,0 +1 @@ +export { default as ProgressBar } from './ProgressBar.svelte'; diff --git a/packages/taikoon-ui/src/components/core/ResponsiveController/ResponsiveController.svelte b/packages/taikoon-ui/src/components/core/ResponsiveController/ResponsiveController.svelte new file mode 100644 index 0000000000..b080af8688 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/ResponsiveController/ResponsiveController.svelte @@ -0,0 +1,39 @@ + diff --git a/packages/taikoon-ui/src/components/core/ResponsiveController/index.ts b/packages/taikoon-ui/src/components/core/ResponsiveController/index.ts new file mode 100644 index 0000000000..66a0f7d6cf --- /dev/null +++ b/packages/taikoon-ui/src/components/core/ResponsiveController/index.ts @@ -0,0 +1 @@ +export { default as ResponsiveController } from './ResponsiveController.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Section/Section.svelte b/packages/taikoon-ui/src/components/core/Section/Section.svelte new file mode 100644 index 0000000000..6e62ddd3f8 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Section/Section.svelte @@ -0,0 +1,50 @@ + + +
+ + +
+ +
+
diff --git a/packages/taikoon-ui/src/components/core/Section/SectionContainer.svelte b/packages/taikoon-ui/src/components/core/Section/SectionContainer.svelte new file mode 100644 index 0000000000..f2c35cfeff --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Section/SectionContainer.svelte @@ -0,0 +1,8 @@ + + +
+ +
diff --git a/packages/taikoon-ui/src/components/core/Section/index.ts b/packages/taikoon-ui/src/components/core/Section/index.ts new file mode 100644 index 0000000000..511089cea6 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Section/index.ts @@ -0,0 +1,2 @@ +export { default as Section } from './Section.svelte'; +export { default as SectionContainer } from './SectionContainer.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Select/Select.svelte b/packages/taikoon-ui/src/components/core/Select/Select.svelte new file mode 100644 index 0000000000..b7d78c79f4 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Select/Select.svelte @@ -0,0 +1,49 @@ + + +
(displayPanel = true)} + on:focus={() => (displayPanel = true)} + on:mouseleave={() => (displayPanel = false)} + role="button" + tabindex="0"> +
+ {label} + +
+ + {#if displayPanel} + + {/if} +
diff --git a/packages/taikoon-ui/src/components/core/Select/SelectPanel.svelte b/packages/taikoon-ui/src/components/core/Select/SelectPanel.svelte new file mode 100644 index 0000000000..1b6790cf57 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Select/SelectPanel.svelte @@ -0,0 +1,32 @@ + + +
+ {#each options as option} + + {/each} +
diff --git a/packages/taikoon-ui/src/components/core/Select/index.ts b/packages/taikoon-ui/src/components/core/Select/index.ts new file mode 100644 index 0000000000..f3019bebde --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Select/index.ts @@ -0,0 +1 @@ +export { default as Select } from './Select.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Spinner/Spinner.svelte b/packages/taikoon-ui/src/components/core/Spinner/Spinner.svelte new file mode 100644 index 0000000000..c453abf3a6 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Spinner/Spinner.svelte @@ -0,0 +1,16 @@ + + + diff --git a/packages/taikoon-ui/src/components/core/Spinner/index.ts b/packages/taikoon-ui/src/components/core/Spinner/index.ts new file mode 100644 index 0000000000..cd9bd18a8d --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Spinner/index.ts @@ -0,0 +1 @@ +export { default as Spinner } from './Spinner.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Text/Link.svelte b/packages/taikoon-ui/src/components/core/Text/Link.svelte new file mode 100644 index 0000000000..fd4f516b93 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Text/Link.svelte @@ -0,0 +1,9 @@ + + + + + diff --git a/packages/taikoon-ui/src/components/core/Text/P.svelte b/packages/taikoon-ui/src/components/core/Text/P.svelte new file mode 100644 index 0000000000..0986a279e4 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Text/P.svelte @@ -0,0 +1,7 @@ + + +

+ +

diff --git a/packages/taikoon-ui/src/components/core/Text/index.ts b/packages/taikoon-ui/src/components/core/Text/index.ts new file mode 100644 index 0000000000..18f2798a5d --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Text/index.ts @@ -0,0 +1,2 @@ +export { default as Link } from './Link.svelte'; +export { default as P } from './P.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Toast/ItemToast.svelte b/packages/taikoon-ui/src/components/core/Toast/ItemToast.svelte new file mode 100644 index 0000000000..c98d5b61a3 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Toast/ItemToast.svelte @@ -0,0 +1,36 @@ + + + diff --git a/packages/taikoon-ui/src/components/core/Toast/Toast.svelte b/packages/taikoon-ui/src/components/core/Toast/Toast.svelte new file mode 100644 index 0000000000..5210102409 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Toast/Toast.svelte @@ -0,0 +1,130 @@ + + + + +
+ +
+ + diff --git a/packages/taikoon-ui/src/components/core/Toast/index.ts b/packages/taikoon-ui/src/components/core/Toast/index.ts new file mode 100644 index 0000000000..fed6666a36 --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Toast/index.ts @@ -0,0 +1,2 @@ +export { default as Toast } from './Toast.svelte'; +export { errorToast, neutralToast, successToast, warningToast } from './Toast.svelte'; diff --git a/packages/taikoon-ui/src/components/core/Toast/types.ts b/packages/taikoon-ui/src/components/core/Toast/types.ts new file mode 100644 index 0000000000..44ae22a45b --- /dev/null +++ b/packages/taikoon-ui/src/components/core/Toast/types.ts @@ -0,0 +1 @@ +export type TypeToast = 'success' | 'error' | 'warning' | 'info' | 'unknown'; diff --git a/packages/taikoon-ui/src/components/core/index.ts b/packages/taikoon-ui/src/components/core/index.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/taikoon-ui/src/components/modals/MintAgreement.modal/MintAgreement.modal.svelte b/packages/taikoon-ui/src/components/modals/MintAgreement.modal/MintAgreement.modal.svelte new file mode 100644 index 0000000000..9ac8031fc8 --- /dev/null +++ b/packages/taikoon-ui/src/components/modals/MintAgreement.modal/MintAgreement.modal.svelte @@ -0,0 +1,33 @@ + + + + {$t('content.mint.modals.agreement.title')} + +
+ {$t('content.mint.modals.agreement.text')} +
+
+ + +
+ + +
+
+
diff --git a/packages/taikoon-ui/src/components/modals/MintAgreement.modal/classes.ts b/packages/taikoon-ui/src/components/modals/MintAgreement.modal/classes.ts new file mode 100644 index 0000000000..6a28821d10 --- /dev/null +++ b/packages/taikoon-ui/src/components/modals/MintAgreement.modal/classes.ts @@ -0,0 +1,24 @@ +import { classNames } from '$lib/util/classNames'; +export const wrapperClasses = 'items-center justify-center'; +export const textContainerClasses = classNames( + 'p-8', + 'my-4', + 'h-[50vh]', + 'w-[90vw]', + 'rounded-3xl', + 'overflow-y-scroll', + 'bg-elevated-background', +); + +export const buttonRowClasses = classNames( + 'flex', + 'md:flex-row', + 'flex-col', + 'w-full', + 'items-center', + 'justify-evenly', + 'gap-4', + 'py-4', +); + +export const buttonClasses = classNames('w-full', 'md:w-1/2'); diff --git a/packages/taikoon-ui/src/components/modals/MintConfirmation.modal/MintConfirmation.modal.svelte b/packages/taikoon-ui/src/components/modals/MintConfirmation.modal/MintConfirmation.modal.svelte new file mode 100644 index 0000000000..066725a873 --- /dev/null +++ b/packages/taikoon-ui/src/components/modals/MintConfirmation.modal/MintConfirmation.modal.svelte @@ -0,0 +1,131 @@ + + + + {#if $mintState.isMinting} + + {$mintState.isMinting + ? $t('content.mint.modals.minting.title', { + values: { + count: $mintState.totalMintCount, + plural: $mintState.totalMintCount === 1 ? '' : 's', + }, + }) + : ''} + + +
+ {#if $mintState.txHash} + {$t('content.mint.modals.minting.pending')} + {:else} + {$t('content.mint.modals.minting.confirm')} + {/if} +
+
+ +
+ {#if $mintState.txHash} +
+ +
+
+
Waiting for confirmation
+ {$t('buttons.etherscan')} + + +
+ {:else} +
+ +
+ {/if} +
+
+ {:else} + +
{ + scrollContainer.scrollLeft += e.deltaY; + }} + class={successBodyClasses}> +
+ {#each $mintState.tokenIds as tokenId} + + {/each} +
+
+ +
+ {$t('content.mint.modals.minted.title')} +
+
+ {$t('content.mint.modals.minted.text')} + + + {$t('content.mint.modals.minted.link')} +
+
+ +
+
+ +
+
+ +
+
+
+ {/if} +
diff --git a/packages/taikoon-ui/src/components/modals/MintConfirmation.modal/classes.ts b/packages/taikoon-ui/src/components/modals/MintConfirmation.modal/classes.ts new file mode 100644 index 0000000000..86e453e467 --- /dev/null +++ b/packages/taikoon-ui/src/components/modals/MintConfirmation.modal/classes.ts @@ -0,0 +1,65 @@ +import { classNames } from '$lib/util/classNames'; + +export const bodyWrapperClasses = 'text-content-secondary'; +export const footerWrapperClasses = 'w-full flex flex-row items-center gap-4'; +export const spinnerSmWrapper = 'bg-interactive-tertiary rounded-md w-[30px] h-[30px] flex items-center justify-center'; +export const spinnerMdWrapper = 'w-full flex justify-center items-center'; +export const textClasses = 'font-sans font-bold text-sm text-content-primary'; +export const linkClasses = 'flex flex-row items-center gap-2'; +export const mintedBodyClasses = 'justify-start gap-6 py-6 items-center'; +export const buttonWrapperClasses = 'md:w-1/2 w-full px-2'; + +export const successBodyClasses = classNames( + 'max-w-[50vw]', + 'p-5', + 'rounded-3xl', + 'my-5', + 'bg-background-elevated', + 'flex', + 'overflow-x-scroll', +); +export const nftRendererWrapperClasses = classNames( + 'flex', + 'flex-row', + 'justify-start', + 'items-start', + 'gap-5', + 'w-max', +); + +export const successTitleClasses = classNames( + 'text-content-primary', + 'text-4xl', + 'font-clash-grotesk', + 'font-semibold', + 'text-center', +); + +export const successContentClasses = classNames( + 'font-sans', + 'text-center', + 'text-content-secondary', + 'font-normal', + 'text-base', + 'md:w-min', + 'md:min-w-[300px]', + 'w-full', +); + +export const successMintedLinkClasses = classNames( + 'hover:text-content-link-hover', + 'text-content-link-primary', + 'font-sans', + 'font-normal', +); + +export const successFooterWrapperClasses = classNames( + 'flex', + 'md:flex-row', + 'flex-col', + 'w-full', + 'gap-4', + 'items-center', + 'justify-between', + 'min-w-[500px]', +); diff --git a/packages/taikoon-ui/src/components/modals/TaikoonDetail.modal/TaikoonDetail.modal.svelte b/packages/taikoon-ui/src/components/modals/TaikoonDetail.modal/TaikoonDetail.modal.svelte new file mode 100644 index 0000000000..8b6d0d9992 --- /dev/null +++ b/packages/taikoon-ui/src/components/modals/TaikoonDetail.modal/TaikoonDetail.modal.svelte @@ -0,0 +1,42 @@ + + + + Taikoon #{$taikoonDetailState.tokenId} + + +
+ +
+ +
+
diff --git a/packages/taikoon-ui/src/components/modals/index.ts b/packages/taikoon-ui/src/components/modals/index.ts new file mode 100644 index 0000000000..284f474353 --- /dev/null +++ b/packages/taikoon-ui/src/components/modals/index.ts @@ -0,0 +1,3 @@ +export { default as MintAgreementModal } from './MintAgreement.modal/MintAgreement.modal.svelte'; +export { default as MintConfirmationModal } from './MintConfirmation.modal/MintConfirmation.modal.svelte'; +export { default as TaikoonDetailModal } from './TaikoonDetail.modal/TaikoonDetail.modal.svelte'; diff --git a/packages/taikoon-ui/src/components/sections/Collapsible.section.svelte b/packages/taikoon-ui/src/components/sections/Collapsible.section.svelte new file mode 100644 index 0000000000..a9d7dc010d --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/Collapsible.section.svelte @@ -0,0 +1,88 @@ + + +
+
+
+ {$t('content.sections.faq.title')} +
+ +
+ {#each options as option, i} + + +
(activeEntryId = activeEntryId === i ? -1 : i)} class={collapseItemClasses}> + +
+ {option.title} +
+
+ {option.text} +
+
+ {/each} +
+
+
diff --git a/packages/taikoon-ui/src/components/sections/Countdown.section.svelte b/packages/taikoon-ui/src/components/sections/Countdown.section.svelte new file mode 100644 index 0000000000..98eaf9c5b5 --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/Countdown.section.svelte @@ -0,0 +1,76 @@ + + +
+ {#if windowSize === 'sm'} +
+ +
+ {/if} + +
+ + +
+ + + {#if windowSize === 'sm'} +
+ {:else} +
+ +
+ {/if} + +
+ + +
+
+ + +
+ + diff --git a/packages/taikoon-ui/src/components/sections/Footer.section.svelte b/packages/taikoon-ui/src/components/sections/Footer.section.svelte new file mode 100644 index 0000000000..e1c016681d --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/Footer.section.svelte @@ -0,0 +1,241 @@ + + +
+
+
+ {$t('content.sections.footer.joinTaiko')} +
+
+ {#each socialLinks as link} + {@const Icon = Icons[link.icon]} + + + {#if windowSize !== 'sm'} + {link.name} + {/if} + + {/each} +
+ +
+
+
+ {$t('content.sections.footer.content.title')} +
+
+ {$t('content.sections.footer.content.text')} +
+ + {#if windowSize === 'sm'} + {/if} +
+ +
+
+ {#each textLinks as textLink} +
    +
  • + {textLink.title} +
  • + {#each textLink.list as link} +
  • + {link.name} +
  • + {/each} +
+ {/each} +
+ {#if windowSize !== 'sm'} + + {/if} +
+
+
+
+ + diff --git a/packages/taikoon-ui/src/components/sections/Heading.section.svelte b/packages/taikoon-ui/src/components/sections/Heading.section.svelte new file mode 100644 index 0000000000..8231765e26 --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/Heading.section.svelte @@ -0,0 +1,31 @@ + + +
+ Taikoons Logo + + + + +
+ + diff --git a/packages/taikoon-ui/src/components/sections/Information.section.svelte b/packages/taikoon-ui/src/components/sections/Information.section.svelte new file mode 100644 index 0000000000..5f487853dd --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/Information.section.svelte @@ -0,0 +1,30 @@ + + +
+

+ {$t('content.sections.information.title')} +

+ +
+ {$t('content.sections.information.text')} +
+ +
diff --git a/packages/taikoon-ui/src/components/sections/TimerItem.svelte b/packages/taikoon-ui/src/components/sections/TimerItem.svelte new file mode 100644 index 0000000000..ff652a23c8 --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/TimerItem.svelte @@ -0,0 +1,27 @@ + + +
+
+ {count} +
+
{label}
+
diff --git a/packages/taikoon-ui/src/components/sections/index.ts b/packages/taikoon-ui/src/components/sections/index.ts new file mode 100644 index 0000000000..e3b6b0efaf --- /dev/null +++ b/packages/taikoon-ui/src/components/sections/index.ts @@ -0,0 +1,5 @@ +export { default as CollapsibleSection } from './Collapsible.section.svelte'; +export { default as CountdownSection } from './Countdown.section.svelte'; +export { default as FooterSection } from './Footer.section.svelte'; +export { default as HeadingSection } from './Heading.section.svelte'; +export { default as InformationSection } from './Information.section.svelte'; diff --git a/packages/taikoon-ui/src/generated/abi/index.ts b/packages/taikoon-ui/src/generated/abi/index.ts new file mode 100644 index 0000000000..fae30cd385 --- /dev/null +++ b/packages/taikoon-ui/src/generated/abi/index.ts @@ -0,0 +1,562 @@ +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// TaikoonToken +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0) + * - + */ +export const taikoonTokenAbi = [ + { + type: 'function', + inputs: [], + name: 'UPGRADE_INTERFACE_VERSION', + outputs: [{ name: '', internalType: 'string', type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'acceptOwnership', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'to', internalType: 'address', type: 'address' }, + { name: 'tokenId', internalType: 'uint256', type: 'uint256' }, + ], + name: 'approve', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'owner', internalType: 'address', type: 'address' }], + name: 'balanceOf', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: '_minter', internalType: 'address', type: 'address' }, + { name: '_maxMints', internalType: 'uint256', type: 'uint256' }, + ], + name: 'canMint', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }], + name: 'getApproved', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: '_owner', internalType: 'address', type: 'address' }, + { name: '_root', internalType: 'bytes32', type: 'bytes32' }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: '_owner', internalType: 'address', type: 'address' }, + { name: '_rootURI', internalType: 'string', type: 'string' }, + { name: '_merkleRoot', internalType: 'bytes32', type: 'bytes32' }, + ], + name: 'initialize', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'owner', internalType: 'address', type: 'address' }, + { name: 'operator', internalType: 'address', type: 'address' }, + ], + name: 'isApprovedForAll', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: '_minter', internalType: 'address', type: 'address' }, + { name: '_maxMints', internalType: 'uint256', type: 'uint256' }, + ], + name: 'leaf', + outputs: [{ name: '', internalType: 'bytes32', type: 'bytes32' }], + stateMutability: 'pure', + }, + { + type: 'function', + inputs: [], + name: 'maxSupply', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'pure', + }, + { + type: 'function', + inputs: [ + { name: '_to', internalType: 'address', type: 'address' }, + { name: '_amount', internalType: 'uint256', type: 'uint256' }, + ], + name: 'mint', + outputs: [{ name: '', internalType: 'uint256[]', type: 'uint256[]' }], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: '_proof', internalType: 'bytes32[]', type: 'bytes32[]' }, + { name: '_maxMints', internalType: 'uint256', type: 'uint256' }, + ], + name: 'mint', + outputs: [{ name: '', internalType: 'uint256[]', type: 'uint256[]' }], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'leaf', internalType: 'bytes32', type: 'bytes32' }], + name: 'minted', + outputs: [{ name: 'hasMinted', internalType: 'bool', type: 'bool' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'name', + outputs: [{ name: '', internalType: 'string', type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'owner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }], + name: 'ownerOf', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'pendingOwner', + outputs: [{ name: '', internalType: 'address', type: 'address' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'proxiableUUID', + outputs: [{ name: '', internalType: 'bytes32', type: 'bytes32' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'renounceOwnership', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [], + name: 'root', + outputs: [{ name: '', internalType: 'bytes32', type: 'bytes32' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'from', internalType: 'address', type: 'address' }, + { name: 'to', internalType: 'address', type: 'address' }, + { name: 'tokenId', internalType: 'uint256', type: 'uint256' }, + ], + name: 'safeTransferFrom', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'from', internalType: 'address', type: 'address' }, + { name: 'to', internalType: 'address', type: 'address' }, + { name: 'tokenId', internalType: 'uint256', type: 'uint256' }, + { name: 'data', internalType: 'bytes', type: 'bytes' }, + ], + name: 'safeTransferFrom', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'operator', internalType: 'address', type: 'address' }, + { name: 'approved', internalType: 'bool', type: 'bool' }, + ], + name: 'setApprovalForAll', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'interfaceId', internalType: 'bytes4', type: 'bytes4' }], + name: 'supportsInterface', + outputs: [{ name: '', internalType: 'bool', type: 'bool' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'symbol', + outputs: [{ name: '', internalType: 'string', type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: 'index', internalType: 'uint256', type: 'uint256' }], + name: 'tokenByIndex', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'owner', internalType: 'address', type: 'address' }, + { name: 'index', internalType: 'uint256', type: 'uint256' }, + ], + name: 'tokenOfOwnerByIndex', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [{ name: '_tokenId', internalType: 'uint256', type: 'uint256' }], + name: 'tokenURI', + outputs: [{ name: '', internalType: 'string', type: 'string' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [], + name: 'totalSupply', + outputs: [{ name: '', internalType: 'uint256', type: 'uint256' }], + stateMutability: 'view', + }, + { + type: 'function', + inputs: [ + { name: 'from', internalType: 'address', type: 'address' }, + { name: 'to', internalType: 'address', type: 'address' }, + { name: 'tokenId', internalType: 'uint256', type: 'uint256' }, + ], + name: 'transferFrom', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: 'newOwner', internalType: 'address', type: 'address' }], + name: 'transferOwnership', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [{ name: '_root', internalType: 'bytes32', type: 'bytes32' }], + name: 'updateRoot', + outputs: [], + stateMutability: 'nonpayable', + }, + { + type: 'function', + inputs: [ + { name: 'newImplementation', internalType: 'address', type: 'address' }, + { name: 'data', internalType: 'bytes', type: 'bytes' }, + ], + name: 'upgradeToAndCall', + outputs: [], + stateMutability: 'payable', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'owner', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'approved', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'tokenId', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + ], + name: 'Approval', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'owner', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'operator', + internalType: 'address', + type: 'address', + indexed: true, + }, + { name: 'approved', internalType: 'bool', type: 'bool', indexed: false }, + ], + name: 'ApprovalForAll', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'version', + internalType: 'uint64', + type: 'uint64', + indexed: false, + }, + ], + name: 'Initialized', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: '_minter', + internalType: 'address', + type: 'address', + indexed: false, + }, + { + name: '_mintAmount', + internalType: 'uint256', + type: 'uint256', + indexed: false, + }, + ], + name: 'MintConsumed', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'previousOwner', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'newOwner', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'OwnershipTransferStarted', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'previousOwner', + internalType: 'address', + type: 'address', + indexed: true, + }, + { + name: 'newOwner', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'OwnershipTransferred', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: '_root', + internalType: 'bytes32', + type: 'bytes32', + indexed: false, + }, + ], + name: 'RootUpdated', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { name: 'from', internalType: 'address', type: 'address', indexed: true }, + { name: 'to', internalType: 'address', type: 'address', indexed: true }, + { + name: 'tokenId', + internalType: 'uint256', + type: 'uint256', + indexed: true, + }, + ], + name: 'Transfer', + }, + { + type: 'event', + anonymous: false, + inputs: [ + { + name: 'implementation', + internalType: 'address', + type: 'address', + indexed: true, + }, + ], + name: 'Upgraded', + }, + { + type: 'error', + inputs: [{ name: 'target', internalType: 'address', type: 'address' }], + name: 'AddressEmptyCode', + }, + { + type: 'error', + inputs: [{ name: 'implementation', internalType: 'address', type: 'address' }], + name: 'ERC1967InvalidImplementation', + }, + { type: 'error', inputs: [], name: 'ERC1967NonPayable' }, + { type: 'error', inputs: [], name: 'ERC721EnumerableForbiddenBatchMint' }, + { + type: 'error', + inputs: [ + { name: 'sender', internalType: 'address', type: 'address' }, + { name: 'tokenId', internalType: 'uint256', type: 'uint256' }, + { name: 'owner', internalType: 'address', type: 'address' }, + ], + name: 'ERC721IncorrectOwner', + }, + { + type: 'error', + inputs: [ + { name: 'operator', internalType: 'address', type: 'address' }, + { name: 'tokenId', internalType: 'uint256', type: 'uint256' }, + ], + name: 'ERC721InsufficientApproval', + }, + { + type: 'error', + inputs: [{ name: 'approver', internalType: 'address', type: 'address' }], + name: 'ERC721InvalidApprover', + }, + { + type: 'error', + inputs: [{ name: 'operator', internalType: 'address', type: 'address' }], + name: 'ERC721InvalidOperator', + }, + { + type: 'error', + inputs: [{ name: 'owner', internalType: 'address', type: 'address' }], + name: 'ERC721InvalidOwner', + }, + { + type: 'error', + inputs: [{ name: 'receiver', internalType: 'address', type: 'address' }], + name: 'ERC721InvalidReceiver', + }, + { + type: 'error', + inputs: [{ name: 'sender', internalType: 'address', type: 'address' }], + name: 'ERC721InvalidSender', + }, + { + type: 'error', + inputs: [{ name: 'tokenId', internalType: 'uint256', type: 'uint256' }], + name: 'ERC721NonexistentToken', + }, + { + type: 'error', + inputs: [ + { name: 'owner', internalType: 'address', type: 'address' }, + { name: 'index', internalType: 'uint256', type: 'uint256' }, + ], + name: 'ERC721OutOfBoundsIndex', + }, + { type: 'error', inputs: [], name: 'FailedInnerCall' }, + { type: 'error', inputs: [], name: 'INVALID_PROOF' }, + { type: 'error', inputs: [], name: 'INVALID_TOKEN_AMOUNT' }, + { type: 'error', inputs: [], name: 'InvalidInitialization' }, + { type: 'error', inputs: [], name: 'MAX_MINTS_EXCEEDED' }, + { type: 'error', inputs: [], name: 'MAX_SUPPLY_REACHED' }, + { type: 'error', inputs: [], name: 'MINTER_NOT_WHITELISTED' }, + { type: 'error', inputs: [], name: 'MINTS_EXCEEDED' }, + { type: 'error', inputs: [], name: 'NotInitializing' }, + { + type: 'error', + inputs: [{ name: 'owner', internalType: 'address', type: 'address' }], + name: 'OwnableInvalidOwner', + }, + { + type: 'error', + inputs: [{ name: 'account', internalType: 'address', type: 'address' }], + name: 'OwnableUnauthorizedAccount', + }, + { type: 'error', inputs: [], name: 'TOKEN_NOT_MINTED' }, + { type: 'error', inputs: [], name: 'UUPSUnauthorizedCallContext' }, + { + type: 'error', + inputs: [{ name: 'slot', internalType: 'bytes32', type: 'bytes32' }], + name: 'UUPSUnsupportedProxiableUUID', + }, +] as const; + +/** + * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0) + * - + */ +export const taikoonTokenAddress = { + 17000: '0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0', + 31337: '0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82', +} as const; + +/** + * - [__View Contract on Holesky Etherscan__](https://holesky.etherscan.io/address/0x0874bD201a33bff5Ebd4f8200c6482A72457FeF0) + * - + */ +export const taikoonTokenConfig = { + address: taikoonTokenAddress, + abi: taikoonTokenAbi, +} as const; diff --git a/packages/taikoon/data/whitelist/hardhat.json b/packages/taikoon-ui/src/generated/whitelist/hardhat.json similarity index 91% rename from packages/taikoon/data/whitelist/hardhat.json rename to packages/taikoon-ui/src/generated/whitelist/hardhat.json index c7f5f9ab73..edf5280fc7 100644 --- a/packages/taikoon/data/whitelist/hardhat.json +++ b/packages/taikoon-ui/src/generated/whitelist/hardhat.json @@ -33,6 +33,5 @@ "treeIndex": 5 } ], - "leafEncoding": ["address", "uint256"], - "root": "0x1c3b504b4d5640d26ad1aa3b57a9df9ec034f19239768e734b849c306d10b110" + "leafEncoding": ["address", "uint256"] } diff --git a/packages/taikoon-ui/src/generated/whitelist/holesky.json b/packages/taikoon-ui/src/generated/whitelist/holesky.json new file mode 100644 index 0000000000..180a516015 --- /dev/null +++ b/packages/taikoon-ui/src/generated/whitelist/holesky.json @@ -0,0 +1,43 @@ +{ + "format": "standard-v1", + "tree": [ + "0x3e2da39414868a8a49c4ee78da50cc4430d88df27060300e553810ab2d23b5bd", + "0x6e291fe5546d4f99f1481bc939c724e98c3abf711a7b963939f9ee6942cbf9b6", + "0x5406cb9aa8f450c6702c6bcddcdb19077baaab45fd536a21c8e91cfd628343f7", + "0xaaa5072acbca877abbad0ad35c2e9742a5c826aedeb2517550beeb319ae8c911", + "0xb44c19e8955458cdce3bbb74260c7491d2737944d49429b72d2a45343b878da0", + "0xee3d903875927a1fd767e1fc8b850a5840596a21a00df4c2bec30a8f5d58d16d", + "0xafc473ef5147f5d39d32d4e4b466f4beea4e859f397980156d0470bb80900373", + "0xaf53707ab893501840153fc5f05a3a24c7d185d8bcfcc44ece20f8bd2f012339", + "0x921a6e0470293d600eead14aeb046dad51a5620ee1eb5e72b95112dbbe9b245a", + "0x7358742a31cea3f1d62dc77c7d63389fbd8a194073ad04ea25e4aa0071c7b4f3", + "0x456e44977c40b6df1bcb531feb67a5857454ad14ef1a4c2dd80834d19b339d0a" + ], + "values": [ + { + "value": ["0x8f63e3cD0D14cAef993E59B4e01e3D404cF3c1B7", "10"], + "treeIndex": 9 + }, + { + "value": ["0x2E2989015f5818A256EB967940454EfE8a0B4b5d", "10"], + "treeIndex": 5 + }, + { + "value": ["0x927a146e18294efb36edCacC99D9aCEA6aB16b95", "10"], + "treeIndex": 10 + }, + { + "value": ["0x4757D97449acA795510b9f3152C6a9019A3545c3", "10"], + "treeIndex": 6 + }, + { + "value": ["0x424bFb32f78731252a6BCeDc828E38e2701DAAEf", "10"], + "treeIndex": 7 + }, + { + "value": ["0xC66fAdfFeb6DA3b9A7FA3C71130F881e3a9B13fb", "10"], + "treeIndex": 8 + } + ], + "leafEncoding": ["address", "uint256"] +} diff --git a/packages/taikoon-ui/src/i18n/en.json b/packages/taikoon-ui/src/i18n/en.json new file mode 100644 index 0000000000..3c77860da7 --- /dev/null +++ b/packages/taikoon-ui/src/i18n/en.json @@ -0,0 +1,688 @@ +{ + "amount": { + "errors": { + "failed_max": "Unable to use max amount" + } + }, + "time": { + "day": "Day", + "days": "Days", + "hour": "Hour", + "hours": "Hours", + "minute": "Minute", + "minutes": "Minutes", + "second": "Second", + "seconds": "Seconds" + }, + "buttons": { + "mintNow": "Mint Now", + "learnMore": "Learn More", + "mint": "Mint", + "etherscan": "View on Etherscan", + "share": "Share", + "yourTaikoons": "Your Taikoons", + "cancel": "Cancel", + "agree": "Agree" + }, + "content": { + "mint": { + "title": "Taikoons", + "text": "Taikoons are the genesis NFT collection for the Taiko Layer 2 ecosystem.", + "mintsLeft": "Mints left: {mintsLeft}", + "toast": { + "clipboardCopy": "Link copied to clipboard" + }, + "modals": { + "minting": { + "title": "Minting {count} NFT{plural}...", + "pending": "This can take up to a couple of minutes. Feel free to close this message.", + "confirm": "Please confirm the transaction in your wallet." + }, + "minted": { + "title": "You got it!", + "text": "Your NFTs were minted! They are now in your Ethereum wallet and displayed on", + "link": "Your Taikoons" + }, + "agreement": { + "title": "Before you mint", + "text": "In a hole in the ground there lived a hobbit. Not a nasty, dirty, wet hole, filled with the ends of worms and an oozy smell, nor yet a dry, bare, sandy hole with nothing in it to sit down on or to eat: it was a hobbit-hole, and that means comfort. It had a perfectly round door like a porthole, painted green, with a shiny yellow brass knob in the exact middle. The door opened on to a tube-shaped hall like a tunnel: a very comfortable tunnel without smoke, with panelled walls, and floors tiled and carpeted, provided with polished chairs, and lots and lots of pegs for hats and coats—the hobbit was fond of visitors. The tunnel wound on and on, going fairly but not quite straight into the side of the hill—The Hill, as all the people for many miles round called it—and many little round doors opened out of it, first on one side and then on another. No going upstairs for the hobbit: bedrooms, bathrooms, cellars, pantries (lots of these), wardrobes (he had whole rooms devoted to clothes), kitchens, dining-rooms, all were on the same floor, and indeed on the same passage. The best rooms were all on the left-hand side (going in), for these were the only ones to have windows, deep-set round windows looking over his garden, and meadows beyond, sloping down to the river. This hobbit was a very well-to-do hobbit, and his name was Baggins. The Bagginses had lived in the neighbourhood of The Hill for time out of mind, and people considered them very respectable, not only because most of them were rich, but also because they never had any adventures or did anything unexpected: you could tell what a Baggins would say on any question without the bother of asking him. This is a story of how a Baggins had an adventure, and found himself doing and saying things altogether unexpected. He may have lost the neighbours’ respect, but he gained—well, you will see whether he gained anything in the end. The mother of our particular hobbit—what is a hobbit? I suppose hobbits need some description nowadays, since they have become rare and shy of the Big People, as they call us. They are (or were) a little people, about half our height, and smaller than the bearded Dwarves. Hobbits have no beards. There is little or no magic about them, except the ordinary everyday sort which helps them to disappear quietly and quickly when large stupid folk like you and me come blundering along, making a noise like elephants which they can hear a mile off. They are inclined to be fat in the stomach; they dress in bright colours (chiefly green and yellow); wear no shoes, because their feet grow natural leathery soles and thick warm brown hair like the stuff on their heads (which is curly); have long clever brown fingers, good-natured faces, and laugh deep fruity laughs (especially after dinner, which they have twice a day when they can get it). Now you know enough to go on with. As I was saying, the mother of this hobbit—of Bilbo Baggins, that is—was the famous Belladonna Took, one of the three remarkable daughters of the Old Took, head of the hobbits who lived across The Water, the small river that ran at the foot of The Hill. It was often said (in other families) that long ago one of the Took ancestors must have taken a fairy wife. That was, of course, absurd, but certainly there was still something not entirely hobbitlike about them, and once in a while members of the Took-clan would go and have adventures. They discreetly disappeared, and the family hushed it up; but the fact remained that the were not as respectable as the Bagginses, though they were undoubtedly richer. Not that Belladonna Took ever had any adventures after she became Mrs. Bungo Baggins. Bungo, that was Bilbo’s father, built the most luxurious hobbit-hole for her (and partly with her money) that was to be found either under The Hill or over The Hill or across The Water, and there they remained to the end of their days. Still it is probable that Bilbo, her only son, although he looked and behaved exactly like a second edition of his solid and comfortable father, got something a bit queer in his make-up from the Took side, something that only waited for a chance to come out. The chance never arrived, until Bilbo Baggins was grown up, being about fifty years old or so, and living in the beautiful hobbithole built by his father, which I have just described for you, until he had in fact apparently settled down immovably. By some curious chance one morning long ago in the quiet of the world, when there was less noise and more green, and the hobbits were still numerous and prosperous, and Bilbo Baggins was standing at his door after breakfast smoking an enormous long wooden pipe that reached nearly down to his woolly toes (neatly brushed)—Gandalf came by. Gandalf! If you had heard only a quarter of what I have heard about him, and I have only heard very little of all there is to hear, you would be prepared for any sort of remarkable tale. Tales and adventures sprouted up all over the place wherever he went, in the most extraordinary fashion. He had not been down that way under The Hill for ages and ages, not since his friend the Old Took died, in fact, and the hobbits had almost forgotten what he looked like. He had been away over The Hill and across The Water on businesses of his own since they were all small hobbit-boys and hobbitgirls. All that the unsuspecting Bilbo saw that morning was an old man with a staff. He had a tall pointed blue hat, a long grey cloak, a silver scarf over which his long white beard hung down below his waist, and immense black boots. “Good Morning!” said Bilbo, and he meant it. The sun was shining, and the grass was very green. But Gandalf looked at him from under long bushy eyebrows that stuck out further than the brim of his shady hat. “What do you mean?” he said. “Do you wish me a good morning, or mean that it is a good morning whether I want it or not; or that you feel good this morning; or that it is a morning to be good on?” “All of them at once,” said Bilbo. “And a very fine morning for a pipe of tobacco out of doors, into the bargain. If you have a pipe about you, sit down and have a fill of mine! There’s no hurry, we have all the day before us!” Then Bilbo sat down on a seat by his door, crossed his legs, and blew out a beautiful grey ring of smoke that sailed up into the air without breaking and floated away over The Hill. “Very pretty!” said Gandalf. “But I have no time to blow smoke-rings this morning. I am looking for someone to share in an adventure that I am arranging, and it’s very difficult to find anyone.” “I should think so—in these parts! We are plain quiet folk and have no use for adventures. Nasty disturbing uncomfortable things! Make you late for dinner! I can’t think what anybody sees in them,” said our Mr. Baggins, and stuck one thumb behind his braces, and blew out another even bigger smokering. Then he took out his morning letters, and began to read, pretending to take no more notice of the old man. He had decided that he was not quite his sort, and wanted him to go away. But the old man did not move. He stood leaning on his stick and gazing at the hobbit without saying anything, till Bilbo got quite uncomfortable and even a little cross. “Good morning!” he said at last. “We don’t want any adventures here, thank you! You might try over The Hill or across The Water.” By this he meant that the conversation was at an end. “What a lot of things you do use Good morning for!” said Gandalf. “Now you mean that you want to get rid of me, and that it won’t be good till I move off.” “Not at all, not at all, my dear sir! Let me see, I don’t think I know your name?” “Yes, yes, my dear sir—and I do know your name, Mr. Bilbo Baggins. And you do know my name, though you don’t remember that I belong to it. I am Gandalf, and Gandalf means me! To think that I should have lived to be good-morninged by Belladonna Took’s son, as if I was selling buttons at the door!” “Gandalf, Gandalf! Good gracious me! Not the wandering wizard that gave Old Took a pair of magic diamond studs that fastened themselves and never came undone till ordered? Not the fellow who used to tell such wonderful tales at parties, about dragons and goblins and giants and the rescue of princesses and the unexpected luck of widows’ sons? Not the man that used to make such particularly excellent fireworks! I remember those! Old Took used to have them on Midsummer’s Eve. Splendid! They used to go up like great lilies and snapdragons and laburnums of fire and hang in the twilight all evening!” You will notice already that Mr. Baggins was not quite so prosy as he liked to believe, also that he was very fond of flowers. “Dear me!” he went on. “Not the Gandalf who was responsible for so many quiet lads and lasses going off into the Blue for mad adventures? Anything from climbing trees to visiting elves—or sailing in ships, sailing to other shores! Bless me, life used to be quite inter—I mean, you used to upset things badly in these parts once upon a time. I beg your pardon, but I had no idea you were still in business.” “Where else should I be?” said the wizard. “All the same I am pleased to find you remember something about me. You seem to remember my fireworks kindly, at any rate, and that is not without hope. Indeed for your old grandfather Took’s sake, and for the sake of poor Belladonna, I will give you what you asked for.” “I beg your pardon, I haven’t asked for anything!” “Yes, you have! Twice now. My pardon. I give it you. In fact I will go so far as to send you on this adventure. Very amusing for me, very good for you—and profitable too, very likely, if you ever get over it.” “Sorry! I don’t want any adventures, thank you. Not today. Good morning! But please come to tea—any time you like! Why not tomorrow? Come tomorrow! Good bye!” With that the hobbit turned and scuttled inside his round green door, and shut it as quickly as he dared, not to seem rude. Wizards after all are wizards. “What on earth did I ask him to tea for!” he said to himself, as he went to the pantry. He had only just had breakfast, but he thought a cake or two and a drink of something would do him good after his fright. Gandalf in the meantime was still standing outside the door, and laughing long but quietly. After a while he stepped up, and with the spike on his staff scratched a queer sign on the hobbit’s beautiful green front-door. Then he strode away, just about the time when Bilbo was finishing his second cake and beginning to think that he had escaped adventures very well. The next day he had almost forgotten about Gandalf. He did not remember things very well, unless he put them down on his Engagement Tablet: like this: Gandalf Tea Wednesday. Yesterday he had been too flustered to do anything of the kind. Just before tea-time there came a tremendous ring on the front-door bell, and then he remembered! He rushed and put on the kettle, and put out another cup and saucer, and an extra cake or two, and ran to the door. “I am so sorry to keep you waiting!” he was going to say, when he saw that it was not Gandalf at all. It was a dwarf with a blue beard tucked into a golden belt, and very bright eyes under his dark-green hood. As soon as the door was opened, he pushed inside, just as if he had been expected. He hung his hooded cloak on the nearest peg, and “Dwalin at your service!” he said with a low bow. “Bilbo Baggins at yours!” said the hobbit, too surprised to ask any questions for the moment. When the silence that followed had become uncomfortable, he added: “I am just about to take tea; pray come and have some with me.” A little stiff perhaps, but he meant it kindly. And what would you do, if an uninvited dwarf came and hung his things up in your hall without a word of explanation? They had not been at table long, in fact they had hardly reached the third cake, when there came another even louder ring at the bell. “Excuse me!” said the hobbit, and off he went to the door. “So you have got here at last!” That was what he was going to say to Gandalf this time. But it was not Gandalf. Instead there was a very old-looking dwarf on the step with a white beard and a scarlet hood; and he too hopped inside as soon as the door was open, just as if he had been invited. “I see they have begun to arrive already,” he said when he caught sight of Dwalin’s green hood hanging up. He hung his red one next to it, and “Balin at your service!” he said with his hand on his breast. “Thank you!” said Bilbo with a gasp. It was not the correct thing to say, but they have begun to arrive had flustered him badly. He liked visitors, but he liked to know them before they arrived, and he preferred to ask them himself. He had a horrible thought that the cakes might run short, and then he—as the host: he knew his duty and stuck to it however painful—he might have to go without. “Come along in, and have some tea!” he managed to say after taking a deep breath. “A little beer would suit me better, if it is all the same to you, my good sir,” said Balin with the white beard. “But I don’t mind some cake—seed-cake, if you have any.” “Lots!” Bilbo found himself answering, to his own surprise; and he found himself scuttling off, too, to the cellar to fill a pint beer-mug, and then to a pantry to fetch two beautiful round seed-cakes which he had baked that afternoon for his after-supper morsel. When he got back Balin and Dwalin were talking at the table like old friends (as a matter of fact they were brothers). Bilbo plumped down the beer and the cake in front of them, when loud came a ring at the bell again, and then another ring. “Gandalf for certain this time,” he thought as he puffed along the passage. But it was not. It was two more dwarves, both with blue hoods, silver belts, and yellow beards; and each of them carried a bag of tools and a spade. In they hopped, as soon as the door began to open —Bilbo was hardly surprised at all. “What can I do for you, my dwarves?” he said. “Kili at your service!” said the one. “And Fili!” added the other; and they both swept off their blue hoods and bowed. “At yours and your family’s!” replied Bilbo, remembering his manners this time. “Dwalin and Balin here already, I see,” said Kili. “Let us join the throng!” “Throng!” thought Mr. Baggins. “I don’t like the sound of that. I really must sit down for a minute and collect my wits, and have a drink.” He had only just had a sip—in the corner, while the four dwarves sat round the table, and talked about mines and gold and troubles with the goblins, and the depredations of dragons, and lots of other things which he did not understand, and did not want to, for they sounded much too adventurous—when, dingdong-a-ling-dang, his bell rang again, as if some naughty little hobbit-boy was trying to pull the handle off. “Someone at the door!” he said, blinking. “Some four, I should say by the sound,” said Fili. “Besides, we saw them coming along behind us in the distance.” The poor little hobbit sat down in the hall and put his head in his hands, and wondered what had happened, and what was going to happen, and whether they would all stay to supper. Then the bell rang again louder than ever, and he had to run to the door. It was not four after all, it was five. Another dwarf had come along while he was wondering in the hall. He had hardly turned the knob, before they were all inside, bowing and saying “at your service” one after another. Dori, Nori, Ori, Oin, and Gloin were their names; and very soon two purple hoods, a grey hood, a brown hood, and a white hood were hanging on the pegs, and off they marched with their broad hands stuck in their gold and silver belts to join the others. Already it had almost become a throng. Some called for ale, and some for porter, and one for coffee, and all of them for cakes; so the hobbit was kept very busy for a while. A big jug of coffee had just been set in the hearth, the seed-cakes were gone, and the dwarves were starting on a round of buttered scones, when there came—a loud knock. Not a ring, but a hard rat-tat on the hobbit’s beautiful green door. Somebody was banging with a stick! Bilbo rushed along the passage, very angry, and altogether bewildered and bewuthered—this was the most awkward Wednesday he ever remembered. He pulled open the door with a jerk, and they all fell in, one on top of the other. More dwarves, four more! And there was Gandalf behind, leaning on his staff and laughing. He had made quite a dent on the beautiful door; he had also, by the way, knocked out the secret mark that he had put there the morning before. “Carefully! Carefully!” he said. “It is not like you, Bilbo, to keep friends waiting on the mat, and then open the door like a pop-gun! Let me introduce Bifur, Bofur, Bombur, and especially Thorin!” “At your service!” said Bifur, Bofur, and Bombur standing in a row. Then they hung up two yellow hoods and a pale green one; and also a sky-blue one with a long silver tassel. This last belonged to Thorin, an enormously important dwarf, in fact no other than the great Thorin Oakenshield himself, who was not at all pleased at falling flat on Bilbo’s mat with Bifur, Bofur, and Bombur on top of him. For one thing Bombur was immensely fat and heavy. Thorin indeed was very haughty, and said nothing about service; but poor Mr. Baggins said he was sorry so many times, that at last he grunted “pray don’t mention it,” and stopped frowning. “Now we are all here!” said Gandalf, looking at the row of thirteen hoods—the best detachable party hoods— and his own hat hanging on the pegs. “Quite a merry gathering! I hope there is something left for the latecomers to eat and drink! What’s that? Tea! No thank you! A little red wine, I think for me.” “And for me,” said Thorin. “And raspberry jam and apple-tart,” said Bifur. “And mince-pies and cheese,” said Bofur. “And pork-pie and salad,” said Bombur. “And more cakes—and ale—and coffee, if you don’t mind,” called the other dwarves through the door. “Put on a few eggs, there’s a good fellow!” Gandalf called after him, as the hobbit stumped off to the pantries. “And just bring out the cold chicken and pickles!” “Seems to know as much about the inside of my larders as I do myself!” thought Mr. Baggins, who was feeling positively flummoxed, and was beginning to wonder whether a most wretched adventure had not come right into his house. By the time he had got all the bottles and dishes and knives and forks and glasses and plates and spoons and things piled up on big trays, he was getting very hot, and red in the face, and annoyed." + } + } + }, + "collection": { + "ownedBy": "Owned by", + "labels": { + "minted": "Minted" + }, + "search": { + "placeholder": "Search Taikoons" + }, + "filter": { + "latest": "Latest", + "oldest": "Oldest" + } + }, + "sections": { + "information": { + "title": "The Collection", + "text": "The 888 Taikoons are the genesis NFT collection for the Taiko Layer 2 ecosystem, designed to foster community growth and establish unique on-chain identities." + }, + "faq": { + "title": "FAQs", + "entries": [ + { + "title": "What is the total supply of the NFTs in this collection?", + "text": "The total supply of the NFTs in this collection is 888." + }, + { + "title": "How can I use my Taikoons?", + "text": "You can use your Taikoons to participate in the Taiko Layer 2 ecosystem." + }, + { + "title": "What is the minting process?", + "text": "The minting process is as follows:" + }, + { + "title": "How does the daily auction work?", + "text": "The daily auction works as follows:" + } + ] + }, + "footer": { + "copyright": "© {year} Taiko Labs", + "joinTaiko": "Join the taiko community", + "content": { + "title": "Taiko", + "text": "The most developer-friendly and secure Ethereum scaling solution." + }, + "subscribe": { + "stayUpdated": "Stay updated! \nDive into the latest Taiko developer news", + "subscribe": "Subscribe", + "email": "Email" + }, + "nav": [ + { + "title": "About", + "list": [ + { + "name": "Blog", + "url": "/blog" + }, + { + "name": "Careers", + "url": "/careers" + }, + { + "name": "Brand kit", + "url": "/brand-assets" + } + ] + }, + { + "title": "Developers", + "list": [ + { + "name": "Get started", + "url": "https://docs.taiko.xyz/start-here/getting-started" + }, + { + "name": "GitHub", + "url": "https://github.com/taikoxyz" + } + ] + }, + { + "title": "Solutions", + "list": [ + { + "name": "Bridge", + "url": "https://bridge.hekla.taiko.xyz/" + }, + { + "name": "Swap", + "url": "https://swap.hekla.taiko.xyz/" + }, + { + "name": "Documentation", + "url": "https://docs.taiko.xyz/" + }, + { + "name": "Explorer", + "url": "https://hekla.taikoscan.network/" + } + ] + } + ], + "socials": [ + { + "icon": "DiscordLogo", + "name": "discord", + "url": "https://discord.com/invite/taikoxyz" + }, + { + "icon": "TwitterLogo", + "name": "twitter", + "url": "https://twitter.com/taikoxyz" + }, + { + "icon": "MirrorLogo", + "name": "mirror", + "url": "https://taiko.mirror.xyz/" + }, + { + "icon": "TaikoLogo", + "name": "forum", + "url": "https://community.taiko.xyz/" + }, + { + "icon": "YoutubeLogo", + "name": "youtube", + "url": "https://www.youtube.com/@taikoxyz" + } + ] + } + } + }, + "bridge": { + "actions": { + "approve": { + "rejected": { + "title": "Request to approve rejected" + }, + "success": { + "message": "You can now proceed to bridge {token}.", + "title": "Approved token" + }, + "tx": { + "message": "Track the {token} token approval status on the explorer here.", + "title": "Approval sent" + } + }, + "bridge": { + "success": { + "message": "Your funds are being prepared for claiming on Taiko.", + "title": "Transaction completed" + }, + "tx": { + "message": "Your bridge transaction was confirmed. The transaction can take a few minutes to complete, track it here.", + "title": "Transaction sent" + } + }, + "nft_manual": "Add manually", + "nft_scan": "Scan for NFT", + "nft_scan_again": "Scan again" + }, + "alerts": { + "slow_bridging": "Please note: Bridging to L1 will take around 24hrs!" + }, + "button": { + "approve": "Approve", + "approved": "Approved", + "approving": "Approving", + "bridge": "Bridge", + "bridging": "Bridging", + "fetch": "Fetch NFT data", + "import": "Import", + "validating": "Validating..." + }, + "description": { + "default": "Send your assets across chains.", + "fungible": { + "confirm": "Bridge your assets", + "import": "Send your assets across chains", + "recipient": "Set up information on the recipient blockchain.", + "review": "Verify your transaction details" + }, + "nft": { + "confirm": "Bridge your NFTs", + "import": "Transfer your NFTs across chains", + "recipient": "Set up information on the recipient blockchain.", + "review": "Verify your transaction details" + } + }, + "errors": { + "approve_error": { + "message": "We encountered an issue while trying to approve this token.", + "title": "Approval failed" + }, + "approve_rejected": { + "title": "Request to approve rejected by user" + }, + "cannot_fetch_balance": "Error fetching balance. Wrong chain?", + "custom_token": { + "not_found": { + "message": "Token not found. Are you on the right network?" + } + }, + "insufficient_allowance": { + "message": "Please increase your allowance to proceed with bridging.", + "title": "Insufficient allowance" + }, + "insufficient_balance": { + "message": "Sorry, your wallet balance is too low to cover this token.", + "title": "Insufficient wallet balance" + }, + "invalid_proof_provided": "An invalid proof was provided for this action.", + "no_allowance_required": { + "message": "You already have sufficient allowance for this request.", + "title": "Allowance already set" + }, + "no_decimals_allowed": "Decimals are not supported for this token", + "not_the_owner_of_all": "You must be the owner of all tokens", + "process_message_error": "Unable to process message", + "release_error": { + "message": "Unable to release the funds." + }, + "retry_error": "Retry claiming failed", + "send_erc20_error": { + "message": "There was an issue attempting to send ERC20 token.", + "title": "Failed to send" + }, + "send_message_error": { + "message": "Please try again", + "title": "Failed to send" + }, + "unknown_error": { + "message": "An unexpected error has occurred. Please try again.", + "title": "Unknown error" + } + }, + "nft": { + "step": { + "import": { + "nft_card": { + "select": "Select NFT", + "title": "NFT details" + }, + "no_nft_found": "We could not find any NFTs. Please try again or consider adding them manually.", + "scan_screen": { + "description": "Don't see your NFTs? Try adding them manually!", + "title": "Your NFTs ({number} items)" + }, + "select_all": "Select all" + }, + "review": { + "recipient_details": "Recipient details", + "transfer_details": "Transfer details", + "your_tokens": "Your tokens on" + } + } + }, + "step": { + "confirm": { + "analyzing": "Please wait", + "approve": { + "description": "Before initiating the bridge, it's necessary to first approve the transfer.", + "pending": "Please wait for your transaction to be picked up", + "success": { + "message": "Your approve transaction was confirmed. The transaction can take a few minutes to complete, track it here." + }, + "title": "Approval required" + }, + "approved": { + "description_eth": "You can now continue to bridge your funds", + "description_token": "All tokens are approved, you can now bridge your assets", + "title": "Proceed to bridge" + }, + "bridge": { + "success": { + "message": "Your bridge transaction was confirmed. The transaction can take a few minutes to complete, track it here." + } + }, + "button": { + "back": "Back to bridge" + }, + "checking_status": "Checking the approval status", + "processing": "Processing...", + "title": "Confirm" + }, + "import": { + "title": "Import" + }, + "review": { + "title": "Review" + } + }, + "title": { + "default": "Bridge Token", + "fungible": { + "confirm": "Confirm", + "import": "Bridge Token", + "recipient": "Recipient", + "review": "Review" + }, + "nft": { + "confirm": "Confirm", + "import": "Import NFT", + "recipient": "Recipient", + "review": "Review" + } + }, + "welcome_modal": { + "body": "Welcome to Katla, our final testnet.
Strengthening security may cause some delay in L2→L1 bridging, around 24 hours on the testnet. We're striving for shorter delays on the mainnet.", + "confirm": "I understand", + "link": "Find out more", + "title": "Important Update" + } + }, + "chain_selector": { + "currently_on": "You are currently on", + "disabled_options": { + "description": "Some options might be disabled due to not having a valid bridge configuration", + "title": "Disabled options?" + }, + "from_placeholder": "Select Source Chain", + "placeholder": "Select chain", + "to_placeholder": "Select Destination Chain" + }, + "common": { + "add": "Add", + "address": "Address", + "amount": "Amount", + "back": "Go back", + "balance": "Balance", + "bridged_address": "Bridged address", + "cancel": "Cancel", + "canonical_address": "Canonical address", + "close": "Close", + "collection": "Collection", + "confirm": "Confirm", + "continue": "Continue", + "contract_address": "Contract address", + "customized": "Customized", + "destination": "Destination", + "edit": "Edit", + "error": "Error", + "fetching_balance": "Fetching balance...", + "from": "From", + "id": "ID", + "loading": "Loading", + "name": "Name", + "not_available_short": "N/A", + "ok": "Okay", + "status": "Status", + "success": "Success", + "symbol": "Symbol", + "to": "To", + "token_id": "Token ID", + "token_standard": "Token standard" + }, + "custom_recipient": { + "placeholder": "Add custom recipient" + }, + "faucet": { + "button": { + "checking": "Checking mintability", + "mint": "Mint", + "minting": "Minting" + }, + "description": "Mint test tokens.", + "mint": { + "error": "You have already minted your tokens.", + "rejected": { + "message": "An error occurred while attempting to mint the token.", + "title": "Error minting token" + }, + "success": { + "message": "Check your updated balance on the Bridge page.", + "title": "Token minted successfully" + }, + "tx": { + "message": "Track the progress on the explorer here.", + "title": "Transaction sent" + }, + "unknown_error": "Something went wrong, please try again." + }, + "title": "Faucet", + "warning": { + "insufficient_balance": "You don't have enough ETH to complete the transaction. Please add some ETH to your wallet.", + "no_connected": "Please connect your wallet to mint tokens.", + "not_mintable": "This token is not mintable on this network", + "token_minted": "You have already minted this token.", + "unknown": "Something did not work" + }, + "wrong_chain": { + "button": "Switch to {network}", + "message": "It appears you are on the wrong network. Switch to {network} to mint tokens." + } + }, + "inputs": { + "address_input": { + "errors": { + "invalid": "Invalid address format", + "not_erc20": "This is not a valid ERC20 address on the current network", + "not_nft": "This is not a valid NFT address on the current network", + "too_short": "Address is too short" + }, + "label": { + "contract": "Contract address", + "default": "Address", + "recipient": "Recipient address" + }, + "placeholder": "Enter a valid ethereum address", + "success": "Valid address format" + }, + "amount": { + "balance": "Balance", + "button": { + "max": "Max" + }, + "errors.failed_max": "Could not estimate max amount to bridge.", + "label": "Amount" + }, + "token_id_input": { + "errors": { + "invalid": "Not a valid numeric value" + }, + "label": "Token ID", + "placeholder": "e.g. 1 (only numbers)" + } + }, + "messages": { + "account": { + "connected": "Account connected", + "disconnected": "Account disconnected", + "required": "Please connect your wallet." + }, + "bridge": { + "nft_scanning": "Scanning for NFTs" + }, + "network": { + "pending": { + "message": "Please open your wallet to check the current status.", + "title": "Network switch pending" + }, + "rejected": { + "message": "Request to switch network has been rejected by the user.", + "title": "Network switch rejected" + }, + "required": "Source chain must be selected.", + "required_dest": "Destination chain must be selected.", + "success": { + "message": "Successfully switched to {chainName}", + "title": "Connected" + }, + "switching": "Switching network" + } + }, + "nav": { + "bridge": "Bridge", + "explorer": "Explorer", + "faucet": "Faucet", + "guide": "Guide", + "nft": "NFT", + "theme": "Theme", + "token": "Token", + "transactions": "Transactions", + "swap": "Swap" + }, + "paused_modal": { + "description": "The bridge is currently not available. Follow our official communicationchannels for more information. ", + "title": "Bridge under maintenance!" + }, + "processing_fee": { + "button": { + "cancel": "Cancel", + "confirm": "Confirm" + }, + "custom": { + "label": "Custom", + "text": "Customize your processing fee" + }, + "customized": "Customized", + "description": "The payment you provide to the relayer for handling your bridge message on the destination chain.", + "link": "Customize fee", + "none": { + "label": "None", + "text": "Use ETH to manually claim your bridged token later", + "warning": "Insufficient ETH to cover the gas fees for claiming." + }, + "recommended": { + "calculating": "Calculating", + "error": "Error calculating", + "label": "Recommended" + }, + "title": "Processing fee", + "tooltip": "The payment you provide to the relayer for handling your bridge message on the destination chain.", + "tooltip_title": "What is Processing Fee?" + }, + "recipient": { + "description": "You can set a custom address as the recipient of your funds, instead of your current wallet address.", + "label": "incl. fees ~", + "link": "Change recipient", + "placeholder": "Add custom recipient 0x…", + "title": "Recipient address", + "tooltip": "Defaults to your address. You can add a custom recipient address as well.", + "tooltip_title": "What is Custom Recipient?" + }, + "switch_modal": { + "description": "Your current network is not supported. Please select one of the following chains to proceed:", + "title": "Incorrect network detected" + }, + "token_dropdown": { + "add_custom": "Add Custom", + "custom_token": { + "button": "Add token", + "description": "You can add your own token by entering the contract address below. Make sure you are on the chain where the token is deployed.", + "title": "Add your own token" + }, + "label": "Select token" + }, + "transactions": { + "actions": { + "claim": { + "dialog": { + "description": "Insufficient balance to claim yourself. Please wait for the relayer to claim for you automatically. Refer to our guide for more information.", + "link": "Go to guide", + "title": "Please wait" + }, + "rejected": { + "title": "Request to claim rejected." + }, + "success": { + "message": "Your funds have been successfully claimed on {network}.", + "title": "Transaction completed" + }, + "tx": { + "message": "Track the progress on the explorer here.", + "title": "Transaction sent" + } + }, + "release": { + "rejected": { + "title": "Request to release rejected." + }, + "success": { + "message": "Your funds have been released on {network}", + "title": "Transaction completed" + }, + "tx": { + "message": "Track the progress on the explorer here.", + "title": "Transaction sent" + } + } + }, + "button": { + "claim": "Claim", + "release": "Release", + "retry": "Retry" + }, + "description": "Track your bridge transactions here.", + "details_dialog": { + "title": "Transaction details" + }, + "errors": { + "insufficient_balance": "Insufficient balance to claim yourself. Please wait for the relayer to claim for you automatically. Refer to our guide for more information.", + "relayer_offline": "Relayer did not respond. Your transactions may only be loaded partially." + }, + "filter": { + "all": "All", + "claimed": "Claimed", + "failed": "Failed", + "processing": "Processing", + "retry": "Retriable", + "title": "Filters" + }, + "header": { + "amount": "Amount", + "explorer": "Explorer", + "from": "From", + "item": "Item", + "status": "Status", + "to": "To" + }, + "link": { + "explorer": "View details", + "explorer_short": "View" + }, + "no_transactions": "No transactions found", + "status": { + "claim": { + "description": "Your asset is now ready for claiming on the destination chain and requires a transaction. If you have set a processing fee, the relayer will automatically handle the claiming process on your behalf.", + "name": "Claim" + }, + "claimed": { + "description": "Your asset has successfully completed the bridging process and is now available to you on the destination chain.", + "name": "Claimed" + }, + "claiming": "Claiming", + "dialog": { + "description": "The bridge message undergoes different stages:", + "title": "Message status" + }, + "error": { + "name": "Failed" + }, + "failed": { + "description": "Your bridge transaction was unsuccessful.", + "name": "Failed" + }, + "pending": { + "description": " Your asset is not yet eligible for claiming. The bridging process from Taiko to Sepolia may take several hours before becoming claimable. Sepolia to Taiko bridging should be claimable within minutes.", + "name": "Pending" + }, + "processing": { + "description": "Transaction is processing. Depending on the pending blocks to be verified this can take up to several minutes.", + "name": "Processing" + }, + "release": { + "description": "Your bridged asset cannot be processed and is now accessible to you on the source chain.", + "name": "Release" + }, + "releasing": "Releasing", + "retry": { + "description": "The relayer was unable to process this message, and you will need to retry the processing yourself.", + "name": "Retry" + } + }, + "title": "Transactions" + }, + "wallet": { + "connect": "Connect wallet", + "status": { + "connected": "Connected", + "connecting": "Connecting", + "disconnected": "Disconnected" + } + } +} diff --git a/packages/taikoon-ui/src/i18n/index.ts b/packages/taikoon-ui/src/i18n/index.ts new file mode 100644 index 0000000000..c95bed640e --- /dev/null +++ b/packages/taikoon-ui/src/i18n/index.ts @@ -0,0 +1,12 @@ +import { addMessages, getLocaleFromNavigator, init } from 'svelte-i18n'; + +import en from './en.json'; +// TODO: import other languages here... + +addMessages('en', en); +// TODO: add other languages here... + +init({ + fallbackLocale: 'en', + initialLocale: getLocaleFromNavigator(), +}); diff --git a/packages/taikoon-ui/src/index.test.ts b/packages/taikoon-ui/src/index.test.ts new file mode 100644 index 0000000000..aa93426376 --- /dev/null +++ b/packages/taikoon-ui/src/index.test.ts @@ -0,0 +1,7 @@ +import { describe, expect, it } from 'vitest'; + +describe('sum test', () => { + it('adds 1 + 2 to equal 3', () => { + expect(1 + 2).toBe(3); + }); +}); diff --git a/packages/taikoon-ui/src/lib/chain/chains.ts b/packages/taikoon-ui/src/lib/chain/chains.ts new file mode 100644 index 0000000000..57cfbe113e --- /dev/null +++ b/packages/taikoon-ui/src/lib/chain/chains.ts @@ -0,0 +1,109 @@ +import type { Chain } from 'viem'; + +import { type ChainConfig, type ChainConfigMap, LayerType } from '../../lib/chain'; + +//import { chainConfig } from '$chainConfig'; + +const chainConfigs: ChainConfigMap = { + '1': { + name: 'Ethereum', + rpcUrls: { + default: { + http: ['https://mainnet.infura.io/v3/'], + webSocket: ['wss://mainnet.infura.io/ws/v3/'], + }, + }, + nativeCurrency: { + name: 'Ether', + symbol: 'ETH', + decimals: 18, + }, + icon: '/chains/ethereum.svg', + type: 'L1' as LayerType, // Add the missing 'type' property with the value of 'LayerType' + }, + '31337': { + name: 'Hardhat', + rpcUrls: { + default: { + http: ['http://localhost:8545'], + //webSocket: ['wss://mainnet.infura.io/ws/v3/'], + }, + }, + nativeCurrency: { + name: 'Ether', + symbol: 'ETH', + decimals: 18, + }, + icon: '/chains/ethereum.svg', + type: 'L1' as LayerType, // Add the missing 'type' property with the value of 'LayerType' + }, + '17000': { + name: 'Holesky', + rpcUrls: { + default: { + http: ['https://rpc.holesky.io'], + //webSocket: ['wss://mainnet.infura.io/ws/v3/'], + }, + }, + nativeCurrency: { + name: 'Ether', + symbol: 'ETH', + decimals: 18, + }, + icon: '/chains/ethereum.svg', + type: 'L1' as LayerType, // Add the missing 'type' property with the value of 'LayerType' + }, +}; + +function mapChainConfigToChain(chainId: string, chainConfig: ChainConfig): Chain { + return { + id: Number(chainId), + name: chainConfig.name, + rpcUrls: chainConfig.rpcUrls, + nativeCurrency: chainConfig.nativeCurrency, + blockExplorers: chainConfig.blockExplorers, + }; +} + +export const chainIdToChain = (chainId: number): Chain => { + const chain = chains.find((chain) => chain.id === chainId); + if (!chain) { + throw new Error(`Chain with id ${chainId} not found`); + } + return chain; +}; + +export const chains: Chain[] = Object.entries(chainConfigs).map(([chainId, chainConfig]) => + mapChainConfigToChain(chainId, chainConfig as ChainConfig), +); + +export const getConfiguredChainIds = (): number[] => { + return chains.map((chain) => Number(chain.id)); +}; + +export const isSupportedChain = (chainId: number) => { + return chains.some((chain) => chain.id === chainId); +}; + +export const getChainImages = (): Record => { + return Object.fromEntries( + Object.entries(chainConfigs).map(([chainId]) => [Number(chainId), chainConfigs[Number(chainId)].icon]), + ); +}; + +export const getChainImage = (chainId: number) => { + const images = getChainImages(); + if (!images[chainId]) { + throw new Error(`Chain with id ${chainId} not found`); + } + + return images[chainId]; +}; + +export const getChainName = (chainId: number) => { + const chain = chains.find((chain) => chain.id === chainId); + if (!chain) { + throw new Error(`Chain with id ${chainId} not found`); + } + return chain.name; +}; diff --git a/packages/taikoon-ui/src/lib/chain/index.ts b/packages/taikoon-ui/src/lib/chain/index.ts new file mode 100644 index 0000000000..6a85535358 --- /dev/null +++ b/packages/taikoon-ui/src/lib/chain/index.ts @@ -0,0 +1,2 @@ +export * from './chains'; +export * from './types'; diff --git a/packages/taikoon-ui/src/lib/chain/types.ts b/packages/taikoon-ui/src/lib/chain/types.ts new file mode 100644 index 0000000000..d5d2d1bba3 --- /dev/null +++ b/packages/taikoon-ui/src/lib/chain/types.ts @@ -0,0 +1,20 @@ +import type { Chain } from 'viem'; + +export type ChainID = bigint; + +export enum LayerType { + L1 = 'L1', + L2 = 'L2', + L3 = 'L3', +} + +export type ChainConfig = Omit & { + icon: string; + type: LayerType; +}; + +export type ChainConfigMap = Record; + +export type ConfiguredChains = { + configuredChains: Array>; +}; diff --git a/packages/taikoon-ui/src/lib/connect/index.ts b/packages/taikoon-ui/src/lib/connect/index.ts new file mode 100644 index 0000000000..3efb092617 --- /dev/null +++ b/packages/taikoon-ui/src/lib/connect/index.ts @@ -0,0 +1 @@ +export * from './web3modal'; diff --git a/packages/taikoon-ui/src/lib/connect/web3modal.ts b/packages/taikoon-ui/src/lib/connect/web3modal.ts new file mode 100644 index 0000000000..2476054566 --- /dev/null +++ b/packages/taikoon-ui/src/lib/connect/web3modal.ts @@ -0,0 +1,41 @@ +import { getAccount, getChainId, watchAccount, watchChainId } from '@wagmi/core'; +import { createWeb3Modal } from '@web3modal/wagmi'; +import { readable } from 'svelte/store'; + +import { PUBLIC_WALLETCONNECT_PROJECT_ID } from '$env/static/public'; +import { config } from '$wagmi-config'; + +import { getChainImages } from '../../lib/chain'; + +const projectId = PUBLIC_WALLETCONNECT_PROJECT_ID || ''; +const chainImages = getChainImages(); + +export const chainId = readable(getChainId(config), (set) => watchChainId(config, { onChange: set })); + +export const account = readable(getAccount(config), (set) => watchAccount(config, { onChange: set })); + +export const provider = readable(undefined, (set) => + watchAccount(config, { + onChange: async (account) => { + if (!account.connector) return set(undefined); + set(await account.connector?.getProvider()); + }, + }), +); + +export const web3modal = createWeb3Modal({ + wagmiConfig: config, + projectId, + featuredWalletIds: [], + allowUnsupportedChain: true, + excludeWalletIds: ['c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96'], + chainImages, + themeVariables: { + '--w3m-color-mix': 'var(--neutral-background)', + '--w3m-color-mix-strength': 20, + '--w3m-font-family': '"Public Sans", sans-serif', + '--w3m-border-radius-master': '9999px', + '--w3m-accent': 'var(--primary-brand)', + }, + themeMode: (localStorage.getItem('theme') as 'dark' | 'light') ?? 'dark', +}); diff --git a/packages/taikoon-ui/src/lib/ens/getAddress.ts b/packages/taikoon-ui/src/lib/ens/getAddress.ts new file mode 100644 index 0000000000..bbe8ada40b --- /dev/null +++ b/packages/taikoon-ui/src/lib/ens/getAddress.ts @@ -0,0 +1,17 @@ +import { getEnsAddress } from '@wagmi/core'; +import { type GetEnsAddressReturnType } from '@wagmi/core'; +import { normalize } from 'viem/ens'; + +import type { IAddress } from '../../types'; +import getConfig from '../wagmi/getConfig'; + +export default async function getAddress(ensName: string): Promise { + const { config, chainId } = getConfig(); + const address = (await getEnsAddress(config, { + name: normalize(ensName), + chainId, + })) as GetEnsAddressReturnType; + + if (!address) throw new Error('No ENS name'); + return address; +} diff --git a/packages/taikoon-ui/src/lib/ens/getName.ts b/packages/taikoon-ui/src/lib/ens/getName.ts new file mode 100644 index 0000000000..9c6f0a6717 --- /dev/null +++ b/packages/taikoon-ui/src/lib/ens/getName.ts @@ -0,0 +1,15 @@ +import { getEnsName } from '@wagmi/core'; +import { type GetEnsNameReturnType } from '@wagmi/core'; + +import type { IAddress } from '../../types'; +import getConfig from '../wagmi/getConfig'; + +export default async function getName(address: IAddress): Promise { + const { config, chainId } = getConfig(); + const ensName = (await getEnsName(config, { + address, + chainId, + })) as GetEnsNameReturnType; + if (!ensName) throw new Error('No ENS name'); + return ensName; +} diff --git a/packages/taikoon-ui/src/lib/ens/index.ts b/packages/taikoon-ui/src/lib/ens/index.ts new file mode 100644 index 0000000000..a9caf0b45f --- /dev/null +++ b/packages/taikoon-ui/src/lib/ens/index.ts @@ -0,0 +1,4 @@ +import getAddress from './getAddress'; +import getName from './getName'; + +export { getAddress, getName }; diff --git a/packages/taikoon-ui/src/lib/error/errors.ts b/packages/taikoon-ui/src/lib/error/errors.ts new file mode 100644 index 0000000000..675bf4b9fb --- /dev/null +++ b/packages/taikoon-ui/src/lib/error/errors.ts @@ -0,0 +1,23 @@ +export class NotConnectedError extends Error { + name = 'NotConnectedError'; +} + +export class FailedTransactionError extends Error { + name = 'FailedTransactionError'; +} + +export class MintError extends Error { + name = 'MintError'; +} + +export class FilterLogsError extends Error { + name = 'FilterLogsError'; +} + +export class ConfigError extends Error { + name = 'ConfigError'; +} + +export class IpfsError extends Error { + name = 'IpfsError'; +} diff --git a/packages/taikoon-ui/src/lib/error/index.ts b/packages/taikoon-ui/src/lib/error/index.ts new file mode 100644 index 0000000000..f72bc43e28 --- /dev/null +++ b/packages/taikoon-ui/src/lib/error/index.ts @@ -0,0 +1 @@ +export * from './errors'; diff --git a/packages/taikoon-ui/src/lib/index.ts b/packages/taikoon-ui/src/lib/index.ts new file mode 100644 index 0000000000..856f2b6c38 --- /dev/null +++ b/packages/taikoon-ui/src/lib/index.ts @@ -0,0 +1 @@ +// place files you want to import through the `$lib` alias in this folder. diff --git a/packages/taikoon-ui/src/lib/ipfs/config.ts b/packages/taikoon-ui/src/lib/ipfs/config.ts new file mode 100644 index 0000000000..ce6b37a9aa --- /dev/null +++ b/packages/taikoon-ui/src/lib/ipfs/config.ts @@ -0,0 +1 @@ +export { PUBLIC_IPFS_GATEWAY } from '$env/static/public'; diff --git a/packages/taikoon-ui/src/lib/ipfs/get.ts b/packages/taikoon-ui/src/lib/ipfs/get.ts new file mode 100644 index 0000000000..f43218d706 --- /dev/null +++ b/packages/taikoon-ui/src/lib/ipfs/get.ts @@ -0,0 +1,6 @@ +import { PUBLIC_IPFS_GATEWAY } from './config'; + +export default async function get(hash: string, json?: boolean): Promise { + const response = await fetch(`${PUBLIC_IPFS_GATEWAY}${hash}`); + return json ? response.json() : response.text(); +} diff --git a/packages/taikoon-ui/src/lib/ipfs/getMetadata.ts b/packages/taikoon-ui/src/lib/ipfs/getMetadata.ts new file mode 100644 index 0000000000..a402e91fc8 --- /dev/null +++ b/packages/taikoon-ui/src/lib/ipfs/getMetadata.ts @@ -0,0 +1,25 @@ +import { IpfsError } from '../error'; +import Token from '../token'; +import { PUBLIC_IPFS_GATEWAY } from './config'; +import get from './get'; + +export interface ITokenMetadata { + name: string; + description: string; + image: string; +} +export default async function getMetadata(tokenId: number): Promise { + const tokenURI = await Token.tokenURI(tokenId); + const hash = tokenURI.split('ipfs://').pop(); + if (!hash) throw new IpfsError('Invalid token URI:' + tokenURI); + const metadata = (await get(hash, true)) as ITokenMetadata; + + const imageHash = metadata.image.split('ipfs://').pop(); + + if (!imageHash) throw new IpfsError('Invalid image URI:' + metadata.image); + + return { + ...metadata, + image: `${PUBLIC_IPFS_GATEWAY}${imageHash}`, + }; +} diff --git a/packages/taikoon-ui/src/lib/ipfs/index.ts b/packages/taikoon-ui/src/lib/ipfs/index.ts new file mode 100644 index 0000000000..aaf516e2bb --- /dev/null +++ b/packages/taikoon-ui/src/lib/ipfs/index.ts @@ -0,0 +1,9 @@ +import get from './get'; +import getMetadata from './getMetadata'; + +const IPFS = { + get, + getMetadata, +}; + +export default IPFS; diff --git a/packages/taikoon-ui/src/lib/token/balanceOf.ts b/packages/taikoon-ui/src/lib/token/balanceOf.ts new file mode 100644 index 0000000000..b8a7e0c976 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/balanceOf.ts @@ -0,0 +1,24 @@ +import { readContract } from '@wagmi/core'; + +import { config } from '$wagmi-config'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi/'; +import { web3modal } from '../../lib/connect'; +import type { IAddress, IChainId } from '../../types'; + +export async function balanceOf(address: IAddress): Promise { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return 0; + + const chainId = selectedNetworkId as IChainId; + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'balanceOf', + args: [address], + chainId, + }); + + return parseInt(result.toString()); +} diff --git a/packages/taikoon-ui/src/lib/token/canMint.ts b/packages/taikoon-ui/src/lib/token/canMint.ts new file mode 100644 index 0000000000..b5ad93bd9a --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/canMint.ts @@ -0,0 +1,25 @@ +import { getAccount, readContract } from '@wagmi/core'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi'; +import type { IAddress } from '../../types'; +import { totalWhitelistMintCount } from '../user/totalWhitelistMintCount'; +import getConfig from '../wagmi/getConfig'; + +export async function canMint(): Promise { + const { config, chainId } = getConfig(); + + const account = getAccount(config); + if (!account.address) return false; + const accountAddress = account.address as IAddress; + + const freeMintCount = await totalWhitelistMintCount(); + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'canMint', + args: [accountAddress, BigInt(freeMintCount)], + chainId, + }); + return result as boolean; +} diff --git a/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts b/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts new file mode 100644 index 0000000000..82901bfb61 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/estimateMintGasCost.ts @@ -0,0 +1,32 @@ +import { formatGwei } from 'viem'; + +import getProof from '$lib/whitelist/getProof'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi'; +import type { IChainId } from '../../types'; +import { web3modal } from '../connect'; +import { totalWhitelistMintCount } from '../user/totalWhitelistMintCount'; +import estimateContractGas from '../wagmi/estimateContractGas'; +import { canMint } from './canMint'; + +export async function estimateMintGasCost({ freeMintCount }: { freeMintCount: number }): Promise { + if (freeMintCount === 0) return 0; + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return -1; + const chainId = selectedNetworkId as IChainId; + + const freeMintLeft = await totalWhitelistMintCount(); + + if (await canMint()) { + const proof = getProof(); + + const gasEstimate = await estimateContractGas({ + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'mint', + args: [proof, BigInt(freeMintLeft)], + }); + return parseFloat(formatGwei(gasEstimate)); + } + return 0; +} diff --git a/packages/taikoon-ui/src/lib/token/index.ts b/packages/taikoon-ui/src/lib/token/index.ts new file mode 100644 index 0000000000..c24b9fc310 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/index.ts @@ -0,0 +1,41 @@ +import { zeroAddress } from 'viem'; + +import { taikoonTokenAddress } from '../../generated/abi'; +import { web3modal } from '../../lib/connect'; +import type { IAddress, IChainId } from '../../types'; +import { balanceOf } from './balanceOf'; +import { canMint } from './canMint'; +import { estimateMintGasCost } from './estimateMintGasCost'; +import { maxSupply } from './maxSupply'; +import { mint } from './mint'; +import { name } from './name'; +import { ownerOf } from './ownerOf'; +import { symbol } from './symbol'; +import { tokenOfOwner } from './tokenOfOwner'; +import { tokenURI } from './tokenURI'; +import { totalSupply } from './totalSupply'; + +function address(): IAddress { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return zeroAddress; + + const chainId = selectedNetworkId as IChainId; + return taikoonTokenAddress[chainId]; +} + +const Token = { + symbol, + name, + totalSupply, + tokenURI, + address, + ownerOf, + balanceOf, + canMint, + maxSupply, + mint, + tokenOfOwner, + estimateMintGasCost, +}; + +export default Token; diff --git a/packages/taikoon-ui/src/lib/token/maxSupply.ts b/packages/taikoon-ui/src/lib/token/maxSupply.ts new file mode 100644 index 0000000000..b74234c7ca --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/maxSupply.ts @@ -0,0 +1,17 @@ +import { readContract } from '@wagmi/core'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi'; +import getConfig from '../wagmi/getConfig'; + +export async function maxSupply(): Promise { + const { config, chainId } = getConfig(); + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'maxSupply', + chainId, + }); + + return parseInt(result.toString(16), 16); +} diff --git a/packages/taikoon-ui/src/lib/token/mint.ts b/packages/taikoon-ui/src/lib/token/mint.ts new file mode 100644 index 0000000000..2f88dab488 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/mint.ts @@ -0,0 +1,72 @@ +import { waitForTransactionReceipt, writeContract } from '@wagmi/core'; +import { decodeEventLog } from 'viem'; + +import { FilterLogsError, MintError } from '$lib/error'; +import getProof from '$lib/whitelist/getProof'; +import { config } from '$wagmi-config'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi'; +import { web3modal } from '../../lib/connect'; +import type { IChainId } from '../../types'; +import { totalWhitelistMintCount } from '../user/totalWhitelistMintCount'; +import { canMint } from './canMint'; + +export async function mint({ + freeMintCount, + onTransaction, +}: { + freeMintCount: number; + onTransaction: (tx: string) => void; +}): Promise { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return []; + let tx: any; + const chainId = selectedNetworkId as IChainId; + + const mintCount = await totalWhitelistMintCount(); + + if (freeMintCount > mintCount) { + throw new MintError('Not enough free mints left'); + } + + if (await canMint()) { + const proof = getProof(); + tx = await writeContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'mint', + args: [proof, BigInt(mintCount)], + chainId, + }); + + onTransaction(tx); + } + + let nounId: number = 0; + + const receipt = await waitForTransactionReceipt(config, { hash: tx }); + + const tokenIds: number[] = []; + + receipt.logs.forEach((log: any) => { + try { + const decoded = decodeEventLog({ + abi: taikoonTokenAbi, + data: log.data, + topics: log.topics, + }); + + if (decoded.eventName === 'Transfer') { + const args: { + to: string; + tokenId: bigint; + } = decoded.args as any; + nounId = parseInt(args.tokenId.toString()); + tokenIds.push(nounId); + } + } catch (e: any) { + throw new FilterLogsError(e.message); + } + }); + return tokenIds; +} diff --git a/packages/taikoon-ui/src/lib/token/name.ts b/packages/taikoon-ui/src/lib/token/name.ts new file mode 100644 index 0000000000..554426efbc --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/name.ts @@ -0,0 +1,23 @@ +import { readContract } from '@wagmi/core'; + +import { config } from '$wagmi-config'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi/'; +import { web3modal } from '../../lib/connect'; +import type { IChainId } from '../../types'; + +export async function name(): Promise { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return ''; + + const chainId = selectedNetworkId as IChainId; + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'name', + chainId, + }); + + return result as string; +} diff --git a/packages/taikoon-ui/src/lib/token/ownerOf.ts b/packages/taikoon-ui/src/lib/token/ownerOf.ts new file mode 100644 index 0000000000..cd6f74b49a --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/ownerOf.ts @@ -0,0 +1,25 @@ +import { readContract } from '@wagmi/core'; +import { zeroAddress } from 'viem'; + +import { config } from '$wagmi-config'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi/'; +import { web3modal } from '../../lib/connect'; +import type { IAddress, IChainId } from '../../types'; + +export async function ownerOf(tokenId: number): Promise { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return zeroAddress; + + const chainId = selectedNetworkId as IChainId; + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'ownerOf', + args: [BigInt(tokenId)], + chainId, + }); + + return result as IAddress; +} diff --git a/packages/taikoon-ui/src/lib/token/symbol.ts b/packages/taikoon-ui/src/lib/token/symbol.ts new file mode 100644 index 0000000000..7dbfdbfad4 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/symbol.ts @@ -0,0 +1,23 @@ +import { readContract } from '@wagmi/core'; + +import { config } from '$wagmi-config'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi/'; +import { web3modal } from '../../lib/connect'; +import type { IChainId } from '../../types'; + +export async function symbol(): Promise { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) return ''; + + const chainId = selectedNetworkId as IChainId; + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'symbol', + chainId, + }); + + return result as string; +} diff --git a/packages/taikoon-ui/src/lib/token/tokenOfOwner.ts b/packages/taikoon-ui/src/lib/token/tokenOfOwner.ts new file mode 100644 index 0000000000..a8232bbac9 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/tokenOfOwner.ts @@ -0,0 +1,26 @@ +import { readContract } from '@wagmi/core'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi'; +import getConfig from '../../lib/wagmi/getConfig'; +import type { IAddress } from '../../types'; +import { balanceOf } from './balanceOf'; + +export async function tokenOfOwner(address: IAddress): Promise { + const balance = await balanceOf(address); + + const tokenIds = []; + const { config, chainId } = getConfig(); + + for (const tokenIdx of Array(balance).keys()) { + const tokenIdRaw = (await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'tokenOfOwnerByIndex', + args: [address, BigInt(tokenIdx)], + chainId, + })) as bigint; + tokenIds.push(parseInt(tokenIdRaw.toString())); + } + + return tokenIds; +} diff --git a/packages/taikoon-ui/src/lib/token/tokenURI.ts b/packages/taikoon-ui/src/lib/token/tokenURI.ts new file mode 100644 index 0000000000..92a9da0c10 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/tokenURI.ts @@ -0,0 +1,18 @@ +import { readContract } from '@wagmi/core'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi/'; +import getConfig from '../../lib/wagmi/getConfig'; + +export async function tokenURI(tokenId: number): Promise { + const { config, chainId } = getConfig(); + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'tokenURI', + args: [BigInt(tokenId)], + chainId, + }); + + return result as string; +} diff --git a/packages/taikoon-ui/src/lib/token/totalSupply.ts b/packages/taikoon-ui/src/lib/token/totalSupply.ts new file mode 100644 index 0000000000..2969756b88 --- /dev/null +++ b/packages/taikoon-ui/src/lib/token/totalSupply.ts @@ -0,0 +1,17 @@ +import { readContract } from '@wagmi/core'; + +import { taikoonTokenAbi, taikoonTokenAddress } from '../../generated/abi'; +import getConfig from '../../lib/wagmi/getConfig'; + +export async function totalSupply(): Promise { + const { config, chainId } = getConfig(); + + const result = await readContract(config, { + abi: taikoonTokenAbi, + address: taikoonTokenAddress[chainId], + functionName: 'totalSupply', + chainId, + }); + + return parseInt(result.toString(16), 16); +} diff --git a/packages/taikoon-ui/src/lib/user/index.ts b/packages/taikoon-ui/src/lib/user/index.ts new file mode 100644 index 0000000000..b82916d35d --- /dev/null +++ b/packages/taikoon-ui/src/lib/user/index.ts @@ -0,0 +1,7 @@ +import { totalWhitelistMintCount } from './totalWhitelistMintCount'; + +const User = { + totalWhitelistMintCount, +}; + +export default User; diff --git a/packages/taikoon-ui/src/lib/user/totalWhitelistMintCount.ts b/packages/taikoon-ui/src/lib/user/totalWhitelistMintCount.ts new file mode 100644 index 0000000000..b5b654266d --- /dev/null +++ b/packages/taikoon-ui/src/lib/user/totalWhitelistMintCount.ts @@ -0,0 +1,22 @@ +import { StandardMerkleTree } from '@openzeppelin/merkle-tree'; +import { getAccount } from '@wagmi/core'; + +import getConfig from '../wagmi/getConfig'; +import { whitelist } from '../whitelist'; + +export async function totalWhitelistMintCount(): Promise { + const { config, chainId } = getConfig(); + + const account = getAccount(config); + if (!account.address) return -1; + + const tree = StandardMerkleTree.load(whitelist[chainId]); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + for (const [_, [address, amount]] of tree.entries()) { + if (address.toString().toLowerCase() === account.address.toString().toLowerCase()) { + return amount; + } + } + + return 0; +} diff --git a/packages/taikoon-ui/src/lib/util/Deferred.ts b/packages/taikoon-ui/src/lib/util/Deferred.ts new file mode 100644 index 0000000000..c3d12ab2ff --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/Deferred.ts @@ -0,0 +1,13 @@ +import { noop } from './noop'; +export class Deferred { + public promise: Promise; + public resolve: (value: T | PromiseLike) => void = noop; + public reject: (reason?: unknown) => void = noop; + + constructor() { + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + } +} diff --git a/packages/taikoon-ui/src/lib/util/balance.test.ts b/packages/taikoon-ui/src/lib/util/balance.test.ts new file mode 100644 index 0000000000..7de2ae95d1 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/balance.test.ts @@ -0,0 +1,47 @@ +import { renderBalance, renderEthBalance } from './balance'; + +vi.mock('@wagmi/core'); + +test('renderBalance lib', () => { + expect(renderBalance(null)).toBe('0.00'); + expect( + renderBalance({ + decimals: 18, + formatted: '0', + symbol: 'ETH', + value: BigInt(0), + }), + ).toBe('0 ETH'); + expect( + renderBalance({ + decimals: 18, + formatted: '0.0000001234567', + symbol: 'ETH', + value: BigInt('123456700000'), + }), + ).toBe('0.0000001234567 ETH'); + expect( + renderBalance({ + decimals: 18, + formatted: '1', + symbol: 'ETH', + value: BigInt(1e18), + }), + ).toBe('1 ETH'); + expect( + renderBalance({ + decimals: 18, + formatted: '1.23', + symbol: 'ETH', + value: BigInt(1.23e18), + }), + ).toBe('1.23 ETH'); +}); + +test('renderEthBalance lib', () => { + expect(renderEthBalance(BigInt(0))).toBe('0 ETH'); + expect(renderEthBalance(BigInt(1))).toBe('0.000000 ETH'); + expect(renderEthBalance(BigInt(123456789000))).toBe('0.000000 ETH'); + expect(renderEthBalance(BigInt(1234567890000))).toBe('0.000001 ETH'); + expect(renderEthBalance(BigInt(12345678900000))).toBe('0.000012 ETH'); +}); diff --git a/packages/taikoon-ui/src/lib/util/balance.ts b/packages/taikoon-ui/src/lib/util/balance.ts new file mode 100644 index 0000000000..c3625a2b9e --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/balance.ts @@ -0,0 +1,17 @@ +import { type GetBalanceReturnType } from '@wagmi/core'; +import { formatEther } from 'viem'; + +import { truncateString } from '../../lib/util/truncateString'; + +export function renderBalance(balance: Maybe) { + if (!balance) return '0.00'; + // if (typeof balance === 'bigint') return balance.toString(); + const maxlength = Number(balance.formatted) < 0.000001 ? balance.decimals : 6; + return `${truncateString(balance.formatted, maxlength, '')} ${truncateString(balance.symbol, 7)}`; +} + +export function renderEthBalance(balance: bigint, maxlength = 8): string { + return `${truncateString(formatEther(balance).toString(), maxlength, '')} ETH`; +} + +export const refreshUserBalance = async () => {}; diff --git a/packages/taikoon-ui/src/lib/util/checkForAdblock.ts b/packages/taikoon-ui/src/lib/util/checkForAdblock.ts new file mode 100644 index 0000000000..ebe1b77ebb --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/checkForAdblock.ts @@ -0,0 +1,19 @@ +// Function to check if the bait element has been hidden or removed by an adblocker +export const checkForAdblocker = async (urlToTest: string): Promise => { + return new Promise((resolve) => { + const bait = document.createElement('script'); + bait.src = urlToTest; + bait.type = 'text/javascript'; + bait.onerror = () => { + // Script failed to load, likely due to an adblocker + resolve(true); + }; + bait.onload = () => { + // Script loaded successfully, likely no adblocker + resolve(false); + }; + document.body.appendChild(bait); + // Ensure the bait element is removed from the DOM afterwards + bait.remove(); + }); +}; diff --git a/packages/taikoon-ui/src/lib/util/checkForPausedContracts.test.ts b/packages/taikoon-ui/src/lib/util/checkForPausedContracts.test.ts new file mode 100644 index 0000000000..0ee1ab6764 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/checkForPausedContracts.test.ts @@ -0,0 +1,83 @@ +import { readContract } from '@wagmi/core'; +import { get } from 'svelte/store'; + +import { bridgePausedModal } from '$stores/modal'; + +import { checkForPausedContracts } from './checkForPausedContracts'; + +vi.mock('@wagmi/core'); +vi.mock('viem'); + +vi.mock('$bridgeConfig', () => ({ + routingContractsMap: { + 1: { + 2: { + erc20VaultAddress: '0x00001', + bridgeAddress: '0x00002', + erc721VaultAddress: '0x00003', + erc1155VaultAddress: '0x00004', + crossChainSyncAddress: '0x00005', + signalServiceAddress: '0x00006', + }, + }, + 2: { + 1: { + erc20VaultAddress: '0x00007', + bridgeAddress: '0x00008', + erc721VaultAddress: '0x00009', + erc1155VaultAddress: '0x00010', + crossChainSyncAddress: '0x00011', + signalServiceAddress: '0x00012', + }, + }, + 3: { + 2: { + erc20VaultAddress: '0x00007', + bridgeAddress: '0x00008', + erc721VaultAddress: '0x00009', + erc1155VaultAddress: '0x00010', + crossChainSyncAddress: '0x00011', + signalServiceAddress: '0x00012', + }, + }, + }, +})); + +describe('checkForPausedContracts', () => { + beforeEach(() => { + vi.resetAllMocks(); + }); + + test('should return false if no contracts are paused', async () => { + // when + await checkForPausedContracts(); + + // then + expect(readContract).toHaveBeenCalledTimes(3); + expect(get(bridgePausedModal)).toBe(false); + }); + + test('should return true if at least one contract is paused', async () => { + // given + vi.mocked(readContract).mockResolvedValueOnce(true); + + // when + await checkForPausedContracts(); + + // then + expect(readContract).toHaveBeenCalledTimes(3); + expect(get(bridgePausedModal)).toBe(true); + }); + + test('should handle errors', async () => { + // given + vi.mocked(readContract).mockRejectedValueOnce(new Error('some error')); + + // when + await checkForPausedContracts(); + + // then + expect(get(bridgePausedModal)).toBe(true); + expect(readContract).toHaveBeenCalledTimes(3); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/checkForPausedContracts.ts b/packages/taikoon-ui/src/lib/util/checkForPausedContracts.ts new file mode 100644 index 0000000000..8451e79ce5 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/checkForPausedContracts.ts @@ -0,0 +1,7 @@ +export const isBridgePaused = async () => { + return await checkForPausedContracts(); +}; + +export const checkForPausedContracts = async () => { + return true; +}; diff --git a/packages/taikoon-ui/src/lib/util/classNames.test.ts b/packages/taikoon-ui/src/lib/util/classNames.test.ts new file mode 100644 index 0000000000..7c8e2a3178 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/classNames.test.ts @@ -0,0 +1,8 @@ +import { classNames } from './classNames'; + +test('classNames lib', () => { + expect(classNames('class1', 'class2 class3')).toBe('class1 class2 class3'); + expect(classNames('class1', 'class2', null)).toBe('class1 class2'); + expect(classNames('class1', 'class2', undefined)).toBe('class1 class2'); + expect(classNames('class1', null, 'class3', '', 'class5')).toBe('class1 class3 class5'); +}); diff --git a/packages/taikoon-ui/src/lib/util/classNames.ts b/packages/taikoon-ui/src/lib/util/classNames.ts new file mode 100644 index 0000000000..4a60c3b72b --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/classNames.ts @@ -0,0 +1,3 @@ +export function classNames(...classes: Array>) { + return classes.filter(Boolean).join(' '); +} diff --git a/packages/taikoon-ui/src/lib/util/debounce.ts b/packages/taikoon-ui/src/lib/util/debounce.ts new file mode 100644 index 0000000000..75cdc86273 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/debounce.ts @@ -0,0 +1,14 @@ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function debounce ReturnType>( + callback: T, + timeout: number, +): (...args: Parameters) => void { + let timer: ReturnType; + + return (...args: Parameters) => { + clearTimeout(timer); + timer = setTimeout(() => { + callback(...args); + }, timeout); + }; +} diff --git a/packages/taikoon-ui/src/lib/util/extractIPFSCidFromUrl.ts b/packages/taikoon-ui/src/lib/util/extractIPFSCidFromUrl.ts new file mode 100644 index 0000000000..38d1e29319 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/extractIPFSCidFromUrl.ts @@ -0,0 +1,7 @@ +export const extractIPFSCidFromUrl = (url: string): { cid: string | null } => { + // Adapting the provided regex to match the URL structure + const regex = + /\/(Qm[1-9A-HJ-NP-Za-km-z]{44,}|b[A-Za-z2-7]{58,}|B[A-Z2-7]{58,}|z[1-9A-HJ-NP-Za-km-z]{48,}|F[0-9A-F]{50,})(\/(\d|\w|\.)+)*/; + const match = url.match(regex); + return match ? { cid: match[1] } : { cid: null }; +}; diff --git a/packages/taikoon-ui/src/lib/util/fetchTransactionReceipt.ts b/packages/taikoon-ui/src/lib/util/fetchTransactionReceipt.ts new file mode 100644 index 0000000000..5a9edcd4ae --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/fetchTransactionReceipt.ts @@ -0,0 +1,31 @@ +import type { Hash } from 'viem'; + +import { chains } from '$libs/chain'; + +export async function fetchTransactionReceipt(transactionHash: Hash, chainId: number) { + try { + const nodeUrl = chains.find((c) => c.id === chainId)?.rpcUrls?.default?.http[0]; + if (!nodeUrl) { + throw new Error('Node URL not found'); + } + + const response = await fetch(nodeUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'eth_getTransactionReceipt', + params: [transactionHash], + id: 1, + }), + }); + + const data = await response.json(); + return data.result; + } catch (error) { + console.error('Error fetching transaction receipt:', error); + throw error; + } +} diff --git a/packages/taikoon-ui/src/lib/util/formatDate.ts b/packages/taikoon-ui/src/lib/util/formatDate.ts new file mode 100644 index 0000000000..7b581213de --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/formatDate.ts @@ -0,0 +1,10 @@ +export default function formatDate(date: Date): string { + const year = date.getFullYear(); + const month = ('0' + (date.getMonth() + 1)).slice(-2); + const day = ('0' + date.getDate()).slice(-2); + const hours = ('0' + date.getHours()).slice(-2); + const minutes = ('0' + date.getMinutes()).slice(-2); + const seconds = ('0' + date.getSeconds()).slice(-2); + + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} diff --git a/packages/taikoon-ui/src/lib/util/getConnectedWallet.test.ts b/packages/taikoon-ui/src/lib/util/getConnectedWallet.test.ts new file mode 100644 index 0000000000..f42cda0f29 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/getConnectedWallet.test.ts @@ -0,0 +1,5 @@ +describe('getConnectedWallet', () => { + it('TODO', () => { + expect(true).toBeTruthy(); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/getConnectedWallet.ts b/packages/taikoon-ui/src/lib/util/getConnectedWallet.ts new file mode 100644 index 0000000000..3f042f9acb --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/getConnectedWallet.ts @@ -0,0 +1,14 @@ +import { getWalletClient } from '@wagmi/core'; + +import { NotConnectedError } from '$libs/error'; +import { config } from '$libs/wagmi'; + +export async function getConnectedWallet(chainId?: number) { + const walletClient = await getWalletClient(config, { chainId }); + + if (!walletClient) { + throw new NotConnectedError('wallet is not connected'); + } + + return walletClient; +} diff --git a/packages/taikoon-ui/src/lib/util/getFileExtension.ts b/packages/taikoon-ui/src/lib/util/getFileExtension.ts new file mode 100644 index 0000000000..d9beabfe8a --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/getFileExtension.ts @@ -0,0 +1,4 @@ +export function getFileExtension(filename: string): string { + const parts: string[] = filename.split('.'); + return parts.length > 1 ? parts[parts.length - 1] : ''; +} diff --git a/packages/taikoon-ui/src/lib/util/groupNFTByCollection.ts b/packages/taikoon-ui/src/lib/util/groupNFTByCollection.ts new file mode 100644 index 0000000000..bf873aeab6 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/groupNFTByCollection.ts @@ -0,0 +1,13 @@ +import type { NFT } from '../token/types'; + +export function groupNFTByCollection(nfts: NFT[]): Record { + const grouped: Record = {}; + nfts.forEach((nft) => { + const addressKey = Object.values(nft.addresses).join('-'); + if (!grouped[addressKey]) { + grouped[addressKey] = []; + } + grouped[addressKey].push(nft); + }); + return grouped; +} diff --git a/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.test.ts b/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.test.ts new file mode 100644 index 0000000000..7dd57bb582 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.test.ts @@ -0,0 +1,18 @@ +import { jsonParseWithDefault } from './jsonParseWithDefault'; + +describe('jsonToArray', () => { + it('should return default value when input is null or empty string', () => { + expect(jsonParseWithDefault(null, [])).toEqual([]); + expect(jsonParseWithDefault('', 5)).toEqual(5); + }); + + it('should return default value when input is not a valid JSON', () => { + expect(jsonParseWithDefault(undefined, true)).toEqual(true); + expect(jsonParseWithDefault('not a valid JSON', '')).toEqual(''); + }); + + it('should return parsed JSON when input is a valid JSON', () => { + const strJson = '{"person": "Fran", "age": "Unknown"}'; + expect(jsonParseWithDefault(strJson, null)).toEqual(JSON.parse(strJson)); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.ts b/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.ts new file mode 100644 index 0000000000..69acdcd867 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/jsonParseWithDefault.ts @@ -0,0 +1,9 @@ +export function jsonParseWithDefault(strJson: Maybe, defaultValue: T): T { + try { + // Keep in mind that strJson could be null or empty string + // JSON.parse would not throw an error in those cases + return strJson ? JSON.parse(strJson) : defaultValue; + } catch (e) { + return defaultValue; + } +} diff --git a/packages/taikoon-ui/src/lib/util/logger.ts b/packages/taikoon-ui/src/lib/util/logger.ts new file mode 100644 index 0000000000..204f4ae8ed --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/logger.ts @@ -0,0 +1,5 @@ +import debug from 'debug'; + +export function getLogger(namespace: string) { + return debug(`nft-lab:${namespace}`); +} diff --git a/packages/taikoon-ui/src/lib/util/mergeTransactions.test.ts b/packages/taikoon-ui/src/lib/util/mergeTransactions.test.ts new file mode 100644 index 0000000000..f6d2b4130a --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/mergeTransactions.test.ts @@ -0,0 +1,162 @@ +import type { Address, Hex } from 'viem'; + +import { type BridgeTransaction, MessageStatus } from '$libs/bridge'; +import type { TokenType } from '$libs/token'; +import { mergeAndCaptureOutdatedTransactions } from '$libs/util/mergeTransactions'; + +function setupMocks() { + vi.mock('@wagmi/core'); + vi.mock('@web3modal/wagmi'); + vi.mock('$customToken', () => { + return { + customToken: [ + { + name: 'Bull Token', + addresses: { + '31336': '0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0', + '167002': '0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE', + }, + symbol: 'BLL', + decimals: 18, + type: 'ERC20', + logoURI: 'ipfs://QmezMTpT6ovJ3szb3SKDM9GVGeQ1R8DfjYyXG12ppMe2BY', + mintable: true, + }, + { + name: 'Horse Token', + addresses: { + '31336': '0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e', + '167002': '0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1', + }, + symbol: 'HORSE', + decimals: 18, + type: 'ERC20', + logoURI: 'ipfs://QmU52ZxmSiGX24uDPNUGG3URyZr5aQdLpACCiD6tap4Mgc', + mintable: true, + }, + ], + }; + }); +} + +describe('mergeUniqueTransactions', () => { + beforeEach(() => { + setupMocks(); + }); + + // Given + const localTxs: BridgeTransaction[] = [ + { + hash: 'hash1' as Hex, + from: 'address1' as Address, + amount: BigInt(1000), + symbol: 'symbol1', + decimals: 2, + srcChainId: BigInt(1), + destChainId: BigInt(2), + status: MessageStatus.DONE, + msgHash: 'msg1' as Hex, + receipt: undefined, + tokenType: 'ERC20' as TokenType, + }, + { + hash: 'hash2' as Hex, + from: 'address2' as Address, + amount: BigInt(2000), + symbol: 'symbol2', + decimals: 2, + srcChainId: BigInt(1), + destChainId: BigInt(2), + status: MessageStatus.DONE, + msgHash: 'msg2' as Hex, + receipt: undefined, + tokenType: 'ERC20' as TokenType, + }, + ]; + + const relayerTx: BridgeTransaction[] = [ + { + hash: 'hash3' as Hex, + from: 'address3' as Address, + amount: BigInt(3000), + symbol: 'symbol3', + decimals: 2, + srcChainId: BigInt(1), + destChainId: BigInt(2), + status: MessageStatus.DONE, + msgHash: 'msg3' as Hex, + receipt: undefined, + tokenType: 'ERC20' as TokenType, + }, + { + hash: 'hash4' as Hex, + from: 'address4' as Address, + amount: BigInt(4000), + symbol: 'symbol4', + decimals: 2, + srcChainId: BigInt(1), + destChainId: BigInt(2), + status: MessageStatus.DONE, + msgHash: 'msg4' as Hex, + receipt: undefined, + tokenType: 'ERC20' as TokenType, + }, + ]; + + it('should merge transactions when no outdated local ones', () => { + // When + const result = mergeAndCaptureOutdatedTransactions(localTxs, relayerTx); + + // Then + expect(extractHashes(result.mergedTransactions)).toEqual(extractHashes([...localTxs, ...relayerTx])); + expect(result.outdatedLocalTransactions).toEqual([]); + }); + + it('should identify and capture outdated local transactions', () => { + // Given + const outdatedTx = relayerTx[0]; + const localWithOutdated = [...localTxs, outdatedTx]; + + // When + const result = mergeAndCaptureOutdatedTransactions(localWithOutdated, relayerTx); + + // Then + expect(extractHashes(result.mergedTransactions)).toEqual(extractHashes([...localTxs, ...relayerTx])); + expect(result.outdatedLocalTransactions).toEqual([outdatedTx]); + }); + + it('should merge transactions and capture outdated ones, complex', () => { + // Given + + const localWithOutdated = [ + ...localTxs, + { + hash: 'hash3' as Hex, + from: 'address2' as Address, + amount: BigInt(2000), + symbol: 'symbol2', + decimals: 2, + srcChainId: BigInt(1), + destChainId: BigInt(2), + status: MessageStatus.DONE, + msgHash: 'msg2' as Hex, + receipt: undefined, + tokenType: 'ERC20' as TokenType, + }, + ]; + + const expectedMergedHashes = extractHashes([...localTxs, ...relayerTx]); + const expectedOutdatedHashes = ['hash3' as Hex]; + + // When + const result = mergeAndCaptureOutdatedTransactions(localWithOutdated, relayerTx); + + // Then + expect(extractHashes(result.mergedTransactions)).toEqual(expectedMergedHashes); + expect(extractHashes(result.outdatedLocalTransactions)).toEqual(expectedOutdatedHashes); + }); +}); + +function extractHashes(transactions: BridgeTransaction[]): Hex[] { + return transactions.map((tx) => tx.hash); +} diff --git a/packages/taikoon-ui/src/lib/util/mergeTransactions.ts b/packages/taikoon-ui/src/lib/util/mergeTransactions.ts new file mode 100644 index 0000000000..42805471ed --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/mergeTransactions.ts @@ -0,0 +1,31 @@ +import type { BridgeTransaction } from '$libs/bridge'; + +type MergeResult = { + mergedTransactions: BridgeTransaction[]; + outdatedLocalTransactions: BridgeTransaction[]; +}; + +export const mergeAndCaptureOutdatedTransactions = ( + localTxs: BridgeTransaction[], + relayerTx: BridgeTransaction[], +): MergeResult => { + const relayerTxMap: Map = new Map(); + relayerTx.forEach((tx) => relayerTxMap.set(tx.hash, tx)); + + const outdatedLocalTransactions: BridgeTransaction[] = []; + const mergedTransactions: BridgeTransaction[] = []; + + for (const tx of localTxs) { + if (!relayerTxMap.has(tx.hash)) { + mergedTransactions.push(tx); + } else { + outdatedLocalTransactions.push(tx); + } + } + + for (const tx of relayerTx) { + mergedTransactions.push(tx); + } + + return { mergedTransactions, outdatedLocalTransactions }; +}; diff --git a/packages/taikoon-ui/src/lib/util/nextTick.ts b/packages/taikoon-ui/src/lib/util/nextTick.ts new file mode 100644 index 0000000000..ae1dee0b66 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/nextTick.ts @@ -0,0 +1,3 @@ +export function nextTick(fn: () => void) { + Promise.resolve().then(fn); +} diff --git a/packages/taikoon-ui/src/lib/util/noop.ts b/packages/taikoon-ui/src/lib/util/noop.ts new file mode 100644 index 0000000000..4b1407a802 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/noop.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line @typescript-eslint/no-empty-function +export const noop = () => {}; diff --git a/packages/taikoon-ui/src/lib/util/parseNFTMetadata.ts b/packages/taikoon-ui/src/lib/util/parseNFTMetadata.ts new file mode 100644 index 0000000000..21cf5fcfc5 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/parseNFTMetadata.ts @@ -0,0 +1,97 @@ +import axios, { AxiosError, type AxiosResponse } from 'axios'; + +import { apiService } from '$config'; +import { type NFT, type NFTMetadata, TokenType } from '$libs/token'; +import { safeParseUrl } from '$libs/util/safeParseUrl'; + +import { checkForAdblocker } from './checkForAdblock'; +import { extractIPFSCidFromUrl } from './extractIPFSCidFromUrl'; +import { getLogger } from './logger'; + +const log = getLogger('libs:token:parseNFTMetadata'); + +export const parseNFTMetadata = async (token: NFT): Promise => { + if (token.type !== TokenType.ERC721 && token.type !== TokenType.ERC1155) throw new Error('Not a NFT'); + + log(`fetching metadata for ${token.name} id: ${token.tokenId}`); + + if (!token.uri) throw new Error('No token URI found'); + + if (token.uri.includes('{id}')) { + token.uri = token.uri.replace('{id}', token.tokenId.toString()); + } + + const url = safeParseUrl(token.uri); + if (!url) throw new Error(`Invalid token URI: ${token.uri}`); + + let json; + + try { + json = await axios.get(url, { timeout: apiService.timeout }); + } catch (err) { + const error = err as AxiosError; + log(`error fetching metadata for ${token.name} id: ${token.tokenId}`, error); + //todo: handle different error scenarios? + json = await retry(url, token.tokenId); + } + if (!json) { + const isBlocked = await checkForAdblocker(url); + if (isBlocked) { + log(`The resource at ${url} is blocked by an adblocker`); + json = await retry(url, token.tokenId); + } else { + throw new Error(`No metadata found for ${token.name} id: ${token.tokenId}`); + } + } + + if (!json || json instanceof Error) { + // Handle error + throw new Error(`No metadata found for ${token.name} id: ${token.tokenId}`); + } + const metadata = { + description: json.data.description || '', + external_url: json.data.external_url || '', + image: json.data.image || '', + name: json.data.name || '', + }; + + log(`fetched metadata for ${token.name} id: ${token.tokenId}`, metadata); + return metadata; +}; + +// TODO: we could retry several times with different gateways +const retry = async (url: string, tokenId: number): Promise => { + let newUrl; + tokenId !== undefined && tokenId !== null ? (newUrl = useGateway(url, tokenId)) : (newUrl = useGateway(url, tokenId)); + if (newUrl) { + const result = await retryRequest(newUrl); + if (result instanceof Error) { + return result; + } + return result; + } + return new Error(`No metadata found for ${url}`); +}; + +const retryRequest = async (newUrl: string): Promise => { + try { + log(`retrying with ${newUrl}`); + return await axios.get(newUrl); + } catch (error) { + log('retrying failed', error); + throw new Error(`No metadata found for ${newUrl}`); + } +}; + +//TODO: make this configurable via the config system? +const useGateway = (url: string, tokenId: number) => { + const { cid } = extractIPFSCidFromUrl(url); + let gateway: string; + if (tokenId !== undefined && tokenId !== null && cid) { + gateway = `https://ipfs.io/ipfs/${cid}/${tokenId}.json`; + } else { + log(`no valid CID found in ${url}`); + return null; + } + return gateway; +}; diff --git a/packages/taikoon-ui/src/lib/util/parseToWei.ts b/packages/taikoon-ui/src/lib/util/parseToWei.ts new file mode 100644 index 0000000000..68795e4e4a --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/parseToWei.ts @@ -0,0 +1,5 @@ +import { parseUnits } from 'viem'; + +export function parseToWei(strEther?: string) { + return parseUnits(strEther ?? '0', 18); +} diff --git a/packages/taikoon-ui/src/lib/util/positionElementByTarget.test.ts b/packages/taikoon-ui/src/lib/util/positionElementByTarget.test.ts new file mode 100644 index 0000000000..2943c66749 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/positionElementByTarget.test.ts @@ -0,0 +1,60 @@ +import { positionElementByTarget } from './positionElementByTarget'; + +const targetElement = { + offsetHeight: 10, + offsetWidth: 10, +} as HTMLElement; + +const elementToPosition = { + style: { + top: '', + bottom: '', + left: '', + right: '', + transform: '', + }, + offsetHeight: 100, + offsetWidth: 100, +} as HTMLElement; + +describe('positionElementByTarget', () => { + it('should position element to the top', () => { + positionElementByTarget(elementToPosition, targetElement, 'top', 15); + + expect(elementToPosition.style.top).toBe(''); + expect(elementToPosition.style.bottom).toBe('25px'); // 10 + 15 + expect(elementToPosition.style.left).toBe('50%'); + expect(elementToPosition.style.right).toBe(''); + expect(elementToPosition.style.transform).toBe('translateX(-50%)'); + }); + + it('should position element to the bottom', () => { + positionElementByTarget(elementToPosition, targetElement, 'bottom', 20); + + expect(elementToPosition.style.top).toBe('30px'); // 10 + 20 + expect(elementToPosition.style.bottom).toBe(''); + expect(elementToPosition.style.left).toBe('50%'); + expect(elementToPosition.style.right).toBe(''); + expect(elementToPosition.style.transform).toBe('translateX(-50%)'); + }); + + it('should position element to the left', () => { + positionElementByTarget(elementToPosition, targetElement, 'left', 25); + + expect(elementToPosition.style.top).toBe('50%'); + expect(elementToPosition.style.bottom).toBe(''); + expect(elementToPosition.style.left).toBe('auto'); + expect(elementToPosition.style.right).toBe('35px'); // 10 + 25 + expect(elementToPosition.style.transform).toBe('translateY(-50%)'); + }); + + it('should position element to the right', () => { + positionElementByTarget(elementToPosition, targetElement, 'right', 30); + + expect(elementToPosition.style.top).toBe('50%'); + expect(elementToPosition.style.bottom).toBe(''); + expect(elementToPosition.style.left).toBe('40px'); // 10 + 30 + expect(elementToPosition.style.right).toBe('auto'); + expect(elementToPosition.style.transform).toBe('translateY(-50%)'); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/positionElementByTarget.ts b/packages/taikoon-ui/src/lib/util/positionElementByTarget.ts new file mode 100644 index 0000000000..d61bbea5ff --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/positionElementByTarget.ts @@ -0,0 +1,45 @@ +// TODO: add support for other positions: 'top-left', 'bottom-right', etc... +export function positionElementByTarget( + elementToPosition: HTMLElement, + targetElement: HTMLElement, + position: Position = 'top', + gap = 10, +) { + const { style } = elementToPosition; + + // Reset styles. + style.top = ''; + style.bottom = ''; + style.left = ''; + style.right = ''; + style.transform = ''; + + switch (position) { + case 'top': + case 'top-right': + case 'top-left': + style.bottom = `${targetElement.offsetHeight + gap}px`; + style.left = '50%'; + style.transform = 'translateX(-50%)'; + break; + case 'bottom': + case 'bottom-right': + case 'bottom-left': + style.top = `${targetElement.offsetHeight + gap}px`; + style.left = '50%'; + style.transform = 'translateX(-50%)'; + break; + case 'left': + style.left = 'auto'; + style.right = `${targetElement.offsetWidth + gap}px`; + style.top = '50%'; + style.transform = 'translateY(-50%)'; + break; + case 'right': + style.right = 'auto'; + style.left = `${targetElement.offsetWidth + gap}px`; + style.top = '50%'; + style.transform = 'translateY(-50%)'; + break; + } +} diff --git a/packages/taikoon-ui/src/lib/util/resolveIPFSUri.ts b/packages/taikoon-ui/src/lib/util/resolveIPFSUri.ts new file mode 100644 index 0000000000..d1c72c5c14 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/resolveIPFSUri.ts @@ -0,0 +1,31 @@ +import axios, { type AxiosRequestConfig } from 'axios'; + +import { ipfsConfig } from '$config'; +import { PUBLIC_IPFS_GATEWAYS } from '$env/static/public'; +import { ConfigError, IpfsError } from '$libs/error'; + +const gateways = PUBLIC_IPFS_GATEWAYS.split(',') || []; + +const axiosConfig: AxiosRequestConfig = { + timeout: ipfsConfig.gatewayTimeout, +}; + +export async function resolveIPFSUri(uri: string): Promise { + const cid = uri.replace('ipfs://', ''); + let elapsedTime = 0; + if (gateways.length === 0) throw new ConfigError('No IPFS gateways configured'); + for (const gateway of gateways) { + const start = Date.now(); + try { + const url = `${gateway}/ipfs/${cid}`; + await axios.head(url, axiosConfig); + return url; // Return the first successful gateway URL + } catch (error) { + elapsedTime += Date.now() - start; + if (elapsedTime > ipfsConfig.overallTimeout) { + break; + } + } + } + throw new IpfsError('Failed to retrieve metadata from IPFS gateways'); +} diff --git a/packages/taikoon-ui/src/lib/util/safeParseUrl.ts b/packages/taikoon-ui/src/lib/util/safeParseUrl.ts new file mode 100644 index 0000000000..006059af8d --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/safeParseUrl.ts @@ -0,0 +1,11 @@ +export const safeParseUrl = (uri: string) => { + const IPFS_PREFIX = 'ipfs://'; + + if (uri && uri.startsWith(IPFS_PREFIX)) { + // todo: multiple configurable ipfs gateways as fallback + const ipfsPath = uri.replace(IPFS_PREFIX, ''); + return `https://ipfs.io/ipfs/${ipfsPath}`; + } + + return uri; +}; diff --git a/packages/taikoon-ui/src/lib/util/safeReadContract.test.ts b/packages/taikoon-ui/src/lib/util/safeReadContract.test.ts new file mode 100644 index 0000000000..85df57956c --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/safeReadContract.test.ts @@ -0,0 +1,35 @@ +import { readContract } from '@wagmi/core'; +import { zeroAddress } from 'viem'; + +import { safeReadContract } from './safeReadContract'; + +vi.mock('@wagmi/core'); + +describe('safeReadContract', () => { + it('should return contract data on success', async () => { + const mockData = { data: 'mockData' }; + vi.mocked(readContract).mockResolvedValue(mockData); + + const result = await safeReadContract({ + address: zeroAddress, + abi: [], + functionName: 'functionName', + chainId: 1, + }); + + expect(result).toEqual(mockData); + }); + + it('should return null on failure', async () => { + vi.mocked(readContract).mockRejectedValue(new Error('mockError')); + + const result = await safeReadContract({ + address: zeroAddress, + abi: [], + functionName: 'functionName', + chainId: 1, + }); + + expect(result).toBeNull(); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/safeReadContract.ts b/packages/taikoon-ui/src/lib/util/safeReadContract.ts new file mode 100644 index 0000000000..072c97c778 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/safeReadContract.ts @@ -0,0 +1,29 @@ +import { readContract } from '@wagmi/core'; +import type { Abi, Address } from 'viem'; + +import { config } from '$libs/wagmi'; + +import { getLogger } from './logger'; + +const log = getLogger('libs:util:safeReadContract'); + +type ReadContractParams = { + address: Address; + abi: Abi; + functionName: string; + args?: unknown[]; + chainId: number; +}; + +/* + * Safely read a contract, returning null if it fails + * useful when trying to access a non standard, non mandatory function + */ +export async function safeReadContract(params: ReadContractParams): Promise { + try { + return await readContract(config, params); + } catch (error) { + log(`Safely failed to read contract: ${error}`); + return null; + } +} diff --git a/packages/taikoon-ui/src/lib/util/shortenAddress.test.ts b/packages/taikoon-ui/src/lib/util/shortenAddress.test.ts new file mode 100644 index 0000000000..e7181058e5 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/shortenAddress.test.ts @@ -0,0 +1,12 @@ +import { shortenAddress } from './shortenAddress'; + +it('should return string with prefix and suffix', () => { + const dummyAddress = '0x63FaC9201494f0bd17B9892B9fae4d52fe3BD377'; + + expect(shortenAddress(dummyAddress)).toStrictEqual('0x63Fa…D377'); + expect(shortenAddress(dummyAddress, 10, 10)).toStrictEqual('0x63FaC920…52fe3BD377'); +}); + +it('should return 0x if empty', () => { + expect(shortenAddress('')).toBe('0x'); +}); diff --git a/packages/taikoon-ui/src/lib/util/shortenAddress.ts b/packages/taikoon-ui/src/lib/util/shortenAddress.ts new file mode 100644 index 0000000000..d30beb3f36 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/shortenAddress.ts @@ -0,0 +1,24 @@ +import type { IAddress } from '../../types'; +import { web3modal } from '../connect'; +import { getName } from '../ens'; + +export async function shortenAddress(address: IAddress, charsStart = 6, charsEnd = 4, sep = '…'): Promise { + if (!address) return '0x'; + const shortened = [address.slice(0, charsStart), address.slice(-charsEnd)].join(sep); + + try { + const { selectedNetworkId } = web3modal.getState(); + if (!selectedNetworkId) { + return shortened; + } + + const name = await getName(address); + if (name) { + return name; + } + } catch (e) { + console.warn(e); + } + + return shortened; +} diff --git a/packages/taikoon-ui/src/lib/util/truncateDecimal.test.ts b/packages/taikoon-ui/src/lib/util/truncateDecimal.test.ts new file mode 100644 index 0000000000..4b5bcf09f0 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/truncateDecimal.test.ts @@ -0,0 +1,9 @@ +import { truncateDecimal } from './truncateDecimal'; + +describe('truncateDecimal', () => { + it('should truncate decimals', () => { + expect(truncateDecimal(1.23456789, 2)).toEqual(1.23); + expect(truncateDecimal(12.3456789, 3)).toEqual(12.345); + expect(truncateDecimal(123.456789, 4)).toEqual(123.4567); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/truncateDecimal.ts b/packages/taikoon-ui/src/lib/util/truncateDecimal.ts new file mode 100644 index 0000000000..bd3391864c --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/truncateDecimal.ts @@ -0,0 +1,4 @@ +export function truncateDecimal(num: number, decimalPlaces: number) { + const factor = 10 ** decimalPlaces; + return Math.floor(num * factor) / factor; +} diff --git a/packages/taikoon-ui/src/lib/util/truncateString.test.ts b/packages/taikoon-ui/src/lib/util/truncateString.test.ts new file mode 100644 index 0000000000..2f8bf9db5c --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/truncateString.test.ts @@ -0,0 +1,9 @@ +import { truncateString } from './truncateString'; + +describe('truncateString', () => { + it('should truncate strings', () => { + expect(truncateString('123456789', 3)).toEqual('123…'); + expect(truncateString('123456789', 5)).toEqual('12345…'); + expect(truncateString('123456789', 6, '...')).toEqual('123456...'); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/truncateString.ts b/packages/taikoon-ui/src/lib/util/truncateString.ts new file mode 100644 index 0000000000..266795e21d --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/truncateString.ts @@ -0,0 +1,3 @@ +export function truncateString(str: string, maxlength: number, strBoundary = '…') { + return str.length > maxlength ? `${str.substring(0, maxlength)}${strBoundary}` : str; +} diff --git a/packages/taikoon-ui/src/lib/util/uid.test.ts b/packages/taikoon-ui/src/lib/util/uid.test.ts new file mode 100644 index 0000000000..44ee4aa327 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/uid.test.ts @@ -0,0 +1,14 @@ +import { uid } from './uid'; + +describe('uid', () => { + it('should always return a unique id', () => { + const generatedIds = new Set(); + + // Is this unique enough? 😅 + for (let i = 0; i < 1000; i++) { + generatedIds.add(uid()); + } + + expect(generatedIds.size).toBe(1000); + }); +}); diff --git a/packages/taikoon-ui/src/lib/util/uid.ts b/packages/taikoon-ui/src/lib/util/uid.ts new file mode 100644 index 0000000000..62cb3175f1 --- /dev/null +++ b/packages/taikoon-ui/src/lib/util/uid.ts @@ -0,0 +1,3 @@ +export function uid() { + return Math.floor(Math.random() * Date.now()).toString(16); +} diff --git a/packages/taikoon-ui/src/lib/wagmi/estimateContractGas.ts b/packages/taikoon-ui/src/lib/wagmi/estimateContractGas.ts new file mode 100644 index 0000000000..3f71cd904f --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/estimateContractGas.ts @@ -0,0 +1,11 @@ +import { getConnectorClient } from '@wagmi/core'; +import { estimateContractGas as viemEstimateContractGas } from 'viem/actions'; + +import getConfig from './getConfig'; + +export default async function estimateContractGas(params: Parameters[1]) { + const { config } = getConfig(); + const client = await getConnectorClient(config); + + return await viemEstimateContractGas(client, params); +} diff --git a/packages/taikoon-ui/src/lib/wagmi/getBalance.ts b/packages/taikoon-ui/src/lib/wagmi/getBalance.ts new file mode 100644 index 0000000000..14c35490e6 --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/getBalance.ts @@ -0,0 +1,14 @@ +import { getBalance as wagmiGetBalance } from '@wagmi/core'; +import { type GetBalanceReturnType } from '@wagmi/core'; + +import type { IAddress } from '../../types'; +import getConfig from './getConfig'; + +export default async function getBalance(address: IAddress): Promise { + const { config, chainId } = getConfig(); + const balance = (await wagmiGetBalance(config, { + address, + chainId, + })) as GetBalanceReturnType; + return balance.value; +} diff --git a/packages/taikoon-ui/src/lib/wagmi/getConfig.ts b/packages/taikoon-ui/src/lib/wagmi/getConfig.ts new file mode 100644 index 0000000000..6456e27b89 --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/getConfig.ts @@ -0,0 +1,18 @@ +import { holesky } from '@wagmi/core/chains'; + +import { config, publicConfig } from '$wagmi-config'; + +import type { IChainId } from '../../types'; +import { web3modal } from '../connect'; + +export default function getConfig() { + const { selectedNetworkId } = web3modal.getState(); + const wagmiConfig = selectedNetworkId ? config : publicConfig; + + const chainId = selectedNetworkId ? selectedNetworkId : holesky.id; + + return { + config: wagmiConfig, + chainId: chainId as IChainId, + }; +} diff --git a/packages/taikoon-ui/src/lib/wagmi/getLogs.ts b/packages/taikoon-ui/src/lib/wagmi/getLogs.ts new file mode 100644 index 0000000000..32ecc54390 --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/getLogs.ts @@ -0,0 +1,10 @@ +import { getConnectorClient } from '@wagmi/core'; +import { getLogs as viemGetLogs } from 'viem/actions'; + +import getConfig from './getConfig'; +export default async function getLogs(params: Parameters[1]) { + const { config } = getConfig(); + const client = await getConnectorClient(config); + + return await viemGetLogs(client, params); +} diff --git a/packages/taikoon-ui/src/lib/wagmi/index.ts b/packages/taikoon-ui/src/lib/wagmi/index.ts new file mode 100644 index 0000000000..7df6a82d85 --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/index.ts @@ -0,0 +1,4 @@ +import getBalance from './getBalance'; +import { startWatching, stopWatching } from './watcher'; + +export { getBalance, startWatching, stopWatching }; diff --git a/packages/taikoon-ui/src/lib/wagmi/publicClient.ts b/packages/taikoon-ui/src/lib/wagmi/publicClient.ts new file mode 100644 index 0000000000..33678a81b6 --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/publicClient.ts @@ -0,0 +1,11 @@ +import { createPublicClient, http } from 'viem'; +import { hardhat } from 'viem/chains'; + +export default async function publicClient() { + const client = createPublicClient({ + chain: hardhat, + transport: http('http://localhost:8545'), + }); + + return client; +} diff --git a/packages/taikoon-ui/src/lib/wagmi/watcher.ts b/packages/taikoon-ui/src/lib/wagmi/watcher.ts new file mode 100644 index 0000000000..819d7b2e9a --- /dev/null +++ b/packages/taikoon-ui/src/lib/wagmi/watcher.ts @@ -0,0 +1,50 @@ +import { watchAccount } from '@wagmi/core'; + +import { config } from '$wagmi-config'; + +import { isSupportedChain } from '../../lib/chain'; +import { refreshUserBalance } from '../../lib/util/balance'; +import { checkForPausedContracts } from '../../lib/util/checkForPausedContracts'; +import { getLogger } from '../../lib/util/logger'; +import { account } from '../../stores/account'; +import { switchChainModal } from '../../stores/modal'; +import { connectedSourceChain } from '../../stores/network'; +const log = getLogger('wagmi:watcher'); + +let isWatching = false; +let unWatchAccount: () => void; + +export async function startWatching() { + checkForPausedContracts(); + + if (!isWatching) { + unWatchAccount = watchAccount(config, { + onChange(data) { + checkForPausedContracts(); + log('Account changed', data); + account.set(data); + refreshUserBalance(); + const { chain } = data; + + // We need to check if the chain is supported, and if not + // we present the user with a modal to switch networks. + if (chain && !isSupportedChain(Number(chain.id))) { + log('Unsupported chain', chain); + switchChainModal.set(true); + return; + } else if (chain) { + // When we switch networks, we are actually selecting + // the source chain. + connectedSourceChain.set(chain); + } + }, + }); + + isWatching = true; + } +} + +export function stopWatching() { + unWatchAccount(); + isWatching = false; +} diff --git a/packages/taikoon-ui/src/lib/whitelist/getProof.ts b/packages/taikoon-ui/src/lib/whitelist/getProof.ts new file mode 100644 index 0000000000..cc6732510a --- /dev/null +++ b/packages/taikoon-ui/src/lib/whitelist/getProof.ts @@ -0,0 +1,27 @@ +import { StandardMerkleTree } from '@openzeppelin/merkle-tree'; +import { getAccount } from '@wagmi/core'; + +import getConfig from '$lib/wagmi/getConfig'; + +import type { IAddress } from '../../types'; +import { whitelist } from './index'; + +export default function getProof(address?: IAddress): IAddress[] { + const { config, chainId } = getConfig(); + + if (!address) { + const account = getAccount(config); + if (!account.address) return []; + address = account.address; + } + + const tree = StandardMerkleTree.load(whitelist[chainId]); + for (const [i, [leafAddress]] of tree.entries()) { + if (leafAddress.toString().toLowerCase() === address.toString().toLowerCase()) { + const proof = tree.getProof(i); + return proof as IAddress[]; + } + } + + return []; +} diff --git a/packages/taikoon-ui/src/lib/whitelist/index.ts b/packages/taikoon-ui/src/lib/whitelist/index.ts new file mode 100644 index 0000000000..30eb338212 --- /dev/null +++ b/packages/taikoon-ui/src/lib/whitelist/index.ts @@ -0,0 +1,9 @@ +import { hardhat, holesky } from '@wagmi/core/chains'; + +import { default as HardhatWhitelist } from '../../generated/whitelist/hardhat.json'; +import { default as HoleskyWhitelist } from '../../generated/whitelist/holesky.json'; + +export const whitelist: Record = { + [hardhat.id]: HardhatWhitelist, + [holesky.id]: HoleskyWhitelist, +}; diff --git a/packages/taikoon-ui/src/routes/+layout.svelte b/packages/taikoon-ui/src/routes/+layout.svelte new file mode 100644 index 0000000000..0c77630d90 --- /dev/null +++ b/packages/taikoon-ui/src/routes/+layout.svelte @@ -0,0 +1,70 @@ + + +
+ + +
+
+ + + + + + + + + +{#if windowSize === 'sm'} + +{/if} + + diff --git a/packages/taikoon-ui/src/routes/+layout.ts b/packages/taikoon-ui/src/routes/+layout.ts new file mode 100644 index 0000000000..967a633331 --- /dev/null +++ b/packages/taikoon-ui/src/routes/+layout.ts @@ -0,0 +1,5 @@ +// When setting this to false your entire app will only be rendered on the client, +// which essentially means you turn your app into an SPA. +// See https://kit.svelte.dev/docs/page-options#ssr + +export const ssr = false; diff --git a/packages/taikoon-ui/src/routes/+page.svelte b/packages/taikoon-ui/src/routes/+page.svelte new file mode 100644 index 0000000000..e9aa539d50 --- /dev/null +++ b/packages/taikoon-ui/src/routes/+page.svelte @@ -0,0 +1,61 @@ + + + + Taikoons + + + + {#if currentPage === 'teaser'} + +
+ +
+
+ {:else} + +
+ +
+
+ {/if} +
+ +
+ + + +
+ + diff --git a/packages/taikoon-ui/src/routes/collection/+page.svelte b/packages/taikoon-ui/src/routes/collection/+page.svelte new file mode 100644 index 0000000000..a76e5f3a59 --- /dev/null +++ b/packages/taikoon-ui/src/routes/collection/+page.svelte @@ -0,0 +1,29 @@ + + + + Taikoons | Collection + + + +
+ +
+
diff --git a/packages/taikoon-ui/src/routes/collection/[address]/+page.svelte b/packages/taikoon-ui/src/routes/collection/[address]/+page.svelte new file mode 100644 index 0000000000..a9b412d30c --- /dev/null +++ b/packages/taikoon-ui/src/routes/collection/[address]/+page.svelte @@ -0,0 +1,30 @@ + + + + Taikoons | Collection + + + +
+ +
+
diff --git a/packages/taikoon-ui/src/routes/collection/[address]/+page.ts b/packages/taikoon-ui/src/routes/collection/[address]/+page.ts new file mode 100644 index 0000000000..843a5a1959 --- /dev/null +++ b/packages/taikoon-ui/src/routes/collection/[address]/+page.ts @@ -0,0 +1,3 @@ +export async function load({ params }) { + return params; +} diff --git a/packages/taikoon-ui/src/routes/mint/+page.svelte b/packages/taikoon-ui/src/routes/mint/+page.svelte new file mode 100644 index 0000000000..4839797433 --- /dev/null +++ b/packages/taikoon-ui/src/routes/mint/+page.svelte @@ -0,0 +1,33 @@ + + + + Taikoons | Mint + + + + +
+ +
+ + + +
+
+ + + + diff --git a/packages/taikoon-ui/src/stores/account.ts b/packages/taikoon-ui/src/stores/account.ts new file mode 100644 index 0000000000..6ffb37f592 --- /dev/null +++ b/packages/taikoon-ui/src/stores/account.ts @@ -0,0 +1,6 @@ +import type { GetAccountReturnType } from '@wagmi/core'; +import { writable } from 'svelte/store'; + +export type Account = GetAccountReturnType; + +export const account = writable(); diff --git a/packages/taikoon-ui/src/stores/balance.ts b/packages/taikoon-ui/src/stores/balance.ts new file mode 100644 index 0000000000..5ea759c362 --- /dev/null +++ b/packages/taikoon-ui/src/stores/balance.ts @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const ethBalance = writable(); diff --git a/packages/taikoon-ui/src/stores/bridgedToken.ts b/packages/taikoon-ui/src/stores/bridgedToken.ts new file mode 100644 index 0000000000..a509a9ba66 --- /dev/null +++ b/packages/taikoon-ui/src/stores/bridgedToken.ts @@ -0,0 +1,32 @@ +import { get, writable } from 'svelte/store'; +import type { Address } from 'viem'; + +import { getLogger } from '../lib/util/logger'; + +const log = getLogger('token:bridgedToken'); + +type TokenInfo = { + isBridged: boolean; + chainId: number; +}; + +type BridgedTokens = Record; +export const bridgedTokens = writable({}); + +export const setBridgedTokenInfoStore = (tokenAddress: Address, isBridged: boolean, chainId: number) => { + bridgedTokens.update((currentTokens) => { + return { ...currentTokens, [tokenAddress]: { isBridged, chainId } }; + }); +}; + +export const getBridgedStatusFromStore = (tokenAddress: Address): boolean => { + log('getting bridged token status from store', tokenAddress); + const tokens = get(bridgedTokens); + return tokens[tokenAddress]?.isBridged ?? false; +}; + +export const getBridgedTokenInfoStore = (tokenAddress: Address): TokenInfo => { + log('getting bridged token info from store', tokenAddress); + const tokens = get(bridgedTokens); + return tokens[tokenAddress]; +}; diff --git a/packages/taikoon-ui/src/stores/index.ts b/packages/taikoon-ui/src/stores/index.ts new file mode 100644 index 0000000000..43b786b1a3 --- /dev/null +++ b/packages/taikoon-ui/src/stores/index.ts @@ -0,0 +1,5 @@ +export { account } from './account'; +export { metadataCache } from './metadata'; +export { connectedSourceChain } from './network'; +export { page } from './page'; +export { pendingTransactions } from './pendingTransactions'; diff --git a/packages/taikoon-ui/src/stores/metadata.ts b/packages/taikoon-ui/src/stores/metadata.ts new file mode 100644 index 0000000000..63da119a57 --- /dev/null +++ b/packages/taikoon-ui/src/stores/metadata.ts @@ -0,0 +1,38 @@ +import { get, writable } from 'svelte/store'; +import type { Address } from 'viem'; + +import type NFTMetadata from '../lib/token'; + +export type NFTCacheIdentifier = { + address: Address; + id: number; +}; + +function createCacheKey(identifier: NFTCacheIdentifier): string { + return `${identifier.address}-${identifier.id.toString()}`; +} + +export const metadataCache = writable>(new Map()); + +export function addMetadataToCache(identifier: NFTCacheIdentifier, metadata: NFTMetadata): void { + metadataCache.update((cache) => { + const key = createCacheKey(identifier); + cache.set(key, metadata); + return cache; + }); +} + +export function getMetadataFromCache(identifier: NFTCacheIdentifier): NFTMetadata | undefined { + const cache = get(metadataCache); + const key = createCacheKey(identifier); + return cache.get(key); +} + +export function isMetadataCached(identifier: NFTCacheIdentifier): boolean { + let exists = false; + metadataCache.subscribe((cache) => { + const key = createCacheKey(identifier); + exists = cache.has(key); + })(); + return exists; +} diff --git a/packages/taikoon-ui/src/stores/mint.ts b/packages/taikoon-ui/src/stores/mint.ts new file mode 100644 index 0000000000..6c70a08729 --- /dev/null +++ b/packages/taikoon-ui/src/stores/mint.ts @@ -0,0 +1,13 @@ +import { writable } from 'svelte/store'; + +import type { IAddress } from '../types'; + +export interface IMintStore { + isModalOpen: boolean; + isMinting: boolean; + tokenIds: number[]; + address: IAddress; + totalMintCount: number; +} + +export const mint = writable(); diff --git a/packages/taikoon-ui/src/stores/modal.ts b/packages/taikoon-ui/src/stores/modal.ts new file mode 100644 index 0000000000..0b7025043d --- /dev/null +++ b/packages/taikoon-ui/src/stores/modal.ts @@ -0,0 +1,7 @@ +import { writable } from 'svelte/store'; + +// We make this global because we need to be able to +// open and close the modal from anywhere in the app +export const switchChainModal = writable(false); + +export const bridgePausedModal = writable(false); diff --git a/packages/taikoon-ui/src/stores/network.ts b/packages/taikoon-ui/src/stores/network.ts new file mode 100644 index 0000000000..48417fb7a1 --- /dev/null +++ b/packages/taikoon-ui/src/stores/network.ts @@ -0,0 +1,6 @@ +import { writable } from 'svelte/store'; +import type { Chain } from 'viem'; + +export const connectedSourceChain = writable(); + +export const switchingNetwork = writable(false); diff --git a/packages/taikoon-ui/src/stores/page.ts b/packages/taikoon-ui/src/stores/page.ts new file mode 100644 index 0000000000..7d34b2d47b --- /dev/null +++ b/packages/taikoon-ui/src/stores/page.ts @@ -0,0 +1,3 @@ +import { writable } from 'svelte/store'; + +export const page = writable(); diff --git a/packages/taikoon-ui/src/stores/pendingTransactions.ts b/packages/taikoon-ui/src/stores/pendingTransactions.ts new file mode 100644 index 0000000000..580932728c --- /dev/null +++ b/packages/taikoon-ui/src/stores/pendingTransactions.ts @@ -0,0 +1,94 @@ +import { waitForTransactionReceipt } from '@wagmi/core'; +import { writable } from 'svelte/store'; +import type { Hex, TransactionReceipt } from 'viem'; + +import { config } from '$wagmi-config'; + +import { pendingTransaction } from '../app.config'; +import { FailedTransactionError } from '../lib/error'; +import { refreshUserBalance } from '../lib/util/balance'; +import { Deferred } from '../lib/util/Deferred'; +import { getLogger } from '../lib/util/logger'; + +const log = getLogger('store:pendingTransactions'); + +// Custom store: pendingTransactions +const { subscribe, set, update } = writable([]); +export const pendingTransactions = { + /** + * We're creating here a custom store, which is a writable store. + * We must stick to the store contract, which is: + */ + set, + subscribe, + // update, // this method is optional. + + /** + * Custom method, which will help us add a new transaction to the store + * and get it removed the transaction is mined. + */ + add: (hash: Hex, chainId: number) => { + const deferred = new Deferred(); + + update((hashes: Hex[]) => { + // New array with the new transaction appended + const newPendingTransactions = [...hashes, hash]; + + // Next step is to wait for the transaction to be mined + // before removing it from the store. + + /** + * Returns a Promise which will not resolve until transactionHash is mined. + * If confirms is 0, this method is non-blocking and if the transaction + * has not been mined returns null. Otherwise, this method will block until + * the transaction has confirms blocks mined on top of the block in which + * is was mined. + */ + waitForTransactionReceipt(config, { + hash, + chainId, + timeout: pendingTransaction.waitTimeout, + }) + .then((receipt) => { + log('Transaction mined with receipt', receipt); + + log(`Removing transaction "${hash}" from store`); + update((hashes: Hex[]) => + // Filter out the transaction with the given hash + hashes.filter((_hash) => _hash !== hash), + ); + + // Resolves or rejects the promise depending on the transaction status. + if (receipt.status === 'success') { + log('Transaction successful'); + deferred.resolve(receipt); + } else { + deferred.reject( + new FailedTransactionError(`transaction with hash "${hash}" failed`, { + cause: receipt, + }), + ); + } + }) + .catch((err) => { + console.error(err); + deferred.reject( + new FailedTransactionError(`transaction with hash "${hash}" failed`, { + cause: err, + }), + ); + }) + .finally(() => { + refreshUserBalance(); + }); + + return newPendingTransactions; + }); + + // TODO: return deferred object instead, so we can cancel the promise + // in case we need it, e.g.: poller picks up already claimed transaction + // by the relayer, in which case we don't need to wait for this transaction + // to finish + return deferred.promise; + }, +}; diff --git a/packages/taikoon-ui/src/stores/relayerApi.ts b/packages/taikoon-ui/src/stores/relayerApi.ts new file mode 100644 index 0000000000..94facbddef --- /dev/null +++ b/packages/taikoon-ui/src/stores/relayerApi.ts @@ -0,0 +1,7 @@ +import { writable } from 'svelte/store'; + +import type { PaginationInfo, RelayerBlockInfo } from '../../lib/relayer/types'; + +export const paginationInfo = writable(); + +export const relayerBlockInfoMap = writable>(); diff --git a/packages/taikoon-ui/src/stores/taikoonDetail.ts b/packages/taikoon-ui/src/stores/taikoonDetail.ts new file mode 100644 index 0000000000..4d03920410 --- /dev/null +++ b/packages/taikoon-ui/src/stores/taikoonDetail.ts @@ -0,0 +1,8 @@ +import { writable } from 'svelte/store'; + +export interface ITaikoonDetailStore { + tokenId: number; + isModalOpen: boolean; +} + +export const taikoonDetail = writable(); diff --git a/packages/taikoon-ui/src/stores/theme.ts b/packages/taikoon-ui/src/stores/theme.ts new file mode 100644 index 0000000000..873c9a2728 --- /dev/null +++ b/packages/taikoon-ui/src/stores/theme.ts @@ -0,0 +1,8 @@ +import { writable } from 'svelte/store'; + +export const enum Theme { + DARK = 'dark', + LIGHT = 'light', +} + +export const theme = writable(Theme.DARK); diff --git a/packages/taikoon-ui/src/stores/tokenInfo.ts b/packages/taikoon-ui/src/stores/tokenInfo.ts new file mode 100644 index 0000000000..a257c946a7 --- /dev/null +++ b/packages/taikoon-ui/src/stores/tokenInfo.ts @@ -0,0 +1,50 @@ +// tokenInfoStore.ts +import { get, writable } from 'svelte/store'; +import type { Address } from 'viem'; + +import { getLogger } from '../../lib/util/logger'; + +const log = getLogger('stores:tokenInfoStore'); + +export type TokenInfo = { + canonical: { + chainId: number; + address: Address; + } | null; + bridged: { + chainId: number; + address: Address; + } | null; +}; +export type SetTokenInfoParams = { + canonicalAddress: Address; + bridgedAddress: Address | null; + info: TokenInfo; +}; +type TokenInfoStore = Record; + +export const tokenInfoStore = writable({}); + +export const setTokenInfo = ({ canonicalAddress, bridgedAddress, info }: SetTokenInfoParams) => { + log('setting token info', canonicalAddress, bridgedAddress, info); + tokenInfoStore.update((store) => { + store[canonicalAddress] = info; + if (!bridgedAddress) return store; + store[bridgedAddress] = info; + return store; + }); +}; + +export const isCanonicalAddress = (address: Address): boolean => { + const store = get(tokenInfoStore); + const tokenInfo = store[address]; + + return tokenInfo?.canonical?.address === address; +}; + +export const isBridgedAddress = (address: Address): boolean => { + const store = get(tokenInfoStore); + const tokenInfo = store[address]; + + return tokenInfo?.bridged?.address === address; +}; diff --git a/packages/taikoon-ui/src/styles/base.css b/packages/taikoon-ui/src/styles/base.css new file mode 100644 index 0000000000..0665003e18 --- /dev/null +++ b/packages/taikoon-ui/src/styles/base.css @@ -0,0 +1,67 @@ +@tailwind base; + +@layer base { + *, + ::after, + ::before { + text-rendering: optimizespeed; + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: transparent; + backface-visibility: hidden; + } + + html { + font-family: 'Public Sans', sans-serif; + } + + html, + body { + height: 100%; + } + + body { + height: 100%; + } + + [data-theme='dark'] body::before { + content: ''; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + /* + background-image: url(/bg/grid-dark.svg), url(/bg/spotlights-dark.svg), + linear-gradient(270deg, #1f1f1f 0%, #000000 100%); + */ + /* No grid background by default */ + background-size: 0, cover, cover; + background-blend-mode: color-dodge, lighten, multiply; + z-index: -1; + } + + [data-theme='light'] body::before { + content: ''; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + background-image: url(/bg/grid-light.svg), url(/bg/spotlights-light.svg), + linear-gradient(270deg, #e2e2e2 0%, #fff 100%); + /* No grid background by default */ + background-size: 0, cover, cover; + background-blend-mode: color-dodge, color, hard-light; + z-index: -1; + } + + @media (min-width: 768px) { + [data-theme='dark'] body::before { + background-size: 50px, cover, cover; + } + + [data-theme='light'] body::before { + background-size: 50px, cover, cover; + } + } +} diff --git a/packages/taikoon-ui/src/styles/components.css b/packages/taikoon-ui/src/styles/components.css new file mode 100644 index 0000000000..0d89cd4e98 --- /dev/null +++ b/packages/taikoon-ui/src/styles/components.css @@ -0,0 +1,234 @@ +@tailwind components; + +@layer components { + /* Typography */ + .title-screen-regular { + @apply font-normal text-[2rem]/10; + } + + .title-screen-bold { + @apply font-bold text-[2rem]/10; + } + + .title-section-regular { + @apply font-normal text-[1.625rem]/8; + } + + .title-section-bold { + @apply font-bold text-[1.625rem]/8; + } + + .title-subsection-regular { + @apply font-normal text-[1.375rem]/7; + } + + .title-subsection-bold { + @apply font-bold text-[1.375rem]/7; + } + + .title-body-regular { + @apply font-normal text-lg/6; + } + + .title-body-bold { + @apply font-bold text-lg/6; + } + + .body-regular { + @apply font-normal text-base; + } + + .body-bold { + @apply font-bold text-base; + } + + .body-small-regular { + @apply font-normal text-sm; + } + + .body-small-bold { + @apply font-bold text-sm; + } + + .callout-regular { + @apply font-normal text-sm; + } + + .callout-bold { + @apply font-bold text-sm; + } + + .link-large-regular { + @apply font-normal text-base; + } + + .link-regular { + @apply font-normal text-sm; + } + + /* Form Controls */ + .input-box { + /* Using shadows to increase border size without impacting the surroundings */ + @apply outline-none + rounded-[10px] + bg-transparent + + /* border */ + /* border-primary-border */ + /* shadow-[0_0_0_1px_#5d636f] */ + + /* hover:border-2 */ + /* hover:border-primary-border-hover */ + enabled:hover:shadow-[0_0_0_2px_#FF6FC8] + + /* focus:border-[3px] */ + /* focus:border-primary-border-accent */ + focus:!shadow-[0_0_0_3px_#E81899]; + } + + .input-box.withValdiation { + @apply outline-none; + } + + .input-box.error { + @apply !shadow; + box-shadow: 0 0 0 3px var(--negative-sentiment) !important; + } + + .input-box.success { + box-shadow: 0 0 0 3px var(--positive-sentiment) !important; + } + + .input-box.warning { + box-shadow: 0 0 0 3px var(--warning-sentiment) !important; + } + + .input-box.neutral { + box-shadow: 0 0 0 1px var(--primary-border-dark) !important; + } + + /* Tooltip */ + .dialog-tooltip { + @apply rounded-[10px] + w-[283px] + p-[24px] + bg-neutral-background + text-primary-content + box-shadow-small; + + letter-spacing: 0.14px; + + > div:first-of-type { + @apply title-body-bold; + padding-bottom: 8px; + } + } + + .dialog-tooltip-top { + :before { + content: ''; + position: absolute; + height: 0px; + width: 0px; + top: 100%; + left: 133px; /* (283px - 9px)/2 - 4px */ + border-width: 9px; + border-color: transparent transparent transparent; + border-style: solid; + border-top: 9px solid var(--neutral-background); + } + } + + /* Separators */ + .h-sep { + @apply divider h-[1px] border-divider-border; + } + + .v-sep { + @apply divider divider-horizontal w-[1px] border-divider-border; + } + + /* Links and buttons */ + .link { + @apply link-regular text-primary-link underline hover:text-primary-link-hover; + } + + .status-btn { + @apply px-[20px] + py-2 + rounded-full + bg-transparent + + /* primary-interactive[#C8047D => pink-500] */ + shadow-[0_0_0_1px_#C8047D] + + /* primary-interactive-accent[#E81899 => pink-400] */ + hover:shadow-[0_0_0_2px_#E81899]; + } + + /* Other components */ + .overlay-backdrop { + @apply modal-backdrop bg-overlay-background rounded-xl z-30; + } + + .overlay-dialog { + background-color: var(--overlay-dialog); + } + + .chainselector { + @apply /* background: var(--interactive-dark-tertiary, #444A55); */ + hover:background-color: var(--interactive-dark-tertiary-hover, #5D636F); + } + + .glassy-gradient-card::before { + @apply glassy-background; + content: ''; + position: absolute; + inset: 0%; + z-index: -1; + } + + input { + border: 1px solid var(--primary-border); + } + + h1 { + color: var(--primary-content); + text-align: center; + /* Title Section/Bold */ + font-family: 'Clash Grotesk', sans-serif; + font-size: 26px; + font-style: normal; + font-weight: 600; + line-height: 32px; /* 123.077% */ + letter-spacing: -0.39px; + } + + h2 { + color: var(--primary-content); + font-family: 'Clash Grotesk', sans-serif; + font-size: 18px; + font-style: normal; + font-weight: 600; + line-height: 24px; /* 133.333% */ + letter-spacing: 0.09px; + margin-bottom: 8px; + } + + button:disabled { + cursor: not-allowed; + } + + input:disabled { + cursor: not-allowed; + } + + .radio { + border: 1px solid var(--primary-border-dark); + &:checked { + border: 1px solid var(--primary-interactive-accent); + } + } + + /* TODO: add more components here */ +} diff --git a/packages/taikoon-ui/src/styles/gimmicks.css b/packages/taikoon-ui/src/styles/gimmicks.css new file mode 100644 index 0000000000..0c3585cfb3 --- /dev/null +++ b/packages/taikoon-ui/src/styles/gimmicks.css @@ -0,0 +1,85 @@ +/* + Shiny border glow effect + */ + +[data-glow-border] { + --base: 333; + --border-size: calc(var(--border, 2) * 1px); + --spotlight-size: calc(var(--size, 150) * 1px); + --hue: calc(var(--base) + (var(--xp, 0) * var(--spread, 0))); + background-image: radial-gradient( + var(--spotlight-size) var(--spotlight-size) at calc(var(--x, 0) * 1px) calc(var(--y, 0) * 1px), + hsl( + var(--hue, 210) calc(var(--saturation, 100) * 1%) calc(var(--lightness, 70) * 1%) / var(--bg-spot-opacity, 0.1) + ), + transparent + ); + border-radius: 20px; + background-color: var(--backdrop, transparent); + background-size: calc(100% + (2 * var(--border-size))) calc(100% + (2 * var(--border-size))); + background-position: 50% 50%; + background-attachment: fixed; + border: var(--border-size) solid var(--backup-border); + position: relative; + touch-action: none; +} + +[data-glow-border]::before, +[data-glow-border]::after { + border-radius: 20px; + pointer-events: none; + content: ''; + position: absolute; + inset: calc(var(--border-size) * -1); + border: var(--border-size) solid transparent; + background-attachment: fixed; + background-size: calc(100% + (2 * var(--border-size))) calc(100% + (2 * var(--border-size))); + background-repeat: no-repeat; + background-position: 50% 50%; + mask: linear-gradient(transparent, transparent), linear-gradient(white, white); + mask-clip: padding-box, border-box; + mask-composite: intersect; +} + +/* This is the emphasis light */ +[data-glow-border]::before { + border-radius: 20px; + background-image: radial-gradient( + calc(var(--spotlight-size) * 0.75) calc(var(--spotlight-size) * 0.75) at calc(var(--x, 0) * 1px) + calc(var(--y, 0) * 1px), + hsl( + var(--hue, 210) calc(var(--saturation, 100) * 1%) calc(var(--lightness, 50) * 1%) / var(--border-spot-opacity, 1) + ), + transparent 100% + ); + filter: brightness(2); +} +/* This is the spotlight */ +[data-glow-border]::after { + background-image: radial-gradient( + calc(var(--spotlight-size) * 0.5) calc(var(--spotlight-size) * 0.5) at calc(var(--x, 0) * 1px) + calc(var(--y, 0) * 1px), + hsl(0 100% 100% / var(--border-light-opacity, 1)), + transparent 100% + ); +} +[data-glow-border] [data-glow-border] { + position: absolute; + inset: 0; + will-change: filter; + opacity: var(--outer, 1); +} +[data-glow-border] > [data-glow-border] { + border-radius: 20px; + border-width: calc(var(--border-size) * 20); + filter: blur(calc(var(--border-size) * 10)); + background: none; + pointer-events: none; +} +[data-glow-border] > [data-glow-border]::before { + inset: -10px; + border-width: 10px; +} +[data-glow-border] [data-glow-border] { + border: none; +} diff --git a/packages/taikoon-ui/src/styles/override.css b/packages/taikoon-ui/src/styles/override.css new file mode 100644 index 0000000000..bff39df2b0 --- /dev/null +++ b/packages/taikoon-ui/src/styles/override.css @@ -0,0 +1,85 @@ +/************************** + * Remove Arrows/Spinners * + **************************/ + +/* Chrome, Safari, Edge, Opera */ +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + @apply appearance-none m-0; +} + +/* Firefox */ +input[type='number'] { + -moz-appearance: textfield; +} + +/** + * Overrides the default color for the overlay component used + * in DaisyUI's drawer. Unfortunately cannot be done via variables + */ +.drawer-toggle:checked ~ .drawer-side > .drawer-overlay { + background-color: var(--primary-background); +} + +/** + * By design we don't have any opacity on disabled buttons, + * also font color is tertiary-content + */ +.btn.btn-disabled, +.btn[disabled], +.btn:disabled { + --tw-border-opacity: 1; + --tw-bg-opacity: 1; + --tw-text-opacity: 1; + @apply text-tertiary-content; +} + +.title-body-bold { + color: var(--primary-content); + text-align: left; + font-size: 18px; + letter-spacing: 0.09px; +} + +.modal-box { + @apply z-40; + display: inline-flex; + padding: 35px 24px 45px 24px; + flex-direction: column; + align-items: center; +} + +.step:after { + height: 0px !important; + width: 0px !important; +} + +.step-primary:after { + height: 8px !important; + width: 8px !important; +} + +.step:before { + background-color: rgba(255, 198, 233, 0.2) !important; + height: 2px !important; +} + +.step-primary:before { + background-color: var(--primary-interactive-accent) !important; + height: 2px !important; +} + +.step-previous:before { + background-color: var(--primary-interactive-accent) !important; + height: 2px !important; +} + +.step-previous:after { + @apply step-primary; + height: 0px !important; + width: 0px !important; +} + +.label { + padding: 0; +} diff --git a/packages/taikoon-ui/src/styles/utilities.css b/packages/taikoon-ui/src/styles/utilities.css new file mode 100644 index 0000000000..88687720b6 --- /dev/null +++ b/packages/taikoon-ui/src/styles/utilities.css @@ -0,0 +1,76 @@ +@tailwind utilities; + +@layer utilities { + .block-hidden { + @apply block invisible opacity-0; + } + + .md-show-block { + @apply hidden md:block; + } + + .md-show-inblock { + @apply hidden md:inline-block; + } + + .w-h-full { + @apply w-full h-full; + } + + .sticky-top { + @apply sticky top-0; + } + + .glassy-background { + @apply backdrop-filter backdrop-blur-sm; + } + + .glassy-background-md { + @apply backdrop-filter backdrop-blur-md; + } + + .glassy-background-lg { + @apply backdrop-filter backdrop-blur-lg; + } + + .dark-glass-background-gradient { + background: linear-gradient(226deg, rgba(93, 99, 111, 0.1) 1.26%, rgba(25, 30, 40, 0.2) 100%); + } + + .light-glass-background-gradient { + background: linear-gradient(226deg, rgba(250, 250, 250, 0.9) 1.26%, rgba(250, 249, 249, 0.9) 100%); + } + + /* Flex shortcuts */ + .f-between-center { + @apply flex justify-between items-center; + } + + .f-center { + @apply flex justify-center items-center; + } + + .f-justify-center { + @apply flex justify-center; + } + + .f-items-center { + @apply flex items-center; + } + + .f-row { + @apply flex flex-row; + } + + .f-col { + @apply flex flex-col; + } + + .box-shadow-small { + box-shadow: 0px 10px 48px 0px rgba(5, 9, 18, 0.3); + } + + .box-shadow-large { + box-shadow: 0px 20px 66px 0px rgba(5, 9, 18, 0.48); + } +} diff --git a/packages/taikoon-ui/src/types.ts b/packages/taikoon-ui/src/types.ts new file mode 100644 index 0000000000..3dc54d5fb4 --- /dev/null +++ b/packages/taikoon-ui/src/types.ts @@ -0,0 +1,46 @@ +import type { Address } from 'viem'; + +import type { IconType } from '$components/core/Icons'; +export type { IconType } from '$components/core/Icons'; + +export interface IDropdownItem { + icon: IconType; + label: string; + href: string; +} + +export type IChainId = 31337 | 17000; + +export interface IBid { + amount: number; + bidder: IAddress; + id: string; + timestamp: Date; +} + +export interface IAuction { + id: number; + tokenId: number; + amount: number; + startTime: Date; + endTime: Date; + bidder: string; + settled: boolean; + //minBid: number + bids: IBid[]; + blockNumber: number; + lastUpdate: Date; + updateCounter: number; +} + +export type IAddress = Address; + +export interface ITaikoon { + id: number; + owner: IAddress; + mintPrice: number; + mintedAt: Date; + isAuctioned: boolean; + isFreeMint: boolean; + isPaidMint: boolean; +} diff --git a/packages/taikoon-ui/src/wagmi.config.ts b/packages/taikoon-ui/src/wagmi.config.ts new file mode 100644 index 0000000000..b437dc7e28 --- /dev/null +++ b/packages/taikoon-ui/src/wagmi.config.ts @@ -0,0 +1,31 @@ +import { injected, walletConnect } from '@wagmi/connectors'; +import { createConfig, http, reconnect } from '@wagmi/core'; +import { hardhat, holesky } from '@wagmi/core/chains'; + +import { PUBLIC_WALLETCONNECT_PROJECT_ID } from '$env/static/public'; + +const projectId = PUBLIC_WALLETCONNECT_PROJECT_ID; + +const baseConfig = { + chains: [hardhat, holesky], + projectId, + metadata: {}, + batch: { + multicall: false, + }, + transports: { + [hardhat.id]: http('http://localhost:8545'), + //[holesky.id]: http('https://1rpc.io/holesky'), + [holesky.id]: http('https://ethereum-holesky.blockpi.network/v1/rpc/public'), + //[holesky.id]: http('https://l1rpc.hekla.taiko.xyz/'), + }, +} as const; + +export const config = createConfig({ + ...baseConfig, + connectors: [walletConnect({ projectId, showQrModal: false }), injected()], +}); + +export const publicConfig = createConfig(baseConfig); + +reconnect(config); diff --git a/packages/taikoon-ui/static/bg/footer-gradient.svg b/packages/taikoon-ui/static/bg/footer-gradient.svg new file mode 100644 index 0000000000..43a7376f6f --- /dev/null +++ b/packages/taikoon-ui/static/bg/footer-gradient.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/taikoon-ui/static/bg/general-gradient.svg b/packages/taikoon-ui/static/bg/general-gradient.svg new file mode 100644 index 0000000000..98bafaecbe --- /dev/null +++ b/packages/taikoon-ui/static/bg/general-gradient.svg @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/taikoon-ui/static/bg/grid-dark.svg b/packages/taikoon-ui/static/bg/grid-dark.svg new file mode 100644 index 0000000000..148051dde1 --- /dev/null +++ b/packages/taikoon-ui/static/bg/grid-dark.svg @@ -0,0 +1 @@ +AAAsZ2p1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAACxBanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46dXVpZDpjYzZjYmZlOC04MDljLTQ2ZDAtYmI4Ny0yOGZjZTAwNzhkNmMAAAABp2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAAMpqdW1iAAAAJmp1bWRjYm9yABEAEIAAAKoAOJtxA2MycGEuYWN0aW9ucwAAAACcY2JvcqFnYWN0aW9uc4GjZmFjdGlvbmtjMnBhLmVkaXRlZG1zb2Z0d2FyZUFnZW50bUFkb2JlIEZpcmVmbHlxZGlnaXRhbFNvdXJjZVR5cGV4Rmh0dHA6Ly9jdi5pcHRjLm9yZy9uZXdzY29kZXMvZGlnaXRhbHNvdXJjZXR5cGUvdHJhaW5lZEFsZ29yaXRobWljTWVkaWEAAACsanVtYgAAAChqdW1kY2JvcgARABCAAACqADibcQNjMnBhLmhhc2guZGF0YQAAAAB8Y2JvcqVqZXhjbHVzaW9uc4GiZXN0YXJ0GK5mbGVuZ3RoGTs0ZG5hbWVuanVtYmYgbWFuaWZlc3RjYWxnZnNoYTI1NmRoYXNoWCB1bx8o+/NyNI5l1oEgUyzJDYVBSgx/XToB6fTf2MNpx2NwYWRJAAAAAAAAAAAAAAACC2p1bWIAAAAkanVtZGMyY2wAEQAQgAAAqgA4m3EDYzJwYS5jbGFpbQAAAAHfY2JvcqhoZGM6dGl0bGVvR2VuZXJhdGVkIEltYWdlaWRjOmZvcm1hdG1pbWFnZS9zdmcreG1samluc3RhbmNlSUR4LHhtcDppaWQ6NmE3ODVjMjgtYWI2NC00OTVmLTk0MTUtODFlNjAyYmJkZDI3b2NsYWltX2dlbmVyYXRvcng2QWRvYmVfSWxsdXN0cmF0b3IvMjguMCBhZG9iZV9jMnBhLzAuNy42IGMycGEtcnMvMC4yNS4ydGNsYWltX2dlbmVyYXRvcl9pbmZvgb9kbmFtZXFBZG9iZSBJbGx1c3RyYXRvcmd2ZXJzaW9uZDI4LjD/aXNpZ25hdHVyZXgZc2VsZiNqdW1iZj1jMnBhLnNpZ25hdHVyZWphc3NlcnRpb25zgqJjdXJseCdzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnNkaGFzaFgg66xm4WqDn3xgnOk59f7WI0GCp10rxJISEEb0ImTQK8GiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFggoJTpDmzsPa9spsd4TAdiTOJdEbKKBnrioj+C4RjRpV5jYWxnZnNoYTI1NgAAKEBqdW1iAAAAKGp1bWRjMmNzABEAEIAAAKoAOJtxA2MycGEuc2lnbmF0dXJlAAAAKBBjYm9y0oREoQE4JKNmc2lnVHN0oWl0c3RUb2tlbnOBoWN2YWxZDjcwgg4zMAMCAQAwgg4qBgkqhkiG9w0BBwKggg4bMIIOFwIBAzEPMA0GCWCGSAFlAwQCAQUAMIGDBgsqhkiG9w0BCRABBKB0BHIwcAIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIPAcP3PUAdVMVgZxh1yfqsSB2cPnFfgUljsGTefVWIuOAhEA8otTf15CzrfTHMUeWoVVphgPMjAyNDAxMDQxNDQyNDZaAgkAt0gQdbEEu3ugggu9MIIFBzCCAu+gAwIBAgIQBR6ekdcekQq75D1c7dDd2TANBgkqhkiG9w0BAQsFADBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMB4XDTIzMDkwODAwMDAwMFoXDTM0MTIwNzIzNTk1OVowWDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTAwLgYDVQQDEydEaWdpQ2VydCBBZG9iZSBBQVRMIFRpbWVzdGFtcCBSZXNwb25kZXIwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARNLK5R+QP/tefzBZdWrDYfEPE7mzrBFX7tKpSaxdLJo7cC9SHh2fwAeyefbtU66YaNQQzfOZX02N9KzQbH0/pso4IBizCCAYcwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMB8GA1UdIwQYMBaAFLoW2W1NhS9zKXaaL3WMaiCPnshvMB0GA1UdDgQWBBSwNapWwyGpi87TuLyLFiVXne804TBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3JsMIGQBggrBgEFBQcBAQSBgzCBgDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMFgGCCsGAQUFBzAChkxodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRSU0E0MDk2U0hBMjU2VGltZVN0YW1waW5nQ0EuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQB4K4xCx4QQhFiUgskV+5bC9AvSyYG19a8lWMkjUcR5DEdi6guz0GUSYAzUfpCaKfD+b9gc6f4zK88OFOKWOq2L9yPB6RZSWuLgcFEyFIB1qYvF8XdSRBF/eDzjg4ux8knpF+tANOeQaMxW+xhlWsW9C63kE0V55K+oIDzVD1/RoftknDsZU3UEC4GW5HWL8aNwKenMva4mYo0cTmaojslksTFIYCsXis8KxVul23tGsDYTlF2cyMXOIsaSs1kiLaTyd9GYgUJ+PVNwA2E57IWzfWZEwNaR3/zaL9mVL73XZGfFGL8KPbwby0w755gAZ0TASml2ALN2Qr8PQpAzzlk3lCTBUQLZlMedqIWgN5w/GwielH6UNqRXznUocKW+hir9IPgYHHSBtixzydFH5q/l5qYGYKvxyIHtIY3AgA6Yw4Kts+AdC+MbQANTPDK1MdNocW+9dOJxSqjLr+cyU0Jd7IMKl1Mj/vcx0D/cv2eRcfwEFqzlwluenVez+HBQSZfMx6op5YZDkrWdZttvvR5avngtISdpZBdS7s0XSSW/+dS16DykZ6KRQ54Ol6aA+3husOGKQMffj9NCblKAbGEq3bLhYslskEBgQJ4yOvYIG0i3FvoScrbop2sWsFZSLSZEtnleWeF7MT4O3/NrkZHbTdIUx3iPdwjdzlnkXm5yuzCCBq4wggSWoAMCAQICEAc2N7ckVHzYR6z9KGYqXlswDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290IEc0MB4XDTIyMDMyMzAwMDAwMFoXDTM3MDMyMjIzNTk1OVowYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMaGNQZJs8E9cklRVcclA8TykTepl1Gh1tKD0Z5Mom2gsMyD+Vr2EaFEFUJfpIjzaPp985yJC3+dH54PMx9QEwsmc5Zt+FeoAn39Q7SE2hHxc7Gz7iuAhIoiGN/r2j3EF3+rGSs+QtxnjupRPfDWVtTnKC3r07G1decfBmWNlCnT2exp39mQh0YAe9tEQYncfGpXevA3eZ9drMvohGS0UvJ2R/dhgxndX7RUCyFobjchu0CsX7LeSn3O9TkSZ+8OpWNs5KbFHc02DVzV5huowWR0QKfAcsW6Th+xtVhNef7Xj3OTrCw54qVI1vCwMROpVymWJy71h6aPTnYVVSZwmCZ/oBpHIEPjQ2OAe3VuJyWQmDo4EbP29p7mO1vsgd4iFNmCKseSv6De4z6ic/rnH1pslPJSlRErWHRAKKtzQ87fSqEcazjFKfPKqpZzQmiftkaznTqj1QPgv/CiPMpC3BhIfxQ0z9JMq++bPf4OuGQq+nUoJEHtQr8FnGZJUlD0UfM2SU2LINIsVzV5K6jzRWC8I41Y99xh3pP+OcD5sjClTNfpmEpYPtMDiP6zj9NeS3YSUZPJjAw7W4oiqMEmCPkUEBIDfV8ju2TjY+Cm4T72wnSyPx4JduyrXUZ14mCjWAkBKAAOhFTuzuldyF4wEr1GnrXTdrnSDmuZDNIztM2xAgMBAAGjggFdMIIBWTASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQWBBS6FtltTYUvcyl2mi91jGogj57IbzAfBgNVHSMEGDAWgBTs1+OC0nFdZEzfLmc/57qYrhwPTzAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgwdwYIKwYBBQUHAQEEazBpMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQQYIKwYBBQUHMAKGNWh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3J0MEMGA1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRSb290RzQuY3JsMCAGA1UdIAQZMBcwCAYGZ4EMAQQCMAsGCWCGSAGG/WwHATANBgkqhkiG9w0BAQsFAAOCAgEAfVmOwJO2b5ipRCIBfmbW2CFC4bAYLhBNE88wU86/GPvHUF3iSyn7cIoNqilp/GnBzx0H6T5gyNgL5Vxb122H+oQgJTQxZ822EpZvxFBMYh0MCIKoFr2pVs8Vc40BIiXOlWk/R3f7cnQU1/+rT4osequFzUNf7WC2qk+RZp4snuCKrOX9jLxkJodskr2dfNBwCnzvqLx1T7pa96kQsl3p/yhUifDVinF2ZdrM8HKjI/rAJ4JErpknG6skHibBt94q6/aesXmZgaNWhqsKRcnfxI2g55j7+6adcq/Ex8HBanHZxhOACcS2n82HhyS7T6NJuXdmkfFynOlLAlKnN36TU6w7HQhJD5TNOXrd/yVjmScsPT9rp/Fmw0HNT7ZAmyEhQNC3EyTN3B14OuSereU0cZLXJmvkOHOrpgFPvT87eK1MrfvElXvtCl8zOYdBeHo46Zzh3SP9HSjTx/no8Zhf+yvYfvJGnXUsHicsJttvFXseGYs2uJPU5vIXmVnKcPA3v5gA3yAWTyf7YGcWoWa63VXAOimGsJigK+2VQbc61RWYMbRiCQ8KvYHZE/6/pNHzV9m8BPqC3jLfBInwAM1dwvnQI38AC+R2AibZ8GV2QqYphwlHK+Z/GqSFD/yYlvZVVCsfgPrA8g4r5db7qS9EFUrnEw4d2zc4GqEr9u3WfPwxggG4MIIBtAIBATB3MGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0ECEAUenpHXHpEKu+Q9XO3Q3dkwDQYJYIZIAWUDBAIBBQCggdEwGgYJKoZIhvcNAQkDMQ0GCyqGSIb3DQEJEAEEMBwGCSqGSIb3DQEJBTEPFw0yNDAxMDQxNDQyNDZaMCsGCyqGSIb3DQEJEAIMMRwwGjAYMBYEFNkauTP+F63pgh6mE/WkOnFOPn59MC8GCSqGSIb3DQEJBDEiBCDVvHFz0ZTcCQRqe9YL5cDCe8cZHiDLrOUdNSYM4GnMejA3BgsqhkiG9w0BCRACLzEoMCYwJDAiBCCC2vGUlXs2hAJFj9UnAGn+YscUVvqeC4ar+CfoUyAn2TAKBggqhkjOPQQDAgRHMEUCIAC/UR9M+deI87GrZf0cckN+bPGi9dIEQQjysi1dfSlNAiEAuJigLXs9WYxBJr9KCwJnvX0f3AO5ePR7yF/88UVcY3xneDVjaGFpboJZBjMwggYvMIIEF6ADAgECAhAbWws72rDkXfLzDZ5U0drSMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRvYmUgVHJ1c3QgU2VydmljZXMxIjAgBgNVBAMTGUFkb2JlIFByb2R1Y3QgU2VydmljZXMgRzMwHhcNMjMwMjAxMDAwMDAwWhcNMjQwMjAxMjM1OTU5WjCBoTERMA8GA1UEAwwIY2FpLXByb2QxHDAaBgNVBAsME0NvbnRlbnQgQ3JlZGVudGlhbHMxEzARBgNVBAoMCkFkb2JlIEluYy4xETAPBgNVBAcMCFNhbiBKb3NlMRMwEQYDVQQIDApDYWxpZm9ybmlhMQswCQYDVQQGEwJVUzEkMCIGCSqGSIb3DQEJARYVZ3JwLWNhaS1vcHNAYWRvYmUuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA79MAp32GPZZBw7MpK0xuxWJZ2BwXMrmpbg+bvVC487/hbE1ji4PDYa8/UU8SPRHgW7t1pu3+L6j7EGH8ZBKdMCGug1ZhDmYWwHkX24cm1kPw+Fr73JOJhGUfkGZk6SJ+x1+tYG7TBR5SVMZGAXLSKALfUwQBW8/XeSINlhtG7B9/W+v/FEl5yCJOBQenbQUU9cXhMEg7cDndWAaV1zQSZkVh1zSWWfOaH9rQU3rIP5DL06ziScWA2fe1ONesHL21aJpXnrPjV1GN/2QeMR/jbGYpbO5tWy9r9oUpx4i6KmXlCpJWx1Jk+GaY62QnbbiLFpuY9jz1yq+xylLgm2UlwQIDAQAFo4IBjDCCAYgwDAYDVR0TAQH/BAIwADAOBgNVHQ8BAf8EBAMCB4AwHgYDVR0lBBcwFQYJKoZIhvcvAQEMBggrBgEFBQcDBDCBjgYDVR0gBIGGMIGDMIGABgkqhkiG9y8BAgMwczBxBggrBgEFBQcCAjBlDGNZb3UgYXJlIG5vdCBwZXJtaXR0ZWQgdG8gdXNlIHRoaXMgTGljZW5zZSBDZXJ0aWZpY2F0ZSBleGNlcHQgYXMgcGVybWl0dGVkIGJ5IHRoZSBsaWNlbnNlIGFncmVlbWVudC4wXQYDVR0fBFYwVDBSoFCgToZMaHR0cDovL3BraS1jcmwuc3ltYXV0aC5jb20vY2FfN2E1YzNhMGM3MzExNzQwNmFkZDE5MzEyYmMxYmMyM2YvTGF0ZXN0Q1JMLmNybDA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9wa2ktb2NzcC5zeW1hdXRoLmNvbTAfBgNVHSMEGDAWgBRXKXoyTcz+5DVOwB8kc85zU6vfajANBgkqhkiG9w0BAQsFAAOCAgEAV45Rmt8gCvxoo5+p/yTVPRWZu9jD+r3OXM61nvctE/hGsLkb4aQ+RHYtU515K6XvLDJIEo0xnW2PshoavM5QlkHlzdf2lqNy/V69bjcWP6FaS59Llln53ye8kfYCpf8qDH4Y8nU+LdX1x4vzIX4a1klUR6l9lN9VBRs/3tvfD9pL/r6oc6SFKNW4/o4m7aDyzDEHAjk7SoiTk4eKN1UmacEAxEQs6PdTZBfi52Y8GJenxOVEiJIP6AqKJl8Uj6aMMmw63ESfYpW7SXBEePPyxoMM7/3OzmHa6J+D5xF5tRZDmlY/kEX+zsIjU4s6J4SMy0eVX6dEBzlr/2z87woz0Hfl69EONN9lpUsUMKLLTUwD7aFQFODgsFR9xHId/HpidNP+n5Awna+zDfP+J9i0jazFL2gRGXZi6gwgZztNnWxa5qYN6U3NBakUOBi//PKY0TUjMubVPUqEJ0ghmKiLI3y/AM4DxBol10YAAWHNbl3nH+P3msm9ytjD7O4Z1k21CqRxySMMaXTd70xnWTVqc/TsX7qN3hC0JZE7wAh4KpGl4vxQGpx3uTwoZ+n69f+HDRfIKA9G7jwKYEt888Ko0Ycax/CEsD3yZ/Cas7qzGiwzJ53NfLR81IjLV+943+qF4e76AsV/0+A95xT5cVN6JtnKXC0NVneNNusdfK5UhkdZBqUwggahMIIEiaADAgECAhAMqLZUe4nm0gaJdc2Lm4niMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRvYmUgVHJ1c3QgU2VydmljZXMxGTAXBgNVBAMTEEFkb2JlIFJvb3QgQ0EgRzIwHhcNMTYxMTI5MDAwMDAwWhcNNDExMTI4MjM1OTU5WjB1MQswCQYDVQQGEwJVUzEjMCEGA1UEChMaQWRvYmUgU3lzdGVtcyBJbmNvcnBvcmF0ZWQxHTAbBgNVBAsTFEFkb2JlIFRydXN0IFNlcnZpY2VzMSIwIAYDVQQDExlBZG9iZSBQcm9kdWN0IFNlcnZpY2VzIEczMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtx8uvb0Js1xIbP4Mg65sAepReCWkgD6Jp7GyiGTa9ol2gfn5HfOV/HiYjZiOz+TuHFU+DXNad86xEqgVeGVMlvIHGe/EHcKBxvEDXdlTXB5zIEkfl0/SGn7J6vTX8MNybfSi95eQDUOZ9fjCaq+PBFjS5ZfeNmzi/yR+MsA0jKKoWarSRCFFFBpUFQWfAgLyXOyxOnXQOQudjxNj6Wu0X0IB13+IH11WcKcWEWXM4j4jh6hLy29Cd3EoVG3oxcVenMF/EMgD2tXjx4NUbTNB1/g9+MR6Nw5Mhp5k/g3atNExAxhtugC+T3SDShSEJfs2quiiRUHtX3RhOcK1s1OJgT5s2s9xGy5/uxVpcAIaK2KiDJXW3xxN8nXPmk1NSVu/mxtfapr4TvSJbhrU7UA3qhQY9n4On2sbH1X1Tw+7LTek8KCA5ZDghOERPiIp/Jt893qov1bE5rJkagcVg0Wqjh89NhCaBA8VyRt3ovlGyCKdNV2UL3bn5vdFsTk7qqmp9makz1/SuVXYxIf6L6+8RXOatXWaPkmucuLE1TPOeP7S1N5JToFCs80l2D2EtxoQXGCR48K/cTUR5zV/fQ+hdIOzoo0nFn77Y8Ydd2k7/x9BE78pmoeMnw6VXYfXCuWEgj6p7jpbLoxQMoWMCVzlg72WVNhJFlSw4aD8fc6ezeECAwEAAaOCATQwggEwMBIGA1UdEwEB/wQIMAYBAf8CAQAwNQYDVR0fBC4wLDAqoCigJoYkaHR0cDovL2NybC5hZG9iZS5jb20vYWRvYmVyb290ZzIuY3JsMA4GA1UdDwEB/wQEAwIBBjAUBgNVHSUEDTALBgkqhkiG9y8BAQcwVwYDVR0gBFAwTjBMBgkqhkiG9y8BAgMwPzA9BggrBgEFBQcCARYxaHR0cHM6Ly93d3cuYWRvYmUuY29tL21pc2MvcGtpL3Byb2Rfc3ZjZV9jcHMuaHRtbDAkBgNVHREEHTAbpBkwFzEVMBMGA1UEAxMMU1lNQy00MDk2LTMzMB0GA1UdDgQWBBRXKXoyTcz+5DVOwB8kc85zU6vfajAfBgNVHSMEGDAWgBSmHOFtVCRMqI9Icr9uqYzV5Owx1DANBgkqhkiG9w0BAQsFAAOCAgEAcc7lB4ym3C3cyOA7ZV4AkoGV65UgJK+faThdyXzxuNqlTQBlOyXBGFyevlm33BsGO1mDJfozuyLyT2+7IVxWFvW5yYMV+5S1NeChMXIZnCzWNXnuiIQSdmPD82TEVCkneQpFET4NDwSxo8/ykfw6Hx8fhuKz0wjhjkWMXmK3dNZXIuYVcbynHLyJOzA+vWU3sH2T0jPtFp7FN39GZne4YG0aVMlnHhtHhxaXVCiv2RVoR4w1QtvKHQpzfPObR53Cl74iLStGVFKPwCLYRSpYRF7J6vVS/XxW4LzvN2b6VEKOcvJmN3LhpxFRl3YYzW+dwnwtbuHW6WJlmjffbLm1MxLFGlG95aCz31X8wzqYNsvb9+5AXcv8Ll69tLXmO1OtsY/3wILNUEp4VLZTE3wqm3n8hMnClZiiKyZCS7L4E0mClbx+BRSMH3eVo6jgve41/fK3FQM4QCNIkpGs7FjjLy+ptC+JyyWqcfvORrFV/GOgB5hD+G5ghJcIpeigD/lHsCRYsOa5sFdqREhwIWLmSWtNwfLZdJ3dkCc7yRpm3gal6qRfTkYpxTNxxKyvKbkaJDoxR9vtWrC3iNrQd9VvxC3TXtuzoHbqumeqgcAqefWF9u6snQ4Q9FkXzeuJArNuSvPIhgBjVtggH0w0vm/lmCQYiC/Y12GeCxfgYlL33btjcGFkWQu8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZZAQArNGNXHEwu8hbhH8BcClaDHvDRrgpyNkc03nFZYvUTTCivFyR2+hucFs6hF3NEvWH1BK7V/DQhtU4Qp/+bC8qUz9Sef/e8KQwGZF1dgNur5Xx4o28p3t/WVh7PeXSRgXT1xj1ZFaikMS0/kF6IYgzMTRQeK0k5PIztuQYa+EIwS+K2kDJYjsM5mx2r5oRNd0ys7stWEfbXYjKYyA5OPSr9DXiGpAiYUUnUkPgguKnRdgEYk5gdmJEMJeNumMesPyFqaNLtaT9we3liyvSuiWL3/ByrBcSfqARLFMzsMccfZPrCPlK5LaCs2cKFcIiQV6LWQPvSWBsJKbJrgu+EO92m \ No newline at end of file diff --git a/packages/taikoon-ui/static/bg/grid-light.svg b/packages/taikoon-ui/static/bg/grid-light.svg new file mode 100644 index 0000000000..218c2b25cf --- /dev/null +++ b/packages/taikoon-ui/static/bg/grid-light.svg @@ -0,0 +1 @@ +AAAsZ2p1bWIAAAAeanVtZGMycGEAEQAQgAAAqgA4m3EDYzJwYQAAACxBanVtYgAAAEdqdW1kYzJtYQARABCAAACqADibcQN1cm46dXVpZDpiM2FmNjgzYy0wYWYzLTRmNzUtOTkzNy03YmMxZDZiMmU1MmUAAAABp2p1bWIAAAApanVtZGMyYXMAEQAQgAAAqgA4m3EDYzJwYS5hc3NlcnRpb25zAAAAAMpqdW1iAAAAJmp1bWRjYm9yABEAEIAAAKoAOJtxA2MycGEuYWN0aW9ucwAAAACcY2JvcqFnYWN0aW9uc4GjZmFjdGlvbmtjMnBhLmVkaXRlZG1zb2Z0d2FyZUFnZW50bUFkb2JlIEZpcmVmbHlxZGlnaXRhbFNvdXJjZVR5cGV4Rmh0dHA6Ly9jdi5pcHRjLm9yZy9uZXdzY29kZXMvZGlnaXRhbHNvdXJjZXR5cGUvdHJhaW5lZEFsZ29yaXRobWljTWVkaWEAAACsanVtYgAAAChqdW1kY2JvcgARABCAAACqADibcQNjMnBhLmhhc2guZGF0YQAAAAB8Y2JvcqVqZXhjbHVzaW9uc4GiZXN0YXJ0GK5mbGVuZ3RoGTs0ZG5hbWVuanVtYmYgbWFuaWZlc3RjYWxnZnNoYTI1NmRoYXNoWCAZT8wekJwPkTmqVVDmaJVQ8PL8UPHn1VCzF0oXaGqgL2NwYWRJAAAAAAAAAAAAAAACC2p1bWIAAAAkanVtZGMyY2wAEQAQgAAAqgA4m3EDYzJwYS5jbGFpbQAAAAHfY2JvcqhoZGM6dGl0bGVvR2VuZXJhdGVkIEltYWdlaWRjOmZvcm1hdG1pbWFnZS9zdmcreG1samluc3RhbmNlSUR4LHhtcDppaWQ6OGM5NDgwODktMWMwMy00NTRhLTg2NjctNzk0NjJmMjM4ZTIxb2NsYWltX2dlbmVyYXRvcng2QWRvYmVfSWxsdXN0cmF0b3IvMjguMCBhZG9iZV9jMnBhLzAuNy42IGMycGEtcnMvMC4yNS4ydGNsYWltX2dlbmVyYXRvcl9pbmZvgb9kbmFtZXFBZG9iZSBJbGx1c3RyYXRvcmd2ZXJzaW9uZDI4LjD/aXNpZ25hdHVyZXgZc2VsZiNqdW1iZj1jMnBhLnNpZ25hdHVyZWphc3NlcnRpb25zgqJjdXJseCdzZWxmI2p1bWJmPWMycGEuYXNzZXJ0aW9ucy9jMnBhLmFjdGlvbnNkaGFzaFgg66xm4WqDn3xgnOk59f7WI0GCp10rxJISEEb0ImTQK8GiY3VybHgpc2VsZiNqdW1iZj1jMnBhLmFzc2VydGlvbnMvYzJwYS5oYXNoLmRhdGFkaGFzaFggMr1E5k8vEKBbJj+hM1mnourzIoF6IQgRtvjbTVlmp4djYWxnZnNoYTI1NgAAKEBqdW1iAAAAKGp1bWRjMmNzABEAEIAAAKoAOJtxA2MycGEuc2lnbmF0dXJlAAAAKBBjYm9y0oREoQE4JKNmc2lnVHN0oWl0c3RUb2tlbnOBoWN2YWxZDjYwgg4yMAMCAQAwgg4pBgkqhkiG9w0BBwKggg4aMIIOFgIBAzEPMA0GCWCGSAFlAwQCAQUAMIGCBgsqhkiG9w0BCRABBKBzBHEwbwIBAQYJYIZIAYb9bAcBMDEwDQYJYIZIAWUDBAIBBQAEIAiMNHRmxkd8bxCYvu18jrVaUlutYw36KL3Hj7BQf9c5AhEAyJ26dPXQ0TjFen9fOnagEBgPMjAyNDAxMDQxNDM4MzlaAggHQlDsH7oj4qCCC70wggUHMIIC76ADAgECAhAFHp6R1x6RCrvkPVzt0N3ZMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjMwOTA4MDAwMDAwWhcNMzQxMjA3MjM1OTU5WjBYMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xMDAuBgNVBAMTJ0RpZ2lDZXJ0IEFkb2JlIEFBVEwgVGltZXN0YW1wIFJlc3BvbmRlcjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABE0srlH5A/+15/MFl1asNh8Q8TubOsEVfu0qlJrF0smjtwL1IeHZ/AB7J59u1Trpho1BDN85lfTY30rNBsfT+myjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgBhv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYEFLA1qlbDIamLztO4vIsWJVed7zThMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAHgrjELHhBCEWJSCyRX7lsL0C9LJgbX1ryVYySNRxHkMR2LqC7PQZRJgDNR+kJop8P5v2Bzp/jMrzw4U4pY6rYv3I8HpFlJa4uBwUTIUgHWpi8Xxd1JEEX94POODi7HySekX60A055BozFb7GGVaxb0LreQTRXnkr6ggPNUPX9Gh+2ScOxlTdQQLgZbkdYvxo3Ap6cy9riZijRxOZqiOyWSxMUhgKxeKzwrFW6Xbe0awNhOUXZzIxc4ixpKzWSItpPJ30ZiBQn49U3ADYTnshbN9ZkTA1pHf/Nov2ZUvvddkZ8UYvwo9vBvLTDvnmABnRMBKaXYAs3ZCvw9CkDPOWTeUJMFRAtmUx52ohaA3nD8bCJ6UfpQ2pFfOdShwpb6GKv0g+BgcdIG2LHPJ0Ufmr+XmpgZgq/HIge0hjcCADpjDgq2z4B0L4xtAA1M8MrUx02hxb7104nFKqMuv5zJTQl3sgwqXUyP+9zHQP9y/Z5Fx/AQWrOXCW56dV7P4cFBJl8zHqinlhkOStZ1m22+9Hlq+eC0hJ2lkF1LuzRdJJb/51LXoPKRnopFDng6XpoD7eG6w4YpAx9+P00JuUoBsYSrdsuFiyWyQQGBAnjI69ggbSLcW+hJytuinaxawVlItJkS2eV5Z4XsxPg7f82uRkdtN0hTHeI93CN3OWeRebnK7MIIGrjCCBJagAwIBAgIQBzY3tyRUfNhHrP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjIwMzIzMDAwMDAwWhcNMzcwMzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIEluYy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYgVGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPRnkyibaCwzIP5WvYRoUQVQl+kiPNo+n3znIkLf50fng8zH1ATCyZzlm34V6gCff1DtITaEfFzsbPuK4CEiiIY3+vaPcQXf6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8GZY2UKdPZ7Gnf2ZCHRgB720RBidx8ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQLIWhuNyG7QKxfst5Kfc71ORJn7w6lY2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1WE15/tePc5OsLDnipUjW8LAxE6lXKZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7dW4nJZCYOjgRs/b2nuY7W+yB3iIU2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAoq3NDzt9KoRxrOMUp88qqlnNCaJ+2RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9/g64ZCr6dSgkQe1CvwWcZklSUPRR8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45wPmyMKVM1+mYSlg+0wOI/rOP015LdhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj4KbhPvbCdLI/Hgl27KtdRnXiYKNYCQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM0jO0zbECAwEAAaOCAV0wggFZMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLoW2W1NhS9zKXaaL3WMaiCPnshvMB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQwQwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9WY7Ak7ZvmKlEIgF+ZtbYIULhsBguEE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHPHQfpPmDI2AvlXFvXbYf6hCAlNDFnzbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6VaT9Hd/tydBTX/6tPiix6q4XNQ1/tYLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAKfO+ovHVPulr3qRCyXen/KFSJ8NWKcXZl2szwcqMj+sAngkSumScbqyQeJsG33irr9p6xeZmBo1aGqwpFyd/EjaDnmPv7pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5d2aR8XKc6UsCUqc3fpNTrDsdCEkPlM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA0LcTJM3cHXg65J6t5TRxktcma+Q4c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjpnOHdI/0dKNPH+ejxmF/7K9h+8kaddSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/mADfIBZPJ/tgZxahZrrdVcA6KYawmKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX2bwE+oLeMt8EifAAzV3C+dAjfwAL5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVUKx+A+sDyDivl1vupL0QVSucTDh3bNzgaoSv27dZ8/DGCAbgwggG0AgEBMHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRpbWVTdGFtcGluZyBDQQIQBR6ekdcekQq75D1c7dDd2TANBglghkgBZQMEAgEFAKCB0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI0MDEwNDE0MzgzOVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU2Rq5M/4XremCHqYT9aQ6cU4+fn0wLwYJKoZIhvcNAQkEMSIEIGY2uZeaq/GU3wRiNUjg48U4fhAY2VudjMBsjAGzAIwmMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEIILa8ZSVezaEAkWP1ScAaf5ixxRW+p4Lhqv4J+hTICfZMAoGCCqGSM49BAMCBEcwRQIgUCxdeKIZq4nDmJIuvjPFmcKxNxyCjlawf4o9L3lW+BQCIQC1UhnvuYYW4Re7yH9Ci7XNzkDXYgNTxjyK4Q+ZR7BfuWd4NWNoYWluglkGMzCCBi8wggQXoAMCAQICEBtbCzvasORd8vMNnlTR2tIwDQYJKoZIhvcNAQELBQAwdTELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMR0wGwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEiMCAGA1UEAxMZQWRvYmUgUHJvZHVjdCBTZXJ2aWNlcyBHMzAeFw0yMzAyMDEwMDAwMDBaFw0yNDAyMDEyMzU5NTlaMIGhMREwDwYDVQQDDAhjYWktcHJvZDEcMBoGA1UECwwTQ29udGVudCBDcmVkZW50aWFsczETMBEGA1UECgwKQWRvYmUgSW5jLjERMA8GA1UEBwwIU2FuIEpvc2UxEzARBgNVBAgMCkNhbGlmb3JuaWExCzAJBgNVBAYTAlVTMSQwIgYJKoZIhvcNAQkBFhVncnAtY2FpLW9wc0BhZG9iZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDv0wCnfYY9lkHDsykrTG7FYlnYHBcyualuD5u9ULjzv+FsTWOLg8Nhrz9RTxI9EeBbu3Wm7f4vqPsQYfxkEp0wIa6DVmEOZhbAeRfbhybWQ/D4Wvvck4mEZR+QZmTpIn7HX61gbtMFHlJUxkYBctIoAt9TBAFbz9d5Ig2WG0bsH39b6/8USXnIIk4FB6dtBRT1xeEwSDtwOd1YBpXXNBJmRWHXNJZZ85of2tBTesg/kMvTrOJJxYDZ97U416wcvbVomlees+NXUY3/ZB4xH+NsZils7m1bL2v2hSnHiLoqZeUKklbHUmT4ZpjrZCdtuIsWm5j2PPXKr7HKUuCbZSXBAgMBAAWjggGMMIIBiDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIHgDAeBgNVHSUEFzAVBgkqhkiG9y8BAQwGCCsGAQUFBwMEMIGOBgNVHSAEgYYwgYMwgYAGCSqGSIb3LwECAzBzMHEGCCsGAQUFBwICMGUMY1lvdSBhcmUgbm90IHBlcm1pdHRlZCB0byB1c2UgdGhpcyBMaWNlbnNlIENlcnRpZmljYXRlIGV4Y2VwdCBhcyBwZXJtaXR0ZWQgYnkgdGhlIGxpY2Vuc2UgYWdyZWVtZW50LjBdBgNVHR8EVjBUMFKgUKBOhkxodHRwOi8vcGtpLWNybC5zeW1hdXRoLmNvbS9jYV83YTVjM2EwYzczMTE3NDA2YWRkMTkzMTJiYzFiYzIzZi9MYXRlc3RDUkwuY3JsMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL3BraS1vY3NwLnN5bWF1dGguY29tMB8GA1UdIwQYMBaAFFcpejJNzP7kNU7AHyRzznNTq99qMA0GCSqGSIb3DQEBCwUAA4ICAQBXjlGa3yAK/Gijn6n/JNU9FZm72MP6vc5czrWe9y0T+EawuRvhpD5Edi1TnXkrpe8sMkgSjTGdbY+yGhq8zlCWQeXN1/aWo3L9Xr1uNxY/oVpLn0uWWfnfJ7yR9gKl/yoMfhjydT4t1fXHi/MhfhrWSVRHqX2U31UFGz/e298P2kv+vqhzpIUo1bj+jibtoPLMMQcCOTtKiJOTh4o3VSZpwQDERCzo91NkF+LnZjwYl6fE5USIkg/oCoomXxSPpowybDrcRJ9ilbtJcER48/LGgwzv/c7OYdron4PnEXm1FkOaVj+QRf7OwiNTizonhIzLR5Vfp0QHOWv/bPzvCjPQd+Xr0Q4032WlSxQwostNTAPtoVAU4OCwVH3Ech38emJ00/6fkDCdr7MN8/4n2LSNrMUvaBEZdmLqDCBnO02dbFrmpg3pTc0FqRQ4GL/88pjRNSMy5tU9SoQnSCGYqIsjfL8AzgPEGiXXRgABYc1uXecf4/eayb3K2MPs7hnWTbUKpHHJIwxpdN3vTGdZNWpz9Oxfuo3eELQlkTvACHgqkaXi/FAanHe5PChn6fr1/4cNF8goD0buPApgS3zzwqjRhxrH8ISwPfJn8JqzurMaLDMnnc18tHzUiMtX73jf6oXh7voCxX/T4D3nFPlxU3om2cpcLQ1Wd4026x18rlSGR1kGpTCCBqEwggSJoAMCAQICEAyotlR7iebSBol1zYubieIwDQYJKoZIhvcNAQELBQAwbDELMAkGA1UEBhMCVVMxIzAhBgNVBAoTGkFkb2JlIFN5c3RlbXMgSW5jb3Jwb3JhdGVkMR0wGwYDVQQLExRBZG9iZSBUcnVzdCBTZXJ2aWNlczEZMBcGA1UEAxMQQWRvYmUgUm9vdCBDQSBHMjAeFw0xNjExMjkwMDAwMDBaFw00MTExMjgyMzU5NTlaMHUxCzAJBgNVBAYTAlVTMSMwIQYDVQQKExpBZG9iZSBTeXN0ZW1zIEluY29ycG9yYXRlZDEdMBsGA1UECxMUQWRvYmUgVHJ1c3QgU2VydmljZXMxIjAgBgNVBAMTGUFkb2JlIFByb2R1Y3QgU2VydmljZXMgRzMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC3Hy69vQmzXEhs/gyDrmwB6lF4JaSAPomnsbKIZNr2iXaB+fkd85X8eJiNmI7P5O4cVT4Nc1p3zrESqBV4ZUyW8gcZ78QdwoHG8QNd2VNcHnMgSR+XT9Iafsnq9Nfww3Jt9KL3l5ANQ5n1+MJqr48EWNLll942bOL/JH4ywDSMoqhZqtJEIUUUGlQVBZ8CAvJc7LE6ddA5C52PE2Ppa7RfQgHXf4gfXVZwpxYRZcziPiOHqEvLb0J3cShUbejFxV6cwX8QyAPa1ePHg1RtM0HX+D34xHo3DkyGnmT+Ddq00TEDGG26AL5PdINKFIQl+zaq6KJFQe1fdGE5wrWzU4mBPmzaz3EbLn+7FWlwAhorYqIMldbfHE3ydc+aTU1JW7+bG19qmvhO9IluGtTtQDeqFBj2fg6faxsfVfVPD7stN6TwoIDlkOCE4RE+Iin8m3z3eqi/VsTmsmRqBxWDRaqOHz02EJoEDxXJG3ei+UbIIp01XZQvdufm90WxOTuqqan2ZqTPX9K5VdjEh/ovr7xFc5q1dZo+Sa5y4sTVM854/tLU3klOgUKzzSXYPYS3GhBcYJHjwr9xNRHnNX99D6F0g7OijScWfvtjxh13aTv/H0ETvymah4yfDpVdh9cK5YSCPqnuOlsujFAyhYwJXOWDvZZU2EkWVLDhoPx9zp7N4QIDAQABo4IBNDCCATAwEgYDVR0TAQH/BAgwBgEB/wIBADA1BgNVHR8ELjAsMCqgKKAmhiRodHRwOi8vY3JsLmFkb2JlLmNvbS9hZG9iZXJvb3RnMi5jcmwwDgYDVR0PAQH/BAQDAgEGMBQGA1UdJQQNMAsGCSqGSIb3LwEBBzBXBgNVHSAEUDBOMEwGCSqGSIb3LwECAzA/MD0GCCsGAQUFBwIBFjFodHRwczovL3d3dy5hZG9iZS5jb20vbWlzYy9wa2kvcHJvZF9zdmNlX2Nwcy5odG1sMCQGA1UdEQQdMBukGTAXMRUwEwYDVQQDEwxTWU1DLTQwOTYtMzMwHQYDVR0OBBYEFFcpejJNzP7kNU7AHyRzznNTq99qMB8GA1UdIwQYMBaAFKYc4W1UJEyoj0hyv26pjNXk7DHUMA0GCSqGSIb3DQEBCwUAA4ICAQBxzuUHjKbcLdzI4DtlXgCSgZXrlSAkr59pOF3JfPG42qVNAGU7JcEYXJ6+WbfcGwY7WYMl+jO7IvJPb7shXFYW9bnJgxX7lLU14KExchmcLNY1ee6IhBJ2Y8PzZMRUKSd5CkURPg0PBLGjz/KR/DofHx+G4rPTCOGORYxeYrd01lci5hVxvKccvIk7MD69ZTewfZPSM+0WnsU3f0Zmd7hgbRpUyWceG0eHFpdUKK/ZFWhHjDVC28odCnN885tHncKXviItK0ZUUo/AIthFKlhEXsnq9VL9fFbgvO83ZvpUQo5y8mY3cuGnEVGXdhjNb53CfC1u4dbpYmWaN99subUzEsUaUb3loLPfVfzDOpg2y9v37kBdy/wuXr20teY7U62xj/fAgs1QSnhUtlMTfCqbefyEycKVmKIrJkJLsvgTSYKVvH4FFIwfd5WjqOC97jX98rcVAzhAI0iSkazsWOMvL6m0L4nLJapx+85GsVX8Y6AHmEP4bmCElwil6KAP+UewJFiw5rmwV2pESHAhYuZJa03B8tl0nd2QJzvJGmbeBqXqpF9ORinFM3HErK8puRokOjFH2+1asLeI2tB31W/ELdNe27Ogduq6Z6qBwCp59YX27qydDhD0WRfN64kCs25K88iGAGNW2CAfTDS+b+WYJBiIL9jXYZ4LF+BiUvfdu2NwYWRZC70AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPZZAQCpz30rbo2ljaBSN4n6iKYafXORzXmlpJ9p8vrZ5gjFrvE6Sae5/6cyt7AunnAkyJG4UV1XWT04lH4RnpANrMybBQpZvbQFvMasqTjNheVytWuGrWCjeSVVQGzHsG/O9Ri0lE1hCWRvwJBj+qBbdgroywtevaBLzYz//ATRw2ndCo7a7nUG+rwSyR1pfGHeSVQZMXJ1DOxsnPyMCRKgkJ1H/KzprrfX6NeIjwjwBvpvgyPgKvWPdvTbtoKbVKjFindWCAhhrjL8RrA/vTEjkwKbcwiGL4AqPJiGHdU2VdIusIOPkd0q35N7Zv5Rg278R4uVxPBwrg1Y/glfjV+NprwZ \ No newline at end of file diff --git a/packages/taikoon-ui/static/bg/spotlights-dark.svg b/packages/taikoon-ui/static/bg/spotlights-dark.svg new file mode 100644 index 0000000000..97cf4cf219 --- /dev/null +++ b/packages/taikoon-ui/static/bg/spotlights-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/taikoon-ui/static/bg/spotlights-light.svg b/packages/taikoon-ui/static/bg/spotlights-light.svg new file mode 100644 index 0000000000..d64071304b --- /dev/null +++ b/packages/taikoon-ui/static/bg/spotlights-light.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/taikoon-ui/static/chains/eldfell.svg b/packages/taikoon-ui/static/chains/eldfell.svg new file mode 100644 index 0000000000..c634e8df40 --- /dev/null +++ b/packages/taikoon-ui/static/chains/eldfell.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/taikoon-ui/static/chains/ethereum.svg b/packages/taikoon-ui/static/chains/ethereum.svg new file mode 100644 index 0000000000..d9b8deb4e9 --- /dev/null +++ b/packages/taikoon-ui/static/chains/ethereum.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/taikoon-ui/static/chains/taiko.svg b/packages/taikoon-ui/static/chains/taiko.svg new file mode 100644 index 0000000000..383b51b90f --- /dev/null +++ b/packages/taikoon-ui/static/chains/taiko.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/taikoon-ui/static/favicon.svg b/packages/taikoon-ui/static/favicon.svg new file mode 100644 index 0000000000..f61040109c --- /dev/null +++ b/packages/taikoon-ui/static/favicon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/README.md b/packages/taikoon-ui/static/fonts/clash-grotesk/README.md new file mode 100644 index 0000000000..a080d77f00 --- /dev/null +++ b/packages/taikoon-ui/static/fonts/clash-grotesk/README.md @@ -0,0 +1,46 @@ +# Installing Webfonts + +Follow these simple Steps. + +## 1. + +Put `clash-grotesk/` Folder into a Folder called `fonts/`. + +## 2. + +Put `clash-grotesk.css` into your `css/` Folder. + +## 3. (Optional) + +You may adapt the `url('path')` in `clash-grotesk.css` depends on your Website Filesystem. + +## 4. + +Import `clash-grotesk.css` at the top of you main Stylesheet. + +``` +@import url('clash-grotesk.css'); +``` + +## 5. + +You are now ready to use the following Rules in your CSS to specify each Font Style: + +``` +font-family: ClashGrotesk-Extralight; +font-family: ClashGrotesk-Light; +font-family: ClashGrotesk-Regular; +font-family: ClashGrotesk-Medium; +font-family: ClashGrotesk-Semibold; +font-family: ClashGrotesk-Bold; +font-family: ClashGrotesk-Variable; + +``` + +## 6. (Optional) + +Use `font-variation-settings` rule to controlaxes of variable fonts: +wght 700.0 + +Available axes: +'wght' (range from 200.0 to 700.0 diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/css/clash-grotesk.css b/packages/taikoon-ui/static/fonts/clash-grotesk/css/clash-grotesk.css new file mode 100644 index 0000000000..53b089035f --- /dev/null +++ b/packages/taikoon-ui/static/fonts/clash-grotesk/css/clash-grotesk.css @@ -0,0 +1,90 @@ +/** +* @license +* +* Font Family: Clash Grotesk +* Designed by: Indian Type Foundry +* URL: https://www.fontshare.com/fonts/clash-grotesk +* © 2024 Indian Type Foundry +* +* Clash Grotesk Extralight +* Clash Grotesk Light +* Clash Grotesk Regular +* Clash Grotesk Medium +* Clash Grotesk Semibold +* Clash Grotesk Bold +* Clash Grotesk Variable (Variable font) + +* +*/ +@font-face { + font-family: 'ClashGrotesk-Extralight'; + src: url('../fonts/ClashGrotesk-Extralight.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Extralight.woff') format('woff'), + url('../fonts/ClashGrotesk-Extralight.ttf') format('truetype'); + font-weight: 200; + font-display: swap; + font-style: normal; +} +@font-face { + font-family: 'ClashGrotesk-Light'; + src: url('../fonts/ClashGrotesk-Light.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Light.woff') format('woff'), + url('../fonts/ClashGrotesk-Light.ttf') format('truetype'); + font-weight: 300; + font-display: swap; + font-style: normal; +} +@font-face { + font-family: 'ClashGrotesk-Regular'; + src: url('../fonts/ClashGrotesk-Regular.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Regular.woff') format('woff'), + url('../fonts/ClashGrotesk-Regular.ttf') format('truetype'); + font-weight: 400; + font-display: swap; + font-style: normal; +} +@font-face { + font-family: 'ClashGrotesk-Medium'; + src: url('../fonts/ClashGrotesk-Medium.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Medium.woff') format('woff'), + url('../fonts/ClashGrotesk-Medium.ttf') format('truetype'); + font-weight: 500; + font-display: swap; + font-style: normal; +} +@font-face { + font-family: 'ClashGrotesk-Semibold'; + src: url('../fonts/ClashGrotesk-Semibold.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Semibold.woff') format('woff'), + url('../fonts/ClashGrotesk-Semibold.ttf') format('truetype'); + font-weight: 600; + font-display: swap; + font-style: normal; +} +@font-face { + font-family: 'ClashGrotesk-Bold'; + src: url('../fonts/ClashGrotesk-Bold.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Bold.woff') format('woff'), + url('../fonts/ClashGrotesk-Bold.ttf') format('truetype'); + font-weight: 700; + font-display: swap; + font-style: normal; +} +/** +* This is a variable font +* You can control variable axes as shown below: +* font-variation-settings: wght 700.0; +* +* available axes: +'wght' (range from 200.0 to 700.0 +*/ +@font-face { + font-family: 'ClashGrotesk-Variable'; + src: url('../fonts/ClashGrotesk-Variable.woff2') format('woff2'), + url('../fonts/ClashGrotesk-Variable.woff') format('woff'), + url('../fonts/ClashGrotesk-Variable.ttf') format('truetype'); + font-weight: 200 700; + font-display: swap; + font-style: normal; +} + diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.eot new file mode 100644 index 0000000000..f464d01962 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.ttf new file mode 100644 index 0000000000..a8efddf541 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff new file mode 100644 index 0000000000..b3699d3d2c Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff2 new file mode 100644 index 0000000000..ddc7e14e91 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Bold.woff2 differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.eot new file mode 100644 index 0000000000..278994887e Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.ttf new file mode 100644 index 0000000000..ed73854c0d Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff new file mode 100644 index 0000000000..ea2ba0a70e Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff2 new file mode 100644 index 0000000000..3233b6a863 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Extralight.woff2 differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.eot new file mode 100644 index 0000000000..d0769028b5 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.ttf new file mode 100644 index 0000000000..797f22928f Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff new file mode 100644 index 0000000000..52b91fdbb1 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff2 new file mode 100644 index 0000000000..f54993965b Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Light.woff2 differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.eot new file mode 100644 index 0000000000..84ecbcc16a Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.ttf new file mode 100644 index 0000000000..4616077652 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff new file mode 100644 index 0000000000..9a2a501439 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff2 new file mode 100644 index 0000000000..93292f29bd Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Medium.woff2 differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.eot new file mode 100644 index 0000000000..fac32e1e18 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.ttf new file mode 100644 index 0000000000..d4edb7e039 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff new file mode 100644 index 0000000000..4611fc98aa Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff2 new file mode 100644 index 0000000000..79f265bf9d Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Regular.woff2 differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.eot new file mode 100644 index 0000000000..2c0b4b7fde Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.ttf new file mode 100644 index 0000000000..25885277e2 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff new file mode 100644 index 0000000000..c36553a370 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff2 new file mode 100644 index 0000000000..0766c26f75 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Semibold.woff2 differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.eot b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.eot new file mode 100644 index 0000000000..9fbbd04431 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.eot differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.ttf b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.ttf new file mode 100644 index 0000000000..3d66c39c77 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.ttf differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff new file mode 100644 index 0000000000..66e1be17f8 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff differ diff --git a/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff2 b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff2 new file mode 100644 index 0000000000..0915d80d14 Binary files /dev/null and b/packages/taikoon-ui/static/fonts/clash-grotesk/fonts/ClashGrotesk-Variable.woff2 differ diff --git a/packages/taikoon-ui/static/icons/ArrowDown.svg b/packages/taikoon-ui/static/icons/ArrowDown.svg new file mode 100644 index 0000000000..600676ea6f --- /dev/null +++ b/packages/taikoon-ui/static/icons/ArrowDown.svg @@ -0,0 +1,4 @@ + + + + diff --git a/packages/taikoon-ui/static/img/test-taikoon.png b/packages/taikoon-ui/static/img/test-taikoon.png new file mode 100644 index 0000000000..02853c76bf Binary files /dev/null and b/packages/taikoon-ui/static/img/test-taikoon.png differ diff --git a/packages/taikoon-ui/static/placeholder.svg b/packages/taikoon-ui/static/placeholder.svg new file mode 100644 index 0000000000..b067172a8a --- /dev/null +++ b/packages/taikoon-ui/static/placeholder.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/taikoon-ui/static/taikoons-icon.png b/packages/taikoon-ui/static/taikoons-icon.png new file mode 100644 index 0000000000..17f619da29 Binary files /dev/null and b/packages/taikoon-ui/static/taikoons-icon.png differ diff --git a/packages/taikoon-ui/svelte.config.js b/packages/taikoon-ui/svelte.config.js new file mode 100644 index 0000000000..13e5d08189 --- /dev/null +++ b/packages/taikoon-ui/svelte.config.js @@ -0,0 +1,17 @@ +import adapter from '@sveltejs/adapter-auto' +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' +/** @type {import('@sveltejs/kit').Config} */ +const config = { + // Consult https://kit.svelte.dev/docs/integrations#preprocessors + // for more information about preprocessors + preprocess: vitePreprocess(), + + kit: { + // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. + // If your environment is not supported or you settled on a specific environment, switch out the adapter. + // See https://kit.svelte.dev/docs/adapters for more information about adapters. + adapter: adapter() + }, +} + +export default config diff --git a/packages/taikoon-ui/tailwind.config.js b/packages/taikoon-ui/tailwind.config.js new file mode 100644 index 0000000000..b189fca3b5 --- /dev/null +++ b/packages/taikoon-ui/tailwind.config.js @@ -0,0 +1,500 @@ +import daisyuiPlugin from 'daisyui' + +/** @type {import('tailwindcss').Config} */ +export default { + darkMode: ['class', '[data-theme="dark"]'], + content: ['./src/**/*.{html,js,svelte,ts}'], + theme: { + extend: { + fontFamily: { + 'clash-grotesk': 'ClashGrotesk-Medium', + }, + fontSize: { + 'h0': ['6.25rem', { + lineHeight: '5.313rem' + }], + 'h4': ['1.375rem', { + lineHeight: '1.75rem' + }], + }, + backgroundImage: { + 'footer': "url('/bg/footer-gradient.svg')", + 'general': "url('/bg/general-gradient.svg')", + }, + keyframes: { + 'cell-pulse-animation': { + '0%': { opacity: '0' }, + '50%': { opacity: '1' }, + '100%': { opacity: '0' }, + }, + 'cell-pulse-negative-animation': { + '0%': { opacity: '1' }, + '50%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + }, + animation: { + 'cell-pulse-3': 'cell-pulse-animation 3s ease-in infinite', + 'cell-pulse-5': 'cell-pulse-animation 5s ease-in infinite', + 'cell-pulse-7': 'cell-pulse-animation 7s ease-in infinite', + 'cell-pulse-negative-3': 'cell-pulse-negative-animation 3s ease-in infinite', + 'cell-pulse-negative-5': 'cell-pulse-negative-animation 5s ease-in infinite', + 'cell-pulse-negative-7': 'cell-pulse-negative-animation 7s ease-in infinite', + }, + colors: { + /*************** + * Base colors * + ***************/ + + blue: { + 0: '#FFFFFF', + 5: '#F3F8FF', + 10: '#E7F1FF', + 50: '#C1DFFF', + 100: '#8DC4FF', + 200: '#5AAAFF', + 300: '#2C8FFF', + 400: '#006AFF', + 500: '#0052CC', + 600: '#003E99', + 700: '#002966', + 800: '#001833', + 900: '#000C0D', + 1000: '#050912', + }, + + grey: { + 0: '#FFFFFF', + 5: '#FAFAFA', + 10: '#F3F3F3', + 50: '#E3E3E3', + 100: '#CACBCE', + 200: '#ADB1B8', + 300: '#91969F', + 400: '#767C89', + 500: '#5D636F', + 600: '#444A55', + 700: '#2B303B', + 800: '#191E28', + 900: '#0B101B', + 1000: '#050912', + }, + + pink: { + 0: '#FFFFFF', + 5: '#FFF8FC', + 10: '#FFE7F6', + 50: '#FFC6E9', + 100: '#FF98D8', + 200: '#FF6FC8', + 300: '#FF40B6', + 400: '#E81899', + 500: '#C8047D', + 600: '#9A0060', + 700: '#7D004E', + 800: '#4B002F', + 900: '#240017', + 1000: '#050912', + }, + + red: { + 0: '#FFFFFF', + 5: '#FEF5F5', + 10: '#FFE7E7', + 50: '#FFC5C5', + 100: '#FF9B9C', + 200: '#FD7576', + 300: '#F15C5D', + 400: '#DB4546', + 500: '#CE2C2D', + 600: '#BB1A1B', + 700: '#790102', + 800: '#440000', + 900: '#250000', + 1000: '#050912', + }, + + green: { + 0: '#FFFFFF', + 5: '#F2FFFA', + 10: '#E4FFF4', + 50: '#BFFFE4', + 100: '#89FFCD', + 200: '#65F0B6', + 300: '#47E0A0', + 400: '#2DCA88', + 500: '#19BA76', + 600: '#059458', + 700: '#005E36', + 800: '#00321D', + 900: '#001C10', + 1000: '#050912', + }, + + yellow: { + 0: '#FFFFFF', + 5: '#FFFCF3', + 10: '#FFF6DE', + 50: '#FFEAB5', + 100: '#FFDC85', + 200: '#FFCF55', + 300: '#F8C23B', + 400: '#EBB222', + 500: '#DBA00D', + 600: '#C28B00', + 700: '#775602', + 800: '#382800', + 900: '#201700', + 1000: '#050912', + }, + + /******************* + * Semantic colors * + *******************/ + + primary: { + DEFAULT: 'var(--primary-brand)', + brand: 'var(--primary-brand)', + content: 'var(--primary-content)', + link: { + DEFAULT: 'var(--primary-link)', + hover: 'var(--primary-link-hover)', + }, + icon: 'var(--primary-icon)', + background: 'var(--primary-background)', + + interactive: { + DEFAULT: 'var(--primary-interactive)', + accent: 'var(--primary-interactive-accent)', + hover: 'var(--primary-interactive-hover)', + }, + border: { + DEFAULT: 'var(--primary-border)', + dark: 'var(--primary-border-dark)', + hover: 'var(--primary-border-hover)', + accent: 'var(--primary-border-accent)', + }, + + base: { + content: 'var(--primary-base-content)', + background: 'var(--primary-base-background)', + }, + }, + + secondary: { + DEFAULT: 'var(--secondary-brand)', + brand: 'var(--secondary-brand)', + content: 'var(--secondary-content)', + icon: 'var(--secondary-icon)', + interactive: { + accent: 'var(--primary-interactive-accent)', + hover: 'var(--secondary-interactive-hover)', + }, + }, + + tertiary: { + content: 'var(--tertiary-content)', + interactive: { + accent: 'var(--tertiary-interactive-accent)', + }, + }, + + positive: { + sentiment: 'var(--positive-sentiment)', + background: 'var(--positive-background)', + }, + + negative: { + sentiment: 'var(--negative-sentiment)', + background: 'var(--negative-background)', + }, + + warning: { + sentiment: 'var(--warning-sentiment)', + background: 'var(--warning-background)', + }, + + dialog: { + background: 'var(--dialog-background)', + interactive: { + disabled: 'var(--dialog-dialog-interactive-disabled)', + }, + }, + + + + + 'elevated-background': 'var(--elevated-background)', + 'neutral-background': 'var(--neutral-background)', + 'overlay-background': 'var(--overlay-background)', + 'divider-border': 'var(--divider-border)', + + 'grey-500-10': 'var(--grey-500-10)', + 'grey-500-20': 'var(--grey-500-20)', + + 'text-dark': 'var(--text-dark)', + 'text-light': 'var(--text-light)', + + + 'interactive-primary-pink': 'var(--interactive-primary-pink)', + 'interactive-primary-accent': 'var(--interactive-primary-accent)', + 'interactive-secondary': 'var(--interactive-secondary)', + 'interactive-tertiary': 'var(--interactive-tertiary)', + 'interactive-accent': 'var(--interactive-accent)', + + + 'content-primary': 'var(--content-primary)', + 'content-secondary': 'var(--content-secondary)', + 'content-tertiary': 'var(--content-tertiary)', + 'content-link-primary': 'var(--content-link-primary)', + 'content-link-hover': 'var(--content-link-hover)', + + 'background-primary': 'var(--background-primary)', + 'background-neutral': 'var(--background-neutral)', + 'background-elevated': 'var(--background-elevated)', + + 'icon-primary': 'var(--icon-primary)', + 'icon-secondary': 'var(--icon-secondary)', + + + 'border-divider-default': 'var(--border-divider-default)', + + + }, + }, + }, + + plugins: [daisyuiPlugin, require('tailwindcss-image-rendering')()], + + // https://daisyui.com/docs/config/ + daisyui: { + darkTheme: 'dark', // name of one of the included themes for dark mode + base: true, // applies background color and foreground color for root element by default + styled: true, // include daisyUI colors and design decisions for all components + utils: true, // adds responsive and modifier utility classes + rtl: false, // rotate style direction from left-to-right to right-to-left. You also need to add dir="rtl" to your html tag and install `tailwindcss-flip` plugin for Tailwind CSS. + prefix: '', // prefix for daisyUI classnames (components, modifiers and responsive class names. Not colors) + logs: false, // Shows info about daisyUI version and used config in the console when building your CSS + themes: [ + { + dark: { + 'color-scheme': 'dark', + '--btn-text-case': 'capitalize', + // '--rounded-box': '0.625rem', // 10px + + '--primary-brand': '#C8047D', // pink-500 + '--primary-content': '#F3F3F3', // grey-10 + '--primary-link': '#FF6FC8', // pink-200 + '--primary-link-hover': '#FFC6E9', // pink-50 + '--primary-icon': '#CACBCE', // grey-100 + '--primary-background': '#0B101B', // grey-900 + '--primary-interactive': '#C8047D', // pink-500 + '--primary-interactive-accent': '#E81899', // pink-400 + '--primary-interactive-hover': '#E81899', // pink-400 + '--primary-border-hover': '#FF6FC8', // pink-200 + '--primary-border-dark': '#5D636F', // grey-500 + '--primary-border-accent': '#E81899', // pink-400 + '--primary-base-background': '#FFFFFF', // grey-0 + '--primary-base-content': '#191E28', // grey-800 + + '--secondary-brand': '#E81899', // pink-400 + '--secondary-content': '#ADB1B8', // grey-200 + '--secondary-icon': '#2B303B', // grey-700 + + '--secondary-interactive-accent': '#2B303B', // grey-700 + '--secondary-interactive-hover': '#ADB1B8', // grey-200 + + '--tertiary-content': '#5D636F', // grey-500 + '--tertiary-interactive-accent': '#5D636F', // grey-500 + '--tertiary-interactive-hover': '#444A55', // grey-600 + + '--positive-sentiment': '#47E0A0', // green-300 + '--positive-background': '#00321D', // green-800 + + '--negative-sentiment': '#F15C5D', // red-300 + '--negative-background': '#440000', // red-800 + + '--warning-sentiment': '#EBB222', // yellow-400 + '--warning-background': '#382800', // yellow-800 + + '--elevated-background': '#191E28', // grey-800 + '--neutral-background': '#2B303B', // grey-700 + '--neutral-content': '#2B303B', // grey-800 + '--neutral-accent': '#2B303B', // grey-700 + '--overlay-background': 'rgba(12, 17, 28, 0.5)', // grey-900|50% + '--overlay-dialog': 'rgba(12, 17, 28, 0.90)', // grey-900|90% + '--divider-border': '#444A55', // grey-600 + '--dialog-background': '#2B303B', // grey-700 + '--dialog-dialog-interactive-disabled': '#444A55', // grey-600 + + + // ==Taikoons Color Customizations==// + '--grey-500-10': 'rgba(93, 99, 111, 0.1)', // grey-500, 10% opacity + '--grey-500-20': 'rgba(93, 99, 111, 0.2)', // grey-500, 20% opacity + + '--text-dark': '#f3f3f3', + '--text-light': '#444A55',// grey-600 + + '--neutral': '#2B303B', // grey-700 + + // figma's theme + '--interactive-primary-pink': '#C8047D', // pink 500 + '--interactive-primary-accent': '#E81899', // pink-400 + '--interactive-secondary': '#2b303b', // grey-700 + '--interactive-tertiary': '#444a55', // grey-600 + '--interactive-accent': '#5D636F', // grey-500 + + '--content-primary': '#F3F3F3', // grey-10 + '--content-secondary': '#ADB1B8', // grey-200 + '--content-tertiary': '#5D636F', // grey-500 + '--content-link-primary': '#FF6FC8', // pink-200 + '--content-link-hover': '#FFC6E9', // pink-50 + + '--border-divider-default': '#444A55', // grey-600 + + '--background-primary': '#0B101B', // grey-900 + '--background-neutral': '#2B303B', // grey-700 + '--background-elevated': '#191E28', // grey-800 + + '--icon-primary': '#CACBCE', // grey-100 + '--icon-secondary': '#2B303B', // grey-700 + // ================================ // + + primary: '#C8047D', // pink-500, + 'primary-focus': '#E81899', // pink-400 + 'primary-content': '#F3F3F3', // grey-10 + + secondary: '#E81899', // pink-400 + // 'secondary-focus': '', + 'secondary-content': '#ADB1B8', // grey-200 + + neutral: '#2B303B', // grey-700 + 'neutral-focus': '#444A55', // grey-600 + 'neutral-content': '#F3F3F3', // grey-10 + + 'base-100': '#0B101B', // grey-900 + // 'base-200': '', + // 'base-300': '', + 'base-content': '#F3F3F3', // grey-10 + + success: '#00321D', // green-800 + 'success-content': '#47E0A0', // green-300 + error: '#440000', // red-800 + 'error-content': '#F15C5D', // red-300 + warning: '#382800', // yellow-800 + 'warning-content': '#EBB222', // yellow-400 + }, + + light: { + 'color-scheme': 'light', + '--btn-text-case': 'capitalize', + + '--primary-brand': '#C8047D', // pink-500 + '--primary-content': '#191E28', // grey-800 + '--primary-link': '#C8047D', // pink-500 + '--primary-link-hover': '#E81899', // pink-400 + '--primary-icon': '#5D636F', // grey-500 + '--primary-background': '#FAFAFA', // grey-5 + '--primary-interactive': '#C8047D', // pink-500 + '--primary-interactive-accent': '#E81899', // pink-400 + '--primary-interactive-hover': '#E3E3E3', //grey-50 + '--primary-border-hover': '#FF6FC8', // pink-200 + '--primary-border-accent': '#E81899', // pink-400 + + // TODO: these two are yet to be decided + '--primary-base-background': '#FFFFFF', // grey-0 + '--primary-base-content': '#191E28', // grey-800 + + '--secondary-brand': '#E81899', // pink-400 + '--secondary-content': '#444A55', // grey-600 + '--secondary-icon': '#2B303B', // grey-700 + '--secondary-interactive-accent': '#E3E3E3', // grey-50 + '--secondary-interactive-hover': '##F3F3F3', // grey-10 + + '--tertiary-content': '#91969F', // grey-300 + + // TODO: these two are missing. Remain the same as dark theme + '--tertiary-interactive-hover': '#444A55', // grey-600 + '--tertiary-interactive-accent': '#5D636F', // grey-500 + + '--positive-sentiment': '#005E36', // green-700 + '--positive-background': '#BFFFE4', // green-50 + + '--negative-sentiment': '#BB1A1B', // red-600 + '--negative-background': '#FFE7E7', // red-10 + + '--warning-sentiment': '#775602', // yellow-700 + '--warning-background': '#FFF6DE', // yellow-10 + + '--elevated-background': '#e3e3e3', //#FAFAFA', // grey-5 + '--neutral-background': '#FFFFFF', // grey-0 + '--neutral-content': '#191E28', // grey-800 + '--neutral-accent': '#e3e3e3', // grey-50 + '--overlay-background': 'rgba(12, 17, 28, 0.2)', // grey-900|20% + '--overlay-dialog': 'rgba(12, 17, 28, 0.9)', // grey-900|20 + + + + '--dialog-background': '#FFFFFF', // grey-0 + '--dialog-dialog-interactive-disabled': '#E3E3E3', // grey-50 + + '--divider-border': '#CACBCE', // grey-100 + // ==Taikoons Color Customizations==// + + '--grey-500-10': 'rgba(250,250,250,0.5)', + '--grey-500-20': 'rgba(250,250,250,0.5)', + '--text-dark': '#191e28', + '--text-light': '#91969f', + '--neutral': '#E3E3E3', // grey-50 + + // figma's theme + '--interactive-primary-pink': '#C8047D', // pink 500 + '--interactive-primary-accent': '#E81899', // pink-400 + '--interactive-secondary': '#f3f3f3', // grey-10 + '--interactive-tertiary': '#e3e3e3', // grey-50 + '--interactive-accent': '#cacbce', // grey-100 + + '--content-primary': '#191E28', // grey-800 + '--content-secondary': '#444A55', // grey-600 + '--content-tertiary': '#91969F', // grey-300 + '--content-link-primary': '#C8047D', // pink-500 + '--content-link-hover': '#E81899', // pink-400 + + '--border-divider-default': '#CACBCE', // grey-100 + + '--background-primary': '#ffffff', // grey-5 + '--background-neutral': '#F8f8f8', // grey-50 + '--background-elevated': '#ffffff', // grey-5 + + '--icon-primary': '#5D636F', // grey-500 + '--icon-secondary': '#e3e3e3', // grey-50 + // ================================ // + + primary: '#C8047D', // pink-500, + 'primary-focus': '#E81899', // pink-400 + 'primary-content': '#191E28', // grey-800 + + secondary: '#E81899', // pink-400 + // 'secondary-focus': '', + 'secondary-content': '#444A55', // grey-600 + + neutral: '#E3E3E3', // grey-50 + 'neutral-focus': '#CACBCE', // grey-100 + 'neutral-content': '#191E28', // grey-800 + + 'base-100': '#FAFAFA', // grey-5 + // 'base-200': '', + // 'base-300': '', + 'base-content': '#191E28', // grey-800 + + success: '#BFFFE4', // green-50 + 'success-content': '#005E36', // green-700 + error: '#FFE7E7', // red-10 + 'error-content': '#BB1A1B', // red-600 + warning: '#FFF6DE', // yellow-10 + 'warning-content': '#775602', // yellow-700 + }, + }, + ], + }, +} diff --git a/packages/taikoon-ui/tests/test.ts b/packages/taikoon-ui/tests/test.ts new file mode 100644 index 0000000000..09e153e02c --- /dev/null +++ b/packages/taikoon-ui/tests/test.ts @@ -0,0 +1,6 @@ +import { expect, test } from '@playwright/test' + +test('index page has expected h1', async ({ page }) => { + await page.goto('/') + await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible() +}) diff --git a/packages/taikoon-ui/tsconfig.json b/packages/taikoon-ui/tsconfig.json new file mode 100644 index 0000000000..8478b23dbf --- /dev/null +++ b/packages/taikoon-ui/tsconfig.json @@ -0,0 +1,37 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler", + "paths": { + "$assets/*": ["./src/assets/*"], + "$components/*": ["./src/components/*"], + "$stores/*": ["./src/stores/*"], + "$config": ["./src/app.config.ts"], + "$lib/*": ["./src/lib/*"], + "$abi": ["./src/abi/index.ts"], + "$wagmi-config": ["./src/wagmi.config.ts"], + "$ui/*": ["./src/components/core/*"], + "$content/*": ["./src/content/*"], + "$modals": ["./src/components/modals/index.ts"], + "$generated/*": ["./src/generated/*"] + //"$bridgeConfig": ["./src/generated/bridgeConfig.ts"], + //"$chainConfig": ["./src/generated/chainConfig.ts"], + //"$relayerConfig": ["./src/generated/relayerConfig.ts"], + //"$customToken": ["./src/generated/customTokenConfig.ts"] + }, + "rootDirs": [".", "./.svelte-kit/types", "./$houdini/types"] + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias + // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in +} diff --git a/packages/taikoon-ui/vite.config.ts b/packages/taikoon-ui/vite.config.ts new file mode 100644 index 0000000000..3bfae646c2 --- /dev/null +++ b/packages/taikoon-ui/vite.config.ts @@ -0,0 +1,14 @@ +import { sveltekit } from '@sveltejs/kit/vite' +import tsconfigPaths from 'vite-tsconfig-paths' +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + plugins: [sveltekit(), tsconfigPaths()], + test: { + include: ['src/**/*.{test,spec}.{js,ts}'], + }, + optimizeDeps: { + exclude: ['@urql/svelte'], + } + // other properties +}) diff --git a/packages/taikoon-ui/wagmi.config.ts b/packages/taikoon-ui/wagmi.config.ts new file mode 100644 index 0000000000..4a03d585fa --- /dev/null +++ b/packages/taikoon-ui/wagmi.config.ts @@ -0,0 +1,50 @@ +import { StandardMerkleTree } from '@openzeppelin/merkle-tree'; +import { defineConfig } from '@wagmi/cli' +import type { Abi, Address } from 'abitype' +import { existsSync, mkdirSync,readFileSync, writeFileSync } from 'fs' + +import * as HoleskyDeployment from '../taikoon/deployments/holesky.json' +import * as LocalhostDeployment from '../taikoon/deployments/localhost.json' +import TaikoonToken from '../taikoon/out/TaikoonToken.sol/TaikoonToken.json' + + + +function generateNetworkWhitelist(network: string){ + const tree = StandardMerkleTree.load(JSON.parse( + readFileSync( + `../taikoon/data/whitelist/${network}.json`, + 'utf8') + )) + + writeFileSync(`./src/generated/whitelist/${network}.json`, + JSON.stringify(tree.dump(), null, 2)) + + console.log(`Whitelist merkle root for network ${network}: ${tree.root}`) + +} +function generateWhitelistJson() { + + const whitelistDir = "./src/generated/whitelist"; + if (!existsSync(whitelistDir)) { + mkdirSync(whitelistDir, { recursive: true }); + } + + generateNetworkWhitelist("hardhat"); + generateNetworkWhitelist("holesky"); +} + +generateWhitelistJson(); + +export default defineConfig({ + out: 'src/generated/abi/index.ts', + contracts: [ + { + name: 'TaikoonToken', + address: { + 31337: LocalhostDeployment.TaikoonToken as Address, + 17000: HoleskyDeployment.TaikoonToken as Address, + }, + abi: TaikoonToken.abi as Abi, + } + ], +}) diff --git a/packages/taikoon/.gitignore b/packages/taikoon/.gitignore index f62d06b744..298c2d3b21 100644 --- a/packages/taikoon/.gitignore +++ b/packages/taikoon/.gitignore @@ -41,3 +41,7 @@ data/images data/metadata lcov.info lib +data/whitelist/hardhat.csv +data/whitelist/holesky.csv +data/whitelist/mainnet.csv +data/whitelist/*.json diff --git a/packages/taikoon/data/whitelist/example.csv b/packages/taikoon/data/whitelist/example.csv new file mode 100644 index 0000000000..341495e1bd --- /dev/null +++ b/packages/taikoon/data/whitelist/example.csv @@ -0,0 +1,2 @@ +freeMints,address +100,0x0000000000000000000000000000000000000000 diff --git a/packages/taikoon/data/whitelist/hardhat.csv b/packages/taikoon/data/whitelist/hardhat.csv deleted file mode 100644 index 08b25dee50..0000000000 --- a/packages/taikoon/data/whitelist/hardhat.csv +++ /dev/null @@ -1,6 +0,0 @@ -freeMints,address -100,0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 -100,0x70997970C51812dc3A010C7d01b50e0d17dc79C8 -100,0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC -100,0x90F79bf6EB2c4f870365E785982E1f101E93b906 -100,0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65 diff --git a/packages/taikoon/data/whitelist/holesky.csv b/packages/taikoon/data/whitelist/holesky.csv deleted file mode 100644 index ca071f2c78..0000000000 --- a/packages/taikoon/data/whitelist/holesky.csv +++ /dev/null @@ -1,7 +0,0 @@ -freeMints,address -10,0x8f63e3cD0D14cAef993E59B4e01e3D404cF3c1B7 -10,0x2E2989015f5818A256EB967940454EfE8a0B4b5d -10,0x927a146e18294efb36edCacC99D9aCEA6aB16b95 -10,0x4757D97449acA795510b9f3152C6a9019A3545c3 -10,0x424bFb32f78731252a6BCeDc828E38e2701DAAEf -10,0xC66fAdfFeb6DA3b9A7FA3C71130F881e3a9B13fb diff --git a/packages/taikoon/package.json b/packages/taikoon/package.json index a7a0e67dba..4a3a23534c 100644 --- a/packages/taikoon/package.json +++ b/packages/taikoon/package.json @@ -27,7 +27,7 @@ "eslint-plugin-prettier": "^5.1.3", "eslint-plugin-promise": "^6.1.1", "ethers": "^5.7.2", - "solc": "0.7.3", + "solc": "0.8.24", "solhint": "^4.5.4", "ts-node": "^10.9.2", "typescript": "^5.2.2" diff --git a/packages/taikoon/script/js/generate-merkle-tree.js b/packages/taikoon/script/js/generate-merkle-tree.js index 08d8d19ada..0b95d156e6 100644 --- a/packages/taikoon/script/js/generate-merkle-tree.js +++ b/packages/taikoon/script/js/generate-merkle-tree.js @@ -32,3 +32,4 @@ async function main(network) { } main('hardhat') +main('holesky') diff --git a/packages/taikoon/script/sol/Deploy.s.sol b/packages/taikoon/script/sol/Deploy.s.sol index d37fa87adc..b66028f57f 100644 --- a/packages/taikoon/script/sol/Deploy.s.sol +++ b/packages/taikoon/script/sol/Deploy.s.sol @@ -36,7 +36,7 @@ contract DeployScript is Script { vm.startBroadcast(deployerPrivateKey); - bytes32 root = merkleMinters.root(); + bytes32 root = merkleMinters.getMerkleRoot(); string memory baseURI = utils.getIpfsBaseURI(); diff --git a/packages/taikoon/script/sol/MerkleMinters.s.sol b/packages/taikoon/script/sol/MerkleMinters.s.sol index 7e52b81a45..961db3990b 100644 --- a/packages/taikoon/script/sol/MerkleMinters.s.sol +++ b/packages/taikoon/script/sol/MerkleMinters.s.sol @@ -12,132 +12,84 @@ import { TaikoonToken } from "../../contracts/TaikoonToken.sol"; contract MerkleMintersScript is Script { using stdJson for string; + UtilsScript public utils; string public jsonLocation; uint256 public deployerPrivateKey; address public deployerAddress; - bytes32[] public leaves; + TaikoonToken token; - bytes32 public root; + // bytes32[] public leaves; - function setUp() public { - string memory treeJson = - vm.readFile(string.concat(vm.projectRoot(), "/data/whitelist/hardhat.json")); - bytes memory treeRaw = treeJson.parseRaw(".tree"); - leaves = abi.decode(treeRaw, (bytes32[])); + // bytes32[] public holeskyLeaves; - bytes memory rootRaw = treeJson.parseRaw(".root"); - root = abi.decode(rootRaw, (bytes32)); - } - /* - function getHoleskyCsvMinters() - public - view - returns (uint256[] memory freeMints, address[] memory minters) - { - string memory csvPath = './data/whitelist/holesky.csv'; - string memory line = vm.readLine(csvPath); - // extract header - line = vm.readLine(csvPath); - - freeMints = new uint256[](10); - minters = new address[](10); - - // read the csv lines - bool linesLeft = true; - uint256 lineCount = 0; - while (linesLeft) { - (uint256 _freeMints, address _minter) = CSVParser.parseLine(line); - - freeMints[lineCount] = _freeMints; - minters[lineCount] = _minter; - - console.log( - 'Free mints: %s, Paid mints: %s, Minter: %s', - freeMints[lineCount], - minters[lineCount] - ); - - lineCount++; - - line = vm.readLine(csvPath); - linesLeft = bytes(line).length >= 27; - } + bytes32 public holeskyRoot; - return (freeMints, minters); - } + bytes32 public localhostRoot; - */ + string public hardhatTreeJson; + string public holeskyTreeJson; - function getHardhatCsvMinters() - public - view - returns (uint256[] memory freeMints, address[] memory minters, bytes32[] memory) - { - uint256 minterCount = 5; - string memory csvPath = "./data/whitelist/hardhat.csv"; - string memory line = vm.readLine(csvPath); - // extract header - line = vm.readLine(csvPath); + function setUp() public { + utils = new UtilsScript(); + utils.setUp(); - freeMints = new uint256[](minterCount); - minters = new address[](minterCount); + deployerPrivateKey = utils.getPrivateKey(); + deployerAddress = utils.getAddress(); - // read the csv lines - bool linesLeft = true; - uint256 lineCount = 0; - while (linesLeft) { - (uint256 _freeMints, address _minter) = CSVParser.parseLine(line); + string memory path = utils.getContractJsonLocation(); + string memory json = vm.readFile(path); - freeMints[lineCount] = _freeMints; - minters[lineCount] = _minter; + // TaikoonToken + bytes memory addressRaw = json.parseRaw(".TaikoonToken"); + address tokenAddress = abi.decode(addressRaw, (address)); + token = TaikoonToken(tokenAddress); - console.log("Free mints: %s, Minter: %s", freeMints[lineCount], minters[lineCount]); + hardhatTreeJson = + vm.readFile(string.concat(vm.projectRoot(), "/data/whitelist/hardhat.json")); + //bytes memory treeRaw = hardhatTreeJson.parseRaw('.tree'); + // leaves = abi.decode(treeRaw, (bytes32[])); - lineCount++; + bytes memory rootRaw = hardhatTreeJson.parseRaw(".root"); + localhostRoot = abi.decode(rootRaw, (bytes32)); - line = vm.readLine(csvPath); - linesLeft = bytes(line).length >= 27; - } + holeskyTreeJson = + vm.readFile(string.concat(vm.projectRoot(), "/data/whitelist/holesky.json")); - return (freeMints, minters, leaves); + // treeRaw = holeskyTreeJson.parseRaw('.tree'); + // holeskyLeaves = abi.decode(treeRaw, (bytes32[])); + rootRaw = holeskyTreeJson.parseRaw(".root"); + holeskyRoot = abi.decode(rootRaw, (bytes32)); } - function getMerkleData() - public - view - returns (uint256[] memory freeMints, address[] memory minters, bytes32[] memory) - { + function getMerkleRoot() public view returns (bytes32) { uint256 chainId = block.chainid; - if (chainId == 31_337) { - return getHardhatCsvMinters(); - } /*else if (chainId == 17000) { - return getHoleskyCsvMinters(); - }*/ else { + return localhostRoot; + } else if (chainId == 17_000) { + return holeskyRoot; + } else { revert("Unsupported chainId"); } } - function getMerkleInfo() public view returns (bytes32, bytes32[] memory) { - return (root, leaves); - } - function run() public { - UtilsScript utils = new UtilsScript(); - utils.setUp(); - - deployerPrivateKey = utils.getPrivateKey(); - deployerAddress = utils.getAddress(); vm.startBroadcast(deployerPrivateKey); + uint256 chainId = block.chainid; - string memory path = utils.getContractJsonLocation(); - string memory json = vm.readFile(path); - - // TaikoonToken - bytes memory addressRaw = json.parseRaw(".TaikoonToken"); - address tokenAddress = abi.decode(addressRaw, (address)); - TaikoonToken token = TaikoonToken(tokenAddress); + bytes32 root = getMerkleRoot(); + bytes32[] memory leaves; + if (chainId == 31_337) { + // hardhat/localhost + bytes memory treeRaw = hardhatTreeJson.parseRaw(".tree"); + leaves = abi.decode(treeRaw, (bytes32[])); + } else if (chainId == 17_000) { + // holesky + bytes memory treeRaw = holeskyTreeJson.parseRaw(".tree"); + leaves = abi.decode(treeRaw, (bytes32[])); + } else { + revert("Unsupported chainId"); + } Merkle tree = new Merkle(); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9330db4039..520a2dc564 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,10 +26,10 @@ importers: version: 2.26.1(debug@4.3.4) '@wagmi/connectors': specifier: ^4.1.18 - version: 4.1.18(@wagmi/core@2.6.9)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) + version: 4.1.18(@wagmi/core@2.8.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) '@wagmi/core': - specifier: ^2.6.9 - version: 2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) + specifier: ^2.8.0 + version: 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) '@walletconnect/ethereum-provider': specifier: ^2.12.2 version: 2.12.2(react@18.2.0) @@ -38,7 +38,7 @@ importers: version: 2.6.2(react@18.2.0) '@web3modal/wagmi': specifier: ^4.1.11 - version: 4.1.11(@wagmi/connectors@4.1.18)(@wagmi/core@2.6.9)(react@18.2.0)(viem@2.7.11) + version: 4.1.11(@wagmi/connectors@4.1.18)(@wagmi/core@2.8.0)(react@18.2.0)(viem@2.7.11) '@zerodevx/svelte-toast': specifier: ^0.9.5 version: 0.9.5(svelte@4.2.12) @@ -122,8 +122,8 @@ importers: specifier: ^12.0.0 version: 12.0.0(eslint@8.56.0) eslint-plugin-svelte: - specifier: ^2.35.1 - version: 2.35.1(eslint@8.56.0)(svelte@4.2.12) + specifier: ^2.38.0 + version: 2.38.0(eslint@8.56.0)(svelte@4.2.12) ethereum-address: specifier: ^0.0.4 version: 0.0.4 @@ -162,7 +162,7 @@ importers: version: 5.4.3 vite: specifier: ^4.5.3 - version: 4.5.3(@types/node@20.11.30) + version: 4.5.3(@types/node@20.12.7) vite-tsconfig-paths: specifier: ^4.3.2 version: 4.3.2(typescript@5.4.3)(vite@4.5.3) @@ -185,8 +185,8 @@ importers: packages/guardian-prover-health-check-ui: dependencies: '@wagmi/core': - specifier: ^2.6.9 - version: 2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.9.16) + specifier: ^2.8.0 + version: 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.9.16) axios: specifier: ^1.6.7 version: 1.6.7(debug@4.3.4) @@ -195,7 +195,7 @@ importers: version: 4.0.0(svelte@4.2.13) viem: specifier: ^2.9.16 - version: 2.9.16(typescript@5.4.3)(zod@3.22.4) + version: 2.9.16(typescript@5.4.3) devDependencies: '@playwright/test': specifier: ^1.43.1 @@ -231,8 +231,8 @@ importers: specifier: ^9.1.0 version: 9.1.0(eslint@8.56.0) eslint-plugin-svelte: - specifier: ^2.35.1 - version: 2.35.1(eslint@8.56.0)(svelte@4.2.13) + specifier: ^2.38.0 + version: 2.38.0(eslint@8.56.0)(svelte@4.2.13) postcss: specifier: ^8.4.38 version: 8.4.38 @@ -253,7 +253,7 @@ importers: version: 4.2.13 svelte-check: specifier: ^3.6.9 - version: 3.6.9(postcss@8.4.38)(svelte@4.2.13) + version: 3.6.9(@babel/core@7.23.9)(postcss@8.4.38)(svelte@4.2.13) tailwindcss: specifier: ^3.4.3 version: 3.4.3 @@ -265,7 +265,7 @@ importers: version: 5.4.3 vite: specifier: ^4.5.3 - version: 4.5.3(@types/node@20.11.30) + version: 4.5.3(@types/node@20.12.7) vite-tsconfig-paths: specifier: ^4.3.2 version: 4.3.2(typescript@5.4.3)(vite@4.5.3) @@ -299,7 +299,7 @@ importers: devDependencies: '@types/node': specifier: ^20.11.30 - version: 20.11.30 + version: 20.12.7 '@typescript-eslint/eslint-plugin': specifier: ^7.4.0 version: 7.4.0(@typescript-eslint/parser@7.7.0)(eslint@8.55.0)(typescript@5.4.3) @@ -331,14 +331,14 @@ importers: specifier: ^5.7.2 version: 5.7.2 solc: - specifier: 0.7.3 - version: 0.7.3 + specifier: 0.8.24 + version: 0.8.24 solhint: specifier: ^4.5.4 version: 4.5.4(typescript@5.4.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.30)(typescript@5.4.3) + version: 10.9.2(@types/node@20.12.7)(typescript@5.4.3) typescript: specifier: ^5.2.2 version: 5.4.3 @@ -371,7 +371,7 @@ importers: devDependencies: '@types/node': specifier: ^20.11.30 - version: 20.11.30 + version: 20.12.7 '@typescript-eslint/eslint-plugin': specifier: ^7.4.0 version: 7.4.0(@typescript-eslint/parser@7.7.0)(eslint@8.56.0)(typescript@5.4.3) @@ -403,14 +403,14 @@ importers: specifier: ^5.7.2 version: 5.7.2 solc: - specifier: 0.7.3 - version: 0.7.3 + specifier: 0.8.24 + version: 0.8.24 solhint: specifier: ^4.5.4 version: 4.5.4(typescript@5.4.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.30)(typescript@5.4.3) + version: 10.9.2(@types/node@20.12.7)(typescript@5.4.3) typescript: specifier: ^5.2.2 version: 5.4.3 @@ -459,7 +459,7 @@ importers: devDependencies: '@types/node': specifier: ^20.11.30 - version: 20.11.30 + version: 20.12.7 '@typescript-eslint/eslint-plugin': specifier: ^7.4.0 version: 7.4.0(@typescript-eslint/parser@7.7.0)(eslint@8.56.0)(typescript@5.4.3) @@ -491,18 +491,166 @@ importers: specifier: ^5.7.2 version: 5.7.2 solc: - specifier: 0.7.3 - version: 0.7.3 + specifier: 0.8.24 + version: 0.8.24 solhint: specifier: ^4.5.4 version: 4.5.4(typescript@5.4.3) ts-node: specifier: ^10.9.2 - version: 10.9.2(@types/node@20.11.30)(typescript@5.4.3) + version: 10.9.2(@types/node@20.12.7)(typescript@5.4.3) typescript: specifier: ^5.2.2 version: 5.4.3 + packages/taikoon-ui: + dependencies: + '@openzeppelin/merkle-tree': + specifier: ^1.0.6 + version: 1.0.6 + '@wagmi/cli': + specifier: ^2.1.4 + version: 2.1.4(typescript@5.4.3) + '@wagmi/connectors': + specifier: ^4.1.18 + version: 4.1.18(@wagmi/core@2.8.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.9.27) + '@wagmi/core': + specifier: ^2.8.0 + version: 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.9.27) + '@web3modal/common': + specifier: ^4.1.1 + version: 4.1.11 + '@web3modal/ui': + specifier: ^4.1.1 + version: 4.1.11 + '@web3modal/wagmi': + specifier: ^4.1.1 + version: 4.1.11(@wagmi/connectors@4.1.18)(@wagmi/core@2.8.0)(react@18.2.0)(viem@2.9.27) + '@zerodevx/svelte-toast': + specifier: ^0.9.5 + version: 0.9.5(svelte@4.2.13) + autoprefixer: + specifier: ^10.4.19 + version: 10.4.19(postcss@8.4.38) + daisyui: + specifier: ^4.10.1 + version: 4.10.1(postcss@8.4.38) + dayjs: + specifier: ^1.11.10 + version: 1.11.10 + debug: + specifier: ^4.3.4 + version: 4.3.4 + minidenticons: + specifier: ^4.2.1 + version: 4.2.1 + postcss: + specifier: ^8.4.38 + version: 8.4.38 + svelte-countdown: + specifier: ^1.1.2 + version: 1.1.2 + tailwindcss: + specifier: ^3.4.3 + version: 3.4.3 + viem: + specifier: ^2.9.26 + version: 2.9.27(typescript@5.4.3)(zod@3.22.4) + devDependencies: + '@chromatic-com/storybook': + specifier: ^1.3.1 + version: 1.3.3(react@18.2.0) + '@playwright/test': + specifier: ^1.28.1 + version: 1.43.1 + '@sveltejs/adapter-auto': + specifier: ^3.0.0 + version: 3.2.0(@sveltejs/kit@2.5.5) + '@sveltejs/kit': + specifier: ^2.0.0 + version: 2.5.5(@sveltejs/vite-plugin-svelte@3.1.0)(svelte@4.2.13)(vite@5.1.3) + '@sveltejs/vite-plugin-svelte': + specifier: ^3.0.0 + version: 3.1.0(svelte@4.2.13)(vite@5.1.3) + '@types/eslint': + specifier: ^8.56.0 + version: 8.56.10 + '@types/node': + specifier: ^20.12.7 + version: 20.12.7 + '@typescript-eslint/eslint-plugin': + specifier: ^7.0.0 + version: 7.4.0(@typescript-eslint/parser@7.7.0)(eslint@8.56.0)(typescript@5.4.3) + '@typescript-eslint/parser': + specifier: ^7.0.0 + version: 7.7.0(eslint@8.56.0)(typescript@5.4.3) + convert-csv-to-json: + specifier: ^2.44.0 + version: 2.46.0 + eslint: + specifier: ^8.56.0 + version: 8.56.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.56.0) + eslint-plugin-simple-import-sort: + specifier: ^12.0.0 + version: 12.0.0(eslint@8.56.0) + eslint-plugin-storybook: + specifier: ^0.8.0 + version: 0.8.0(eslint@8.56.0)(typescript@5.4.3) + eslint-plugin-svelte: + specifier: ^2.38.0 + version: 2.38.0(eslint@8.56.0)(svelte@4.2.13) + p-map: + specifier: ^7.0.2 + version: 7.0.2 + prettier: + specifier: ^3.1.1 + version: 3.2.5 + prettier-plugin-svelte: + specifier: ^3.1.2 + version: 3.2.2(prettier@3.2.5)(svelte@4.2.13) + raw-body: + specifier: ^2.5.2 + version: 2.5.2 + svelte: + specifier: ^4.2.7 + version: 4.2.13 + svelte-check: + specifier: ^3.6.0 + version: 3.6.9(@babel/core@7.23.9)(postcss@8.4.38)(svelte@4.2.13) + svelte-copy: + specifier: ^1.4.2 + version: 1.4.2(svelte@4.2.13) + svelte-i18n: + specifier: ^4.0.0 + version: 4.0.0(svelte@4.2.13) + svelte-scrolling: + specifier: ^1.4.0 + version: 1.4.0(svelte@4.2.13) + tailwindcss-image-rendering: + specifier: ^1.0.2 + version: 1.0.2 + tslib: + specifier: ^2.4.1 + version: 2.6.2 + typescript: + specifier: ^5.0.0 + version: 5.4.3 + vite: + specifier: ^5.0.3 + version: 5.1.3(@types/node@20.12.7) + vite-tsconfig-paths: + specifier: ^4.3.2 + version: 4.3.2(typescript@5.4.3)(vite@5.1.3) + vitest: + specifier: ^1.2.0 + version: 1.5.0(@types/node@20.12.7) + which: + specifier: ^4.0.0 + version: 4.0.0 + packages: /@aashutoshrathi/word-wrap@1.2.6: @@ -516,7 +664,6 @@ packages: /@alloc/quick-lru@5.2.0: resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - dev: true /@ampproject/remapping@2.2.1: resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} @@ -1950,6 +2097,21 @@ packages: '@chainsafe/is-ip': 2.0.2 dev: false + /@chromatic-com/storybook@1.3.3(react@18.2.0): + resolution: {integrity: sha512-1y9r691T5vVGDZ0HY3YrCXUnvtrT2YrhDuvDZSvYSNUVpM/Imz6i1dnNMKb3eoI1qRsH55mI4zCt+Iq94NLedQ==} + engines: {node: '>=16.0.0', yarn: '>=1.22.18'} + dependencies: + chromatic: 11.3.0 + filesize: 10.1.1 + jsonfile: 6.1.0 + react-confetti: 6.1.0(react@18.2.0) + strip-ansi: 7.1.0 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + - react + dev: true + /@coinbase/wallet-sdk@3.9.1: resolution: {integrity: sha512-cGUE8wm1/cMI8irRMVOqbFWYcnNugqCtuy2lnnHfgloBg+GRLs9RsrkOUDMdv/StfUeeKhCDyYudsXXvcL1xIA==} dependencies: @@ -2891,7 +3053,6 @@ packages: dependencies: '@formatjs/intl-localematcher': 0.5.4 tslib: 2.6.2 - dev: false /@formatjs/fast-memoize@1.2.1: resolution: {integrity: sha512-Rg0e76nomkz3vF9IPlKeV+Qynok0r7YZjL6syLz4/urSg0IbjPZCB/iYUMNsYA643gh4mgrX3T7KEIFIxJBQeg==} @@ -2903,7 +3064,6 @@ packages: resolution: {integrity: sha512-hnk/nY8FyrL5YxwP9e4r9dqeM6cAbo8PeU9UjyXojZMNvVad2Z06FAVHyR3Ecw6fza+0GH7vdJgiKIVXTMbSBA==} dependencies: tslib: 2.6.2 - dev: false /@formatjs/icu-messageformat-parser@2.1.0: resolution: {integrity: sha512-Qxv/lmCN6hKpBSss2uQ8IROVnta2r9jd3ymUEIjm2UyIkUCHVcbUVRGL/KS/wv7876edvsPe+hjHVJ4z8YuVaw==} @@ -2919,7 +3079,6 @@ packages: '@formatjs/ecma402-abstract': 1.18.2 '@formatjs/icu-skeleton-parser': 1.8.0 tslib: 2.6.2 - dev: false /@formatjs/icu-skeleton-parser@1.3.6: resolution: {integrity: sha512-I96mOxvml/YLrwU2Txnd4klA7V8fRhb6JG/4hm3VMNmeJo1F03IpV2L3wWt7EweqNLES59SZ4d6hVOPCSf80Bg==} @@ -2933,7 +3092,6 @@ packages: dependencies: '@formatjs/ecma402-abstract': 1.18.2 tslib: 2.6.2 - dev: false /@formatjs/intl-localematcher@0.2.25: resolution: {integrity: sha512-YmLcX70BxoSopLFdLr1Ds99NdlTI2oWoLbaUW2M406lxOIPzE1KQhRz2fPUkq34xVZQaihCoU29h0KK7An3bhA==} @@ -2945,7 +3103,6 @@ packages: resolution: {integrity: sha512-zTwEpWOzZ2CiKcB93BLngUX59hQkuZjT2+SAQEscSm52peDW/getsawMcWF1rGRpMCX6D7nSJA3CzJ8gn13N/g==} dependencies: tslib: 2.6.2 - dev: false /@hapi/hoek@9.3.0: resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -3217,7 +3374,6 @@ packages: strip-ansi-cjs: /strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true /@isaacs/ttlcache@1.4.1: resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} @@ -3242,7 +3398,7 @@ packages: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.30 + '@types/node': 20.12.7 jest-mock: 29.7.0 dev: false @@ -3252,7 +3408,7 @@ packages: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.11.30 + '@types/node': 20.12.7 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3270,7 +3426,7 @@ packages: dependencies: '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.30 + '@types/node': 20.12.7 '@types/yargs': 15.0.19 chalk: 4.1.2 dev: false @@ -3282,7 +3438,7 @@ packages: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.11.30 + '@types/node': 20.12.7 '@types/yargs': 17.0.32 chalk: 4.1.2 dev: false @@ -3918,12 +4074,10 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: true /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: true /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} @@ -3931,7 +4085,6 @@ packages: dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - dev: true /@openzeppelin/contracts-upgradeable@4.9.6: resolution: {integrity: sha512-m4iHazOsOCv1DgM7eD7GupTJ+NFVujRZt1wzddDPSVGpWdKq1SKkla5htKG7+IS4d2XOCtzkUNwRZ7Vq5aEUMA==} @@ -4106,7 +4259,6 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} requiresBuild: true - dev: true optional: true /@pkgr/utils@2.4.2: @@ -4894,6 +5046,12 @@ packages: '@stablelib/wipe': 1.0.1 dev: false + /@storybook/csf@0.0.1: + resolution: {integrity: sha512-USTLkZze5gkel8MYCujSRBVIrUQ3YPBrLOx7GNk/0wttvVtlzWXAq9eLbQ4p/NicGxP+3T7KPEMVV//g+yubpw==} + dependencies: + lodash: 4.17.21 + dev: true + /@sveltejs/adapter-auto@3.2.0(@sveltejs/kit@1.30.4): resolution: {integrity: sha512-She5nKT47kwHE18v9NMe6pbJcvULr82u0V3yZ0ej3n1laWKGgkgdEABE9/ak5iDPs93LqsBkuIo51kkwCLBjJA==} peerDependencies: @@ -4908,7 +5066,7 @@ packages: peerDependencies: '@sveltejs/kit': ^2.0.0 dependencies: - '@sveltejs/kit': 2.5.5(@sveltejs/vite-plugin-svelte@3.1.0)(svelte@4.2.13)(vite@4.5.3) + '@sveltejs/kit': 2.5.5(@sveltejs/vite-plugin-svelte@3.1.0)(svelte@4.2.13)(vite@5.1.3) import-meta-resolve: 4.0.0 dev: true @@ -4943,7 +5101,7 @@ packages: svelte: 4.2.12 tiny-glob: 0.2.9 undici: 5.28.3 - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) transitivePeerDependencies: - supports-color dev: true @@ -4972,7 +5130,34 @@ packages: sirv: 2.0.4 svelte: 4.2.13 tiny-glob: 0.2.9 - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) + dev: true + + /@sveltejs/kit@2.5.5(@sveltejs/vite-plugin-svelte@3.1.0)(svelte@4.2.13)(vite@5.1.3): + resolution: {integrity: sha512-ULe3PB00q4+wYRL+IS5FDPsCEVnhEITofm7b9Yz8malcH3r1SAnW/JJ6T13hIMeu8QNRIuVQWo+P4+2VklbnLQ==} + engines: {node: '>=18.13'} + hasBin: true + requiresBuild: true + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.3 + dependencies: + '@sveltejs/vite-plugin-svelte': 3.1.0(svelte@4.2.13)(vite@5.1.3) + '@types/cookie': 0.6.0 + cookie: 0.6.0 + devalue: 4.3.2 + esm-env: 1.0.0 + import-meta-resolve: 4.0.0 + kleur: 4.1.5 + magic-string: 0.30.9 + mrmime: 2.0.0 + sade: 1.8.1 + set-cookie-parser: 2.6.0 + sirv: 2.0.4 + svelte: 4.2.13 + tiny-glob: 0.2.9 + vite: 5.1.3(@types/node@20.12.7) dev: true /@sveltejs/vite-plugin-svelte-inspector@1.0.4(@sveltejs/vite-plugin-svelte@2.5.3)(svelte@4.2.12)(vite@4.5.3): @@ -4986,7 +5171,7 @@ packages: '@sveltejs/vite-plugin-svelte': 2.5.3(svelte@4.2.12)(vite@4.5.3) debug: 4.3.4 svelte: 4.2.12 - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) transitivePeerDependencies: - supports-color dev: true @@ -5002,7 +5187,23 @@ packages: '@sveltejs/vite-plugin-svelte': 3.1.0(svelte@4.2.13)(vite@4.5.3) debug: 4.3.4 svelte: 4.2.13 - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) + transitivePeerDependencies: + - supports-color + dev: true + + /@sveltejs/vite-plugin-svelte-inspector@2.0.0(@sveltejs/vite-plugin-svelte@3.1.0)(svelte@4.2.13)(vite@5.1.3): + resolution: {integrity: sha512-gjr9ZFg1BSlIpfZ4PRewigrvYmHWbDrq2uvvPB1AmTWKuM+dI1JXQSUu2pIrYLb/QncyiIGkFDFKTwJ0XqQZZg==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 3.1.0(svelte@4.2.13)(vite@5.1.3) + debug: 4.3.4 + svelte: 4.2.13 + vite: 5.1.3(@types/node@20.12.7) transitivePeerDependencies: - supports-color dev: true @@ -5021,7 +5222,7 @@ packages: magic-string: 0.30.9 svelte: 4.2.12 svelte-hmr: 0.15.3(svelte@4.2.12) - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) vitefu: 0.2.5(vite@4.5.3) transitivePeerDependencies: - supports-color @@ -5041,12 +5242,32 @@ packages: magic-string: 0.30.9 svelte: 4.2.13 svelte-hmr: 0.16.0(svelte@4.2.13) - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) vitefu: 0.2.5(vite@4.5.3) transitivePeerDependencies: - supports-color dev: true + /@sveltejs/vite-plugin-svelte@3.1.0(svelte@4.2.13)(vite@5.1.3): + resolution: {integrity: sha512-sY6ncCvg+O3njnzbZexcVtUqOBE3iYmQPJ9y+yXSkOwG576QI/xJrBnQSRXFLGwJNBa0T78JEKg5cIR0WOAuUw==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 2.0.0(@sveltejs/vite-plugin-svelte@3.1.0)(svelte@4.2.13)(vite@5.1.3) + debug: 4.3.4 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.9 + svelte: 4.2.13 + svelte-hmr: 0.16.0(svelte@4.2.13) + vite: 5.1.3(@types/node@20.12.7) + vitefu: 0.2.5(vite@5.1.3) + transitivePeerDependencies: + - supports-color + dev: true + /@szmarczak/http-timer@5.0.1: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} @@ -5127,13 +5348,20 @@ packages: /@types/dns-packet@5.6.5: resolution: {integrity: sha512-qXOC7XLOEe43ehtWJCMnQXvgcIpv6rPmQ1jXT98Ad8A3TB1Ue50jsCbSSSyuazScEuZ/Q026vHbrOTVkmwA+7Q==} dependencies: - '@types/node': 20.11.30 + '@types/node': 20.12.7 dev: false /@types/dom-screen-wake-lock@1.0.3: resolution: {integrity: sha512-3Iten7X3Zgwvk6kh6/NRdwN7WbZ760YgFCsF5AxDifltUQzW1RaW+WRmcVtgwFzLjaNu64H+0MPJ13yRa8g3Dw==} dev: false + /@types/eslint@8.56.10: + resolution: {integrity: sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + /@types/estree@1.0.5: resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -5191,8 +5419,8 @@ packages: undici-types: 5.26.5 dev: false - /@types/node@20.11.30: - resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==} + /@types/node@20.12.7: + resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} dependencies: undici-types: 5.26.5 @@ -5217,7 +5445,7 @@ packages: /@types/secp256k1@4.0.6: resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} dependencies: - '@types/node': 20.11.30 + '@types/node': 20.12.7 dev: false /@types/semver@7.5.7: @@ -5348,6 +5576,14 @@ packages: - supports-color dev: true + /@typescript-eslint/scope-manager@5.62.0: + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + dev: true + /@typescript-eslint/scope-manager@7.4.0: resolution: {integrity: sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -5404,6 +5640,11 @@ packages: - supports-color dev: true + /@typescript-eslint/types@5.62.0: + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + /@typescript-eslint/types@7.4.0: resolution: {integrity: sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -5414,6 +5655,27 @@ packages: engines: {node: ^18.18.0 || >=20.0.0} dev: true + /@typescript-eslint/typescript-estree@5.62.0(typescript@5.4.3): + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.6.0 + tsutils: 3.21.0(typescript@5.4.3) + typescript: 5.4.3 + transitivePeerDependencies: + - supports-color + dev: true + /@typescript-eslint/typescript-estree@7.4.0(typescript@5.4.3): resolution: {integrity: sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -5458,6 +5720,26 @@ packages: - supports-color dev: true + /@typescript-eslint/utils@5.62.0(eslint@8.56.0)(typescript@5.4.3): + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.7 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.3) + eslint: 8.56.0 + eslint-scope: 5.1.1 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + /@typescript-eslint/utils@7.4.0(eslint@8.55.0)(typescript@5.4.3): resolution: {integrity: sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -5496,6 +5778,14 @@ packages: - typescript dev: true + /@typescript-eslint/visitor-keys@5.62.0: + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + dev: true + /@typescript-eslint/visitor-keys@7.4.0: resolution: {integrity: sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -5644,14 +5934,13 @@ packages: picocolors: 1.0.0 prettier: 3.2.5 typescript: 5.4.3 - viem: 2.9.16(typescript@5.4.3)(zod@3.22.4) + viem: 2.9.27(typescript@5.4.3)(zod@3.22.4) zod: 3.22.4 transitivePeerDependencies: - bufferutil - utf-8-validate - dev: true - /@wagmi/connectors@4.1.18(@wagmi/core@2.6.9)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11): + /@wagmi/connectors@4.1.18(@wagmi/core@2.8.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11): resolution: {integrity: sha512-K/iLH/Z8jwvgPAYESU/uCQtQBvcIR1Jrqk+t2uCDSxew/tYtkOo2yOjtaPuOb+xJ5OrMGg+0tVHhGChYXry9Ow==} peerDependencies: '@wagmi/core': 2.6.9 @@ -5665,7 +5954,7 @@ packages: '@metamask/sdk': 0.14.3(react-native@0.73.4)(react@18.2.0) '@safe-global/safe-apps-provider': 0.18.1(typescript@5.4.3) '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.4.3) - '@wagmi/core': 2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) + '@wagmi/core': 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) '@walletconnect/ethereum-provider': 2.11.2(react@18.2.0) '@walletconnect/modal': 2.6.2(react@18.2.0) typescript: 5.4.3 @@ -5695,8 +5984,52 @@ packages: - zod dev: false - /@wagmi/core@2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.7.11): - resolution: {integrity: sha512-AbNbHK+m60mfMTds0flv5YYJGp+JSz8O8ikzX+T7MdemFrYA9tZr6G+iSEnf+JLtcgiaCgQqUwac/WmmTkDiMA==} + /@wagmi/connectors@4.1.18(@wagmi/core@2.8.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.9.27): + resolution: {integrity: sha512-K/iLH/Z8jwvgPAYESU/uCQtQBvcIR1Jrqk+t2uCDSxew/tYtkOo2yOjtaPuOb+xJ5OrMGg+0tVHhGChYXry9Ow==} + peerDependencies: + '@wagmi/core': 2.6.9 + typescript: '>=5.0.4' + viem: 2.x + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@coinbase/wallet-sdk': 3.9.1 + '@metamask/sdk': 0.14.3(react-native@0.73.4)(react@18.2.0) + '@safe-global/safe-apps-provider': 0.18.1(typescript@5.4.3) + '@safe-global/safe-apps-sdk': 8.1.0(typescript@5.4.3) + '@wagmi/core': 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.9.27) + '@walletconnect/ethereum-provider': 2.11.2(react@18.2.0) + '@walletconnect/modal': 2.6.2(react@18.2.0) + typescript: 5.4.3 + viem: 2.9.27(typescript@5.4.3)(zod@3.22.4) + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/kv' + - bufferutil + - encoding + - react + - react-dom + - react-native + - rollup + - supports-color + - utf-8-validate + - zod + dev: false + + /@wagmi/core@2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.7.11): + resolution: {integrity: sha512-u0CWfbpdv2T3jE1yZQPwxvLlUVMymMoy73g6UE4XYNilF+EjdYu43EjWNvvB9lJcfSyYk6/VdKNHxJ2G+iBxYw==} peerDependencies: '@tanstack/query-core': '>=5.0.0' typescript: '>=5.0.4' @@ -5721,8 +6054,34 @@ packages: - zod dev: false - /@wagmi/core@2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.9.16): - resolution: {integrity: sha512-AbNbHK+m60mfMTds0flv5YYJGp+JSz8O8ikzX+T7MdemFrYA9tZr6G+iSEnf+JLtcgiaCgQqUwac/WmmTkDiMA==} + /@wagmi/core@2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.9.16): + resolution: {integrity: sha512-u0CWfbpdv2T3jE1yZQPwxvLlUVMymMoy73g6UE4XYNilF+EjdYu43EjWNvvB9lJcfSyYk6/VdKNHxJ2G+iBxYw==} + peerDependencies: + '@tanstack/query-core': '>=5.0.0' + typescript: '>=5.0.4' + viem: 2.x + peerDependenciesMeta: + '@tanstack/query-core': + optional: true + typescript: + optional: true + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.5(typescript@5.4.3) + typescript: 5.4.3 + viem: 2.9.16(typescript@5.4.3) + zustand: 4.4.1(react@18.2.0) + transitivePeerDependencies: + - '@types/react' + - bufferutil + - immer + - react + - utf-8-validate + - zod + dev: false + + /@wagmi/core@2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.9.27): + resolution: {integrity: sha512-u0CWfbpdv2T3jE1yZQPwxvLlUVMymMoy73g6UE4XYNilF+EjdYu43EjWNvvB9lJcfSyYk6/VdKNHxJ2G+iBxYw==} peerDependencies: '@tanstack/query-core': '>=5.0.0' typescript: '>=5.0.4' @@ -5736,7 +6095,7 @@ packages: eventemitter3: 5.0.1 mipd: 0.0.5(typescript@5.4.3) typescript: 5.4.3 - viem: 2.9.16(typescript@5.4.3)(zod@3.22.4) + viem: 2.9.27(typescript@5.4.3)(zod@3.22.4) zustand: 4.4.1(react@18.2.0) transitivePeerDependencies: - '@types/react' @@ -6406,7 +6765,7 @@ packages: qrcode: 1.5.3 dev: false - /@web3modal/wagmi@4.1.11(@wagmi/connectors@4.1.18)(@wagmi/core@2.6.9)(react@18.2.0)(viem@2.7.11): + /@web3modal/wagmi@4.1.11(@wagmi/connectors@4.1.18)(@wagmi/core@2.8.0)(react@18.2.0)(viem@2.7.11): resolution: {integrity: sha512-VoXV9idD0yV7jx0F2Xk722VXqQNCDKqDc+LR8WsuOU64TiTLJx9UDQpNcoigbC3bYCi/4Cpw41iSGgs7utbgyQ==} peerDependencies: '@wagmi/connectors': '>=4.0.0' @@ -6423,8 +6782,8 @@ packages: vue: optional: true dependencies: - '@wagmi/connectors': 4.1.18(@wagmi/core@2.6.9)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) - '@wagmi/core': 2.6.9(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) + '@wagmi/connectors': 4.1.18(@wagmi/core@2.8.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) + '@wagmi/core': 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.7.11) '@web3modal/polyfills': 4.1.11 '@web3modal/scaffold': 4.1.11(react@18.2.0) '@web3modal/scaffold-react': 4.1.11(react@18.2.0) @@ -6437,6 +6796,37 @@ packages: - '@types/react' dev: false + /@web3modal/wagmi@4.1.11(@wagmi/connectors@4.1.18)(@wagmi/core@2.8.0)(react@18.2.0)(viem@2.9.27): + resolution: {integrity: sha512-VoXV9idD0yV7jx0F2Xk722VXqQNCDKqDc+LR8WsuOU64TiTLJx9UDQpNcoigbC3bYCi/4Cpw41iSGgs7utbgyQ==} + peerDependencies: + '@wagmi/connectors': '>=4.0.0' + '@wagmi/core': '>=2.0.0' + react: '>=17' + react-dom: '>=17' + viem: '>=2.0.0' + vue: '>=3' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + vue: + optional: true + dependencies: + '@wagmi/connectors': 4.1.18(@wagmi/core@2.8.0)(react-native@0.73.4)(react@18.2.0)(typescript@5.4.3)(viem@2.9.27) + '@wagmi/core': 2.8.0(react@18.2.0)(typescript@5.4.3)(viem@2.9.27) + '@web3modal/polyfills': 4.1.11 + '@web3modal/scaffold': 4.1.11(react@18.2.0) + '@web3modal/scaffold-react': 4.1.11(react@18.2.0) + '@web3modal/scaffold-utils': 4.1.11(react@18.2.0) + '@web3modal/scaffold-vue': 4.1.11(react@18.2.0) + '@web3modal/siwe': 4.1.11(react@18.2.0) + react: 18.2.0 + viem: 2.9.27(typescript@5.4.3)(zod@3.22.4) + transitivePeerDependencies: + - '@types/react' + dev: false + /@web3modal/wallet@4.1.11: resolution: {integrity: sha512-6eJSpNcrBxufJFEQu9+ZOMUZxPqa8438RvfYKCU9nLXwoBtweo6ecpQw2yhXDlrfG+uJZhFabtPxROabn2M8Kg==} dependencies: @@ -6452,6 +6842,14 @@ packages: svelte: 4.2.12 dev: false + /@zerodevx/svelte-toast@0.9.5(svelte@4.2.13): + resolution: {integrity: sha512-JLeB/oRdJfT+dz9A5bgd3Z7TuQnBQbeUtXrGIrNWMGqWbabpepBF2KxtWVhL2qtxpRqhae2f6NAOzH7xs4jUSw==} + peerDependencies: + svelte: ^3.57.0 || ^4.0.0 + dependencies: + svelte: 4.2.13 + dev: false + /abitype@0.9.10(typescript@5.4.3)(zod@3.22.4): resolution: {integrity: sha512-FIS7U4n7qwAT58KibwYig5iFG4K61rbhAqaQh/UWj8v1Y8mjX3F8TC9gd8cz9yT1TYel9f8nS5NO5kZp2RW0jQ==} peerDependencies: @@ -6465,7 +6863,6 @@ packages: dependencies: typescript: 5.4.3 zod: 3.22.4 - dev: true /abitype@0.9.8(typescript@5.4.3): resolution: {integrity: sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==} @@ -6597,7 +6994,6 @@ packages: /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} - dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -6618,7 +7014,6 @@ packages: /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - dev: true /antlr4@4.13.1: resolution: {integrity: sha512-kiXTspaRYvnIArgE97z5YVVf/cDVQABr3abFRR6mE7yesLMkgu4ujuyV/sgxafQ8wgve0DJQUJ38Z8tkgA2izA==} @@ -6627,7 +7022,6 @@ packages: /any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: true /any-signal@3.0.1: resolution: {integrity: sha512-xgZgJtKEa9YmDqXodIgl7Fl1C8yNXr8w6gXjqK3LW4GcEiYT+6AQfJSE/8SPsEpLLmcvbv8YU+qet94UewHxqg==} @@ -6650,7 +7044,6 @@ packages: /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: true /argparse@1.0.10: resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} @@ -6797,6 +7190,22 @@ packages: postcss-value-parser: 4.2.0 dev: true + /autoprefixer@10.4.19(postcss@8.4.38): + resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + dependencies: + browserslist: 4.23.0 + caniuse-lite: 1.0.30001614 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.0.0 + postcss: 8.4.38 + postcss-value-parser: 4.2.0 + dev: false + /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -6924,7 +7333,6 @@ packages: buffer: 6.0.3 inherits: 2.0.4 readable-stream: 3.6.2 - dev: true /blakejs@1.2.1: resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} @@ -6967,7 +7375,6 @@ packages: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 - dev: true /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} @@ -7096,17 +7503,20 @@ packages: dependencies: esbuild: 0.19.12 load-tsconfig: 0.2.5 - dev: true /bytes@3.0.0: resolution: {integrity: sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==} engines: {node: '>= 0.8'} dev: false + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: true + /cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} - dev: true /cacheable-lookup@7.0.0: resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} @@ -7164,12 +7574,10 @@ packages: dependencies: pascal-case: 3.1.2 tslib: 2.6.2 - dev: true /camelcase-css@2.0.1: resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} engines: {node: '>= 6'} - dev: true /camelcase@5.3.1: resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} @@ -7184,13 +7592,16 @@ packages: /caniuse-lite@1.0.30001593: resolution: {integrity: sha512-UWM1zlo3cZfkpBysd7AS+z+v007q9G1+fLTUU42rQnY6t2axoogPW/xol6T7juU5EUoOhML4WgBIdG+9yYqAjQ==} + /caniuse-lite@1.0.30001614: + resolution: {integrity: sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==} + dev: false + /capital-case@1.0.4: resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} dependencies: no-case: 3.0.4 tslib: 2.6.2 upper-case-first: 2.0.2 - dev: true /cborg@4.2.0: resolution: {integrity: sha512-q6cFW5m3KxfP/9xGI3yGLaC1l5DP6DWM9IvjiJojnIwohL5CQDl02EXViPV852mOfQo+7PJGPN01MI87vFGzyA==} @@ -7228,7 +7639,6 @@ packages: /chalk@5.3.0: resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: true /change-case@4.1.2: resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} @@ -7245,7 +7655,6 @@ packages: sentence-case: 3.0.4 snake-case: 3.0.4 tslib: 2.6.2 - dev: true /check-error@1.0.3: resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} @@ -7267,12 +7676,25 @@ packages: optionalDependencies: fsevents: 2.3.3 + /chromatic@11.3.0: + resolution: {integrity: sha512-q1ZtJDJrjLGnz60ivpC16gmd7KFzcaA4eTb7gcytCqbaKqlHhCFr1xQmcUDsm14CK7JsqdkFU6S+JQdOd2ZNJg==} + hasBin: true + peerDependencies: + '@chromatic-com/cypress': ^0.*.* || ^1.0.0 + '@chromatic-com/playwright': ^0.*.* || ^1.0.0 + peerDependenciesMeta: + '@chromatic-com/cypress': + optional: true + '@chromatic-com/playwright': + optional: true + dev: true + /chrome-launcher@0.15.2: resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==} engines: {node: '>=12.13.0'} hasBin: true dependencies: - '@types/node': 20.11.30 + '@types/node': 20.12.7 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -7283,7 +7705,7 @@ packages: /chromium-edge-launcher@1.0.0: resolution: {integrity: sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==} dependencies: - '@types/node': 20.11.30 + '@types/node': 20.12.7 escape-string-regexp: 4.0.0 is-wsl: 2.2.0 lighthouse-logger: 1.4.2 @@ -7324,7 +7746,6 @@ packages: es6-iterator: 2.0.3 memoizee: 0.4.15 timers-ext: 0.1.7 - dev: false /cli-cursor@3.1.0: resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} @@ -7338,7 +7759,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: restore-cursor: 4.0.0 - dev: true /cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} @@ -7460,13 +7880,13 @@ packages: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} dev: false - /commander@3.0.2: - resolution: {integrity: sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==} - dev: true - /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} + + /commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} dev: true /commander@9.5.0: @@ -7533,11 +7953,9 @@ packages: no-case: 3.0.4 tslib: 2.6.2 upper-case: 2.0.2 - dev: true /convert-csv-to-json@2.46.0: resolution: {integrity: sha512-Q7PjRjhECa5nBUEGbsKXvB8YaygVUesF/sYnaoCPTWoiwJEDCbLd2CcFDE1y80Q347IaTQukCQSCP2fR5IW+5g==} - dev: false /convert-source-map@1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -7678,7 +8096,6 @@ packages: dependencies: cssesc: 3.0.0 fastparse: 1.1.2 - dev: true /css-tree@2.3.1: resolution: {integrity: sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==} @@ -7691,7 +8108,6 @@ packages: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} hasBin: true - dev: true /cssstyle@4.0.1: resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} @@ -7708,14 +8124,12 @@ packages: /culori@3.3.0: resolution: {integrity: sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /d@1.0.1: resolution: {integrity: sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==} dependencies: es5-ext: 0.10.62 type: 1.2.0 - dev: false /dag-jose@4.0.0: resolution: {integrity: sha512-tw595L3UYoOUT9dSJPbBEG/qpRpw24kRZxa5SLRnlnr+g5L7O8oEs1d3W5TiVA1oJZbthVsf0Vi3zFN66qcEBA==} @@ -7734,7 +8148,6 @@ packages: postcss-js: 4.0.1(postcss@8.4.38) transitivePeerDependencies: - postcss - dev: true /daisyui@4.7.2(postcss@8.4.38): resolution: {integrity: sha512-9UCss12Zmyk/22u+JbkVrHHxOzFOyY17HuqP5LeswI4hclbj6qbjJTovdj2zRy8cCH6/n6Wh0lTLjriGnyGh0g==} @@ -7763,6 +8176,10 @@ packages: '@babel/runtime': 7.23.9 dev: false + /dayjs@1.10.1: + resolution: {integrity: sha512-2xg7JrHQeLBQFkvTumLoy62x1siyeocc98QwjtURgvRqOPYmAkMUdmSjrOA+MlmL6QMQn5MUhDf6rNZNuPc1LQ==} + dev: false + /dayjs@1.11.10: resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} dev: false @@ -7823,7 +8240,6 @@ packages: /dedent@0.7.0: resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} - dev: true /deep-eql@4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} @@ -7920,7 +8336,6 @@ packages: /depd@2.0.0: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} - dev: false /deprecated-react-native-prop-types@5.0.0: resolution: {integrity: sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==} @@ -7970,7 +8385,6 @@ packages: /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - dev: true /diff-sequences@29.6.3: resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} @@ -7991,11 +8405,9 @@ packages: engines: {node: '>=8'} dependencies: path-type: 4.0.0 - dev: true /dlv@1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - dev: true /dns-over-http-resolver@2.1.3: resolution: {integrity: sha512-zjRYFhq+CsxPAouQWzOsxNMvEN+SHisjzhX8EMxd2Y0EG3thvn6wXQgMJLnTDImkhe4jhLbOQpXtL10nALBOSA==} @@ -8034,17 +8446,14 @@ packages: dependencies: no-case: 3.0.4 tslib: 2.6.2 - dev: true /dotenv-expand@10.0.0: resolution: {integrity: sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==} engines: {node: '>=12'} - dev: true /dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} - dev: true /duplexify@4.1.2: resolution: {integrity: sha512-fz3OjcNCHmRP12MJoZMPglx8m4rrFP8rovnk4vT8Fs+aonZoCwGg10dSsQsfP/E62eZcPTMSMP6686fu9Qlqtw==} @@ -8057,7 +8466,6 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true /eciesjs@0.3.18: resolution: {integrity: sha512-RQhegEtLSyIiGJmFTZfvCTHER/fymipXFVx6OwSRYD6hOuy+6Kjpk0dGvIfP9kxn/smBpxQy71uxpGO406ITCw==} @@ -8097,7 +8505,6 @@ packages: /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true /encode-utf8@1.0.3: resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} @@ -8260,7 +8667,6 @@ packages: es6-iterator: 2.0.3 es6-symbol: 3.1.3 next-tick: 1.1.0 - dev: false /es6-iterator@2.0.3: resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} @@ -8268,7 +8674,6 @@ packages: d: 1.0.1 es5-ext: 0.10.62 es6-symbol: 3.1.3 - dev: false /es6-promise@3.3.1: resolution: {integrity: sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==} @@ -8279,7 +8684,6 @@ packages: dependencies: d: 1.0.1 ext: 1.7.0 - dev: false /es6-weak-map@2.0.3: resolution: {integrity: sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==} @@ -8288,7 +8692,6 @@ packages: es5-ext: 0.10.62 es6-iterator: 2.0.3 es6-symbol: 3.1.3 - dev: false /esbuild@0.18.20: resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} @@ -8389,6 +8792,16 @@ packages: eslint: 8.56.0 dev: true + /eslint-compat-utils@0.5.0(eslint@8.56.0): + resolution: {integrity: sha512-dc6Y8tzEcSYZMHa+CMPLi/hyo1FzNeonbhJL7Ol0ccuKQkwopJcJBA9YL/xmMTLU1eKigXo9vj9nALElWYSowg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.56.0 + semver: 7.6.0 + dev: true + /eslint-config-prettier@9.1.0(eslint@8.55.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true @@ -8759,12 +9172,28 @@ packages: eslint: 8.56.0 dev: true - /eslint-plugin-svelte@2.35.1(eslint@8.56.0)(svelte@4.2.12): - resolution: {integrity: sha512-IF8TpLnROSGy98Z3NrsKXWDSCbNY2ReHDcrYTuXZMbfX7VmESISR78TWgO9zdg4Dht1X8coub5jKwHzP0ExRug==} + /eslint-plugin-storybook@0.8.0(eslint@8.56.0)(typescript@5.4.3): + resolution: {integrity: sha512-CZeVO5EzmPY7qghO2t64oaFM+8FTaD4uzOEjHKp516exyTKo+skKAL9GI3QALS2BXhyALJjNtwbmr1XinGE8bA==} + engines: {node: '>= 18'} + peerDependencies: + eslint: '>=6' + dependencies: + '@storybook/csf': 0.0.1 + '@typescript-eslint/utils': 5.62.0(eslint@8.56.0)(typescript@5.4.3) + eslint: 8.56.0 + requireindex: 1.2.0 + ts-dedent: 2.2.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /eslint-plugin-svelte@2.38.0(eslint@8.56.0)(svelte@4.2.12): + resolution: {integrity: sha512-IwwxhHzitx3dr0/xo0z4jjDlb2AAHBPKt+juMyKKGTLlKi1rZfA4qixMwnveU20/JTHyipM6keX4Vr7LZFYc9g==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0-0 - svelte: ^3.37.0 || ^4.0.0 + eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.112 peerDependenciesMeta: svelte: optional: true @@ -8773,27 +9202,27 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 debug: 4.3.4 eslint: 8.56.0 - eslint-compat-utils: 0.1.2(eslint@8.56.0) + eslint-compat-utils: 0.5.0(eslint@8.56.0) esutils: 2.0.3 - known-css-properties: 0.29.0 + known-css-properties: 0.30.0 postcss: 8.4.38 postcss-load-config: 3.1.4(postcss@8.4.38) postcss-safe-parser: 6.0.0(postcss@8.4.38) - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.0.16 semver: 7.6.0 svelte: 4.2.12 - svelte-eslint-parser: 0.33.1(svelte@4.2.12) + svelte-eslint-parser: 0.35.0(svelte@4.2.12) transitivePeerDependencies: - supports-color - ts-node dev: true - /eslint-plugin-svelte@2.35.1(eslint@8.56.0)(svelte@4.2.13): - resolution: {integrity: sha512-IF8TpLnROSGy98Z3NrsKXWDSCbNY2ReHDcrYTuXZMbfX7VmESISR78TWgO9zdg4Dht1X8coub5jKwHzP0ExRug==} + /eslint-plugin-svelte@2.38.0(eslint@8.56.0)(svelte@4.2.13): + resolution: {integrity: sha512-IwwxhHzitx3dr0/xo0z4jjDlb2AAHBPKt+juMyKKGTLlKi1rZfA4qixMwnveU20/JTHyipM6keX4Vr7LZFYc9g==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: - eslint: ^7.0.0 || ^8.0.0-0 - svelte: ^3.37.0 || ^4.0.0 + eslint: ^7.0.0 || ^8.0.0-0 || ^9.0.0-0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.112 peerDependenciesMeta: svelte: optional: true @@ -8802,21 +9231,29 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 debug: 4.3.4 eslint: 8.56.0 - eslint-compat-utils: 0.1.2(eslint@8.56.0) + eslint-compat-utils: 0.5.0(eslint@8.56.0) esutils: 2.0.3 - known-css-properties: 0.29.0 + known-css-properties: 0.30.0 postcss: 8.4.38 postcss-load-config: 3.1.4(postcss@8.4.38) postcss-safe-parser: 6.0.0(postcss@8.4.38) - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.0.16 semver: 7.6.0 svelte: 4.2.13 - svelte-eslint-parser: 0.33.1(svelte@4.2.13) + svelte-eslint-parser: 0.35.0(svelte@4.2.13) transitivePeerDependencies: - supports-color - ts-node dev: true + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + /eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8969,6 +9406,11 @@ packages: estraverse: 5.3.0 dev: true + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -8976,7 +9418,6 @@ packages: /estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - dev: false /estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -9151,7 +9592,6 @@ packages: dependencies: d: 1.0.1 es5-ext: 0.10.62 - dev: false /event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} @@ -9225,7 +9665,6 @@ packages: resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} dependencies: type: 2.7.2 - dev: false /extension-port-stream@2.1.1: resolution: {integrity: sha512-qknp5o5rj2J9CRKfVB8KJr+uXQlrojNZzdESUPhKYLXf97TPcGf6qWWKmpsNNtUyOdzFhab1ON0jzouNxHHvow==} @@ -9259,7 +9698,6 @@ packages: glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.5 - dev: true /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} @@ -9287,13 +9725,11 @@ packages: /fastparse@1.1.2: resolution: {integrity: sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==} - dev: true /fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: reusify: 1.0.4 - dev: true /fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} @@ -9308,6 +9744,11 @@ packages: flat-cache: 3.2.0 dev: true + /filesize@10.1.1: + resolution: {integrity: sha512-L0cdwZrKlwZQkMSFnCflJ6J2Y+5egO/p3vgRSDQGxQt++QbUZe5gMbRO6kg6gzwQDPvq2Fk9AmoxUNfZ5gdqaQ==} + engines: {node: '>= 10.4.0'} + dev: true + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -9375,7 +9816,6 @@ packages: dependencies: locate-path: 7.2.0 path-exists: 5.0.0 - dev: true /flat-cache@3.2.0: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} @@ -9386,6 +9826,13 @@ packages: rimraf: 3.0.2 dev: true + /flat@4.1.1: + resolution: {integrity: sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==} + hasBin: true + dependencies: + is-buffer: 2.0.5 + dev: true + /flatted@3.2.9: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true @@ -9421,7 +9868,6 @@ packages: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 - dev: true /form-data-encoder@2.1.4: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} @@ -9438,23 +9884,12 @@ packages: /fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: true /fresh@0.5.2: resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} engines: {node: '>= 0.6'} dev: false - /fs-extra@0.30.0: - resolution: {integrity: sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 2.4.0 - klaw: 1.3.1 - path-is-absolute: 1.0.1 - rimraf: 2.7.1 - dev: true - /fs-extra@11.2.0: resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} engines: {node: '>=14.14'} @@ -9462,7 +9897,6 @@ packages: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 - dev: true /fs-extra@8.1.0: resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} @@ -9577,7 +10011,6 @@ packages: engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 - dev: true /glob@10.3.10: resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} @@ -9589,7 +10022,6 @@ packages: minimatch: 9.0.4 minipass: 7.0.4 path-scurry: 1.10.1 - dev: true /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} @@ -9661,7 +10093,6 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 4.0.0 - dev: true /globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -9774,7 +10205,6 @@ packages: dependencies: capital-case: 1.0.4 tslib: 2.6.2 - dev: true /hermes-estree@0.15.0: resolution: {integrity: sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==} @@ -9850,7 +10280,6 @@ packages: setprototypeof: 1.2.0 statuses: 2.0.1 toidentifier: 1.0.1 - dev: false /http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} @@ -9910,6 +10339,13 @@ packages: '@babel/runtime': 7.23.9 dev: false + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -9931,7 +10367,6 @@ packages: /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - dev: true /image-size@1.1.1: resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==} @@ -10018,7 +10453,6 @@ packages: '@formatjs/fast-memoize': 2.2.0 '@formatjs/icu-messageformat-parser': 2.7.6 tslib: 2.6.2 - dev: false /intl-messageformat@9.13.0: resolution: {integrity: sha512-7sGC7QnSQGa5LZP7bXLDhVDtQOeKGeBFGHF2Y8LVBwYZoQZCgWeKoPGTa5GMG8g/TzDgeXuYJQis7Ggiw2xTOw==} @@ -10213,6 +10647,11 @@ packages: has-tostringtag: 1.0.0 dev: true + /is-buffer@2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: true + /is-builtin-module@3.2.1: resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} engines: {node: '>=6'} @@ -10301,7 +10740,6 @@ packages: /is-interactive@2.0.0: resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} engines: {node: '>=12'} - dev: true /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} @@ -10342,7 +10780,6 @@ packages: /is-promise@2.2.2: resolution: {integrity: sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==} - dev: false /is-reference@3.0.2: resolution: {integrity: sha512-v3rht/LgVcsdZa3O2Nqs+NMowLOxeOm7Ay9+/ARQ2F+qEoANRcqrjAZKGN0v8ymUetZGgkp26LTnGT7H0Qo9Pg==} @@ -10399,7 +10836,6 @@ packages: /is-unicode-supported@1.3.0: resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} engines: {node: '>=12'} - dev: true /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} @@ -10443,6 +10879,11 @@ packages: /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + /isexe@3.1.1: + resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} + engines: {node: '>=16'} + dev: true + /iso-url@1.2.1: resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} engines: {node: '>=12'} @@ -10572,7 +11013,6 @@ packages: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: true /jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} @@ -10581,7 +11021,7 @@ packages: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.11.30 + '@types/node': 20.12.7 jest-mock: 29.7.0 jest-util: 29.7.0 dev: false @@ -10611,7 +11051,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.30 + '@types/node': 20.12.7 jest-util: 29.7.0 dev: false @@ -10620,7 +11060,7 @@ packages: engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/types': 29.6.3 - '@types/node': 20.11.30 + '@types/node': 20.12.7 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -10643,7 +11083,7 @@ packages: resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@types/node': 20.11.30 + '@types/node': 20.12.7 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -10831,12 +11271,6 @@ packages: /jsonc-parser@3.2.0: resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} - /jsonfile@2.4.0: - resolution: {integrity: sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - /jsonfile@4.0.0: resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} optionalDependencies: @@ -10849,7 +11283,6 @@ packages: universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 - dev: true /keccak@3.0.4: resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} @@ -10876,12 +11309,6 @@ packages: engines: {node: '>=0.10.0'} dev: false - /klaw@1.3.1: - resolution: {integrity: sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - /kleur@3.0.3: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} @@ -10892,8 +11319,8 @@ packages: engines: {node: '>=6'} dev: true - /known-css-properties@0.29.0: - resolution: {integrity: sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ==} + /known-css-properties@0.30.0: + resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==} dev: true /latest-version@7.0.0: @@ -11007,12 +11434,10 @@ packages: /lilconfig@2.1.0: resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} engines: {node: '>=10'} - dev: true /lilconfig@3.1.1: resolution: {integrity: sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==} engines: {node: '>=14'} - dev: true /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} @@ -11090,7 +11515,6 @@ packages: /load-tsconfig@0.2.5: resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /local-pkg@0.4.3: resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} @@ -11134,7 +11558,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: p-locate: 6.0.0 - dev: true /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -11182,7 +11605,6 @@ packages: dependencies: chalk: 5.3.0 is-unicode-supported: 1.3.0 - dev: true /logkitty@0.7.1: resolution: {integrity: sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==} @@ -11206,7 +11628,6 @@ packages: hasBin: true dependencies: js-tokens: 4.0.0 - dev: false /loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} @@ -11218,7 +11639,6 @@ packages: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: tslib: 2.6.2 - dev: true /lowercase-keys@3.0.0: resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} @@ -11244,7 +11664,6 @@ packages: resolution: {integrity: sha512-BpdYkt9EvGl8OfWHDQPISVpcl5xZthb+XPsbELj5AQXxIC8IriDZIQYjBJPEm5rS420sjZ0TLEzRcq5KdBhYrQ==} dependencies: es5-ext: 0.10.62 - dev: false /magic-string@0.30.7: resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==} @@ -11257,7 +11676,6 @@ packages: engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 - dev: true /magicast@0.3.3: resolution: {integrity: sha512-ZbrP1Qxnpoes8sz47AM0z08U+jW6TyRgZzcWy3Ma3vDhJttwMwAFDMMQFobwdBxByBD46JYmxRzeF7w2+wJEuw==} @@ -11322,7 +11740,6 @@ packages: lru-queue: 0.1.0 next-tick: 1.1.0 timers-ext: 0.1.7 - dev: false /memorystream@0.3.1: resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} @@ -11342,7 +11759,6 @@ packages: /merge2@1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} - dev: true /merkletreejs@0.3.11: resolution: {integrity: sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==} @@ -11628,6 +12044,11 @@ packages: engines: {node: '>=4'} dev: true + /minidenticons@4.2.1: + resolution: {integrity: sha512-oWfFivA0lOx/V/bO/YIJbthB26lV8JXYvhnv9zM2hNd3fzsHTXQ6c6bWZPcvhD3nnOB+lQk/D9lF43BXixrN8g==} + engines: {node: '>=15.14.0'} + dev: false + /minimalistic-assert@1.0.1: resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} @@ -11665,7 +12086,6 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 - dev: true /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -11673,7 +12093,6 @@ packages: /minipass@7.0.4: resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} engines: {node: '>=16 || 14 >=14.17'} - dev: true /mipd@0.0.5(typescript@5.4.3): resolution: {integrity: sha512-gbKA784D2WKb5H/GtqEv+Ofd1S9Zj+Z/PGDIl1u1QAbswkxD28BQ5bSXQxkeBzPBABg1iDSbiwGG1XqlOxRspA==} @@ -11796,7 +12215,6 @@ packages: any-promise: 1.3.0 object-assign: 4.1.1 thenify-all: 1.6.0 - dev: true /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} @@ -11844,14 +12262,12 @@ packages: /next-tick@1.1.0: resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - dev: false /no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} dependencies: lower-case: 2.0.2 tslib: 2.6.2 - dev: true /nocache@3.0.4: resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==} @@ -11926,7 +12342,6 @@ packages: /normalize-range@0.1.2: resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} engines: {node: '>=0.10.0'} - dev: true /normalize-url@8.0.0: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} @@ -12154,7 +12569,6 @@ packages: stdin-discarder: 0.1.0 strip-ansi: 7.1.0 wcwidth: 1.0.1 - dev: true /os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} @@ -12201,7 +12615,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: yocto-queue: 1.0.0 - dev: true /p-limit@5.0.0: resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} @@ -12235,6 +12648,10 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: p-limit: 4.0.0 + + /p-map@7.0.2: + resolution: {integrity: sha512-z4cYYMMdKHzw4O5UkWJImbZynVIo0lSGTXc7bzB1e/rrDqkgGUNysK/o4bTr+0+xKvvLoTyGqYC4Fgljy9qe1Q==} + engines: {node: '>=18'} dev: true /p-queue@8.0.1: @@ -12270,7 +12687,6 @@ packages: dependencies: dot-case: 3.0.4 tslib: 2.6.2 - dev: true /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} @@ -12315,7 +12731,6 @@ packages: dependencies: no-case: 3.0.4 tslib: 2.6.2 - dev: true /path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -12326,7 +12741,6 @@ packages: dependencies: dot-case: 3.0.4 tslib: 2.6.2 - dev: true /path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} @@ -12340,7 +12754,6 @@ packages: /path-exists@5.0.0: resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: true /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} @@ -12363,7 +12776,6 @@ packages: dependencies: lru-cache: 10.2.0 minipass: 7.0.4 - dev: true /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} @@ -12404,7 +12816,6 @@ packages: /pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} - dev: true /pify@3.0.0: resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} @@ -12508,7 +12919,6 @@ packages: postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - dev: true /postcss-import@16.1.0(postcss@8.4.38): resolution: {integrity: sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==} @@ -12530,7 +12940,6 @@ packages: dependencies: camelcase-css: 2.0.1 postcss: 8.4.38 - dev: true /postcss-load-config@3.1.4(postcss@8.4.38): resolution: {integrity: sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==} @@ -12564,7 +12973,6 @@ packages: lilconfig: 3.1.1 postcss: 8.4.38 yaml: 2.3.4 - dev: true /postcss-nested@5.0.6(postcss@8.4.38): resolution: {integrity: sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==} @@ -12573,7 +12981,7 @@ packages: postcss: ^8.2.14 dependencies: postcss: 8.4.38 - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.0.16 dev: true /postcss-nested@6.0.1(postcss@8.4.38): @@ -12583,8 +12991,7 @@ packages: postcss: ^8.2.14 dependencies: postcss: 8.4.38 - postcss-selector-parser: 6.0.15 - dev: true + postcss-selector-parser: 6.0.16 /postcss-nesting@12.1.0(postcss@8.4.38): resolution: {integrity: sha512-QOYnosaZ+mlP6plQrAxFw09UUp2Sgtxj1BVHN+rSVbtV0Yx48zRt9/9F/ZOoxOKBBEsaJk2MYhhVRjeRRw5yuw==} @@ -12622,11 +13029,16 @@ packages: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: true + + /postcss-selector-parser@6.0.16: + resolution: {integrity: sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==} + engines: {node: '>=4'} + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 /postcss-value-parser@4.2.0: resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: true /postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} @@ -12635,7 +13047,6 @@ packages: nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.2.0 - dev: true /preact@10.19.5: resolution: {integrity: sha512-OPELkDmSVbKjbFqF9tgvOowiiQ9TmsJljIzXRyNE8nGiis94pwv1siF78rQkAP1Q1738Ce6pellRg/Ns/CtHqQ==} @@ -12685,7 +13096,6 @@ packages: resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} engines: {node: '>=14'} hasBin: true - dev: true /pretty-format@26.6.2: resolution: {integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==} @@ -12763,7 +13173,7 @@ packages: '@protobufjs/path': 1.1.2 '@protobufjs/pool': 1.1.0 '@protobufjs/utf8': 1.1.0 - '@types/node': 20.11.30 + '@types/node': 20.12.7 long: 5.2.3 dev: false @@ -12834,7 +13244,6 @@ packages: /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true /queue@6.0.2: resolution: {integrity: sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==} @@ -12866,6 +13275,16 @@ packages: engines: {node: '>= 0.6'} dev: false + /raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: true + /rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -12876,6 +13295,16 @@ packages: strip-json-comments: 2.0.1 dev: true + /react-confetti@6.1.0(react@18.2.0): + resolution: {integrity: sha512-7Ypx4vz0+g8ECVxr88W9zhcQpbeujJAVqL14ZnXJ3I23mOI9/oBVTQ3dkJhUmB0D6XOtCZEM6N0Gm9PMngkORw==} + engines: {node: '>=10.18'} + peerDependencies: + react: ^16.3.0 || ^17.0.1 || ^18.0.0 + dependencies: + react: 18.2.0 + tween-functions: 1.2.0 + dev: true + /react-devtools-core@4.28.5: resolution: {integrity: sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==} dependencies: @@ -13022,13 +13451,11 @@ packages: engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 - dev: false /read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} dependencies: pify: 2.3.0 - dev: true /readable-stream@2.3.3: resolution: {integrity: sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==} @@ -13191,6 +13618,11 @@ packages: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} dev: false + /requireindex@1.2.0: + resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} + engines: {node: '>=0.10.5'} + dev: true + /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} dev: true @@ -13241,7 +13673,6 @@ packages: dependencies: onetime: 5.1.2 signal-exit: 3.0.7 - dev: true /retimer@3.0.0: resolution: {integrity: sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==} @@ -13250,7 +13681,6 @@ packages: /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true /rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} @@ -13348,7 +13778,6 @@ packages: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - dev: true /sade@1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} @@ -13483,7 +13912,6 @@ packages: no-case: 3.0.4 tslib: 2.6.2 upper-case-first: 2.0.2 - dev: true /serialize-error@2.1.0: resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} @@ -13536,7 +13964,6 @@ packages: /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false /sha.js@2.4.11: resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} @@ -13642,7 +14069,6 @@ packages: /slash@4.0.0: resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} engines: {node: '>=12'} - dev: true /slice-ansi@2.1.0: resolution: {integrity: sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==} @@ -13667,7 +14093,6 @@ packages: dependencies: dot-case: 3.0.4 tslib: 2.6.2 - dev: true /socket.io-client@4.7.4(bufferutil@4.0.8)(utf-8-validate@6.0.3): resolution: {integrity: sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==} @@ -13693,18 +14118,16 @@ packages: - supports-color dev: false - /solc@0.7.3: - resolution: {integrity: sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==} - engines: {node: '>=8.0.0'} + /solc@0.8.24: + resolution: {integrity: sha512-G5yUqjTUPc8Np74sCFwfsevhBPlUifUOfhYrgyu6CmYlC6feSw0YS6eZW47XDT23k3JYdKx5nJ+Q7whCEmNcoA==} + engines: {node: '>=10.0.0'} hasBin: true dependencies: command-exists: 1.2.9 - commander: 3.0.2 + commander: 8.3.0 follow-redirects: 1.15.5(debug@4.3.4) - fs-extra: 0.30.0 js-sha3: 0.8.0 memorystream: 0.3.1 - require-from-string: 2.0.2 semver: 5.7.2 tmp: 0.0.33 transitivePeerDependencies: @@ -13829,7 +14252,6 @@ packages: /statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - dev: false /std-env@3.7.0: resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} @@ -13839,7 +14261,6 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: bl: 5.1.0 - dev: true /stream-shift@1.0.1: resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} @@ -13871,7 +14292,6 @@ packages: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true /string.prototype.trim@1.2.8: resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} @@ -13933,7 +14353,6 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 - dev: true /strip-bom@3.0.0: resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} @@ -14004,7 +14423,6 @@ packages: mz: 2.7.0 pirates: 4.0.6 ts-interface-checker: 0.1.13 - dev: true /sudo-prompt@9.2.1: resolution: {integrity: sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==} @@ -14065,7 +14483,7 @@ packages: - sugarss dev: true - /svelte-check@3.6.9(postcss@8.4.38)(svelte@4.2.13): + /svelte-check@3.6.9(@babel/core@7.23.9)(postcss@8.4.38)(svelte@4.2.13): resolution: {integrity: sha512-hDQrk3L0osX07djQyMiXocKysTLfusqi8AriNcCiQxhQR49/LonYolcUGMtZ0fbUR8HTR198Prrgf52WWU9wEg==} hasBin: true peerDependencies: @@ -14078,7 +14496,7 @@ packages: picocolors: 1.0.0 sade: 1.8.1 svelte: 4.2.13 - svelte-preprocess: 5.1.3(postcss@8.4.38)(svelte@4.2.13)(typescript@5.4.3) + svelte-preprocess: 5.1.3(@babel/core@7.23.9)(postcss@8.4.38)(svelte@4.2.13)(typescript@5.4.3) typescript: 5.4.3 transitivePeerDependencies: - '@babel/core' @@ -14092,11 +14510,25 @@ packages: - sugarss dev: true - /svelte-eslint-parser@0.33.1(svelte@4.2.12): - resolution: {integrity: sha512-vo7xPGTlKBGdLH8T5L64FipvTrqv3OQRx9d2z5X05KKZDlF4rQk8KViZO4flKERY+5BiVdOh7zZ7JGJWo5P0uA==} + /svelte-copy@1.4.2(svelte@4.2.13): + resolution: {integrity: sha512-Q99JvWDzB58JlbVWX2VxjHX/CQ5ayDLUGGJgL2EqU1+3c9CDOtxLrKFZx5CVN5bN/DDl62nxtazz0j3nGX1Xew==} + peerDependencies: + svelte: ^3.55.0 || ^4.0.0 + dependencies: + svelte: 4.2.13 + dev: true + + /svelte-countdown@1.1.2: + resolution: {integrity: sha512-datUfbRtGCp+7OwIRcbW9tbIwlkN7KiJp9Mg01Na9HgSQrLG0knsD/xjaIVKPovxY8xF0yOrbPEz+bT/BS9EBQ==} + dependencies: + dayjs: 1.10.1 + dev: false + + /svelte-eslint-parser@0.35.0(svelte@4.2.12): + resolution: {integrity: sha512-CtbPseajW0gjwEvHiuzYJkPDjAcHz2FaHt540j6RVYrZgnE6xWkzUBodQ4I3nV+G5AS0Svt8K6aIA/CIU9xT2Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - svelte: ^3.37.0 || ^4.0.0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.112 peerDependenciesMeta: svelte: optional: true @@ -14109,11 +14541,11 @@ packages: svelte: 4.2.12 dev: true - /svelte-eslint-parser@0.33.1(svelte@4.2.13): - resolution: {integrity: sha512-vo7xPGTlKBGdLH8T5L64FipvTrqv3OQRx9d2z5X05KKZDlF4rQk8KViZO4flKERY+5BiVdOh7zZ7JGJWo5P0uA==} + /svelte-eslint-parser@0.35.0(svelte@4.2.13): + resolution: {integrity: sha512-CtbPseajW0gjwEvHiuzYJkPDjAcHz2FaHt540j6RVYrZgnE6xWkzUBodQ4I3nV+G5AS0Svt8K6aIA/CIU9xT2Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: - svelte: ^3.37.0 || ^4.0.0 + svelte: ^3.37.0 || ^4.0.0 || ^5.0.0-next.112 peerDependenciesMeta: svelte: optional: true @@ -14176,7 +14608,6 @@ packages: sade: 1.8.1 svelte: 4.2.13 tiny-glob: 0.2.9 - dev: false /svelte-preprocess@5.1.3(@babel/core@7.23.9)(postcss@8.4.38)(svelte@4.2.12)(typescript@5.4.3): resolution: {integrity: sha512-xxAkmxGHT+J/GourS5mVJeOXZzne1FR5ljeOUAMXUkfEhkLEllRreXpbl3dIYJlcJRfL1LO1uIAPpBpBfiqGPw==} @@ -14227,7 +14658,7 @@ packages: typescript: 5.4.3 dev: true - /svelte-preprocess@5.1.3(postcss@8.4.38)(svelte@4.2.13)(typescript@5.4.3): + /svelte-preprocess@5.1.3(@babel/core@7.23.9)(postcss@8.4.38)(svelte@4.2.13)(typescript@5.4.3): resolution: {integrity: sha512-xxAkmxGHT+J/GourS5mVJeOXZzne1FR5ljeOUAMXUkfEhkLEllRreXpbl3dIYJlcJRfL1LO1uIAPpBpBfiqGPw==} engines: {node: '>= 16.0.0', pnpm: ^8.0.0} requiresBuild: true @@ -14265,6 +14696,7 @@ packages: typescript: optional: true dependencies: + '@babel/core': 7.23.9 '@types/pug': 2.0.10 detect-indent: 6.1.0 magic-string: 0.30.9 @@ -14275,6 +14707,14 @@ packages: typescript: 5.4.3 dev: true + /svelte-scrolling@1.4.0(svelte@4.2.13): + resolution: {integrity: sha512-1721UrmTODAIhybCR5p/l6lQNSmuk66VgtgxdAEdQiGuYU1wCcKB/9kba0VXlxIeh5vhEaoODAOCizRRtHKQoQ==} + peerDependencies: + svelte: ^3 || ^4 + dependencies: + svelte: 4.2.13 + dev: true + /svelte@4.2.12: resolution: {integrity: sha512-d8+wsh5TfPwqVzbm4/HCXC783/KPHV60NvwitJnyTA5lWn1elhXMNWhXGCJ7PwPa8qFUnyJNIyuIRt2mT0WMug==} engines: {node: '>=16'} @@ -14310,7 +14750,7 @@ packages: estree-walker: 3.0.3 is-reference: 3.0.2 locate-character: 3.0.0 - magic-string: 0.30.7 + magic-string: 0.30.9 periscopic: 3.1.0 /symbol-tree@3.2.4: @@ -14341,6 +14781,13 @@ packages: strip-ansi: 6.0.1 dev: true + /tailwindcss-image-rendering@1.0.2: + resolution: {integrity: sha512-WC3hJd2RbHBYIqtJxwpQ5z94wUNyBrJn1eFz3J/jR7OGrQB8WYbJGvJQ9scNNVzoHEYGoNdZbUI90l9YgpBCwg==} + dependencies: + flat: 4.1.1 + lodash: 4.17.21 + dev: true + /tailwindcss@3.4.3: resolution: {integrity: sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==} engines: {node: '>=14.0.0'} @@ -14370,7 +14817,6 @@ packages: sucrase: 3.35.0 transitivePeerDependencies: - ts-node - dev: true /temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} @@ -14413,13 +14859,11 @@ packages: engines: {node: '>=0.8'} dependencies: thenify: 3.3.1 - dev: true /thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} dependencies: any-promise: 1.3.0 - dev: true /thread-stream@0.15.2: resolution: {integrity: sha512-UkEhKIg2pD+fjkHQKyJO3yoIvAP3N6RlNFt2dUhcS1FGvCD1cQa1M/PGknCLFIyZdtJOWQjejp7bdNqmN7zwdA==} @@ -14449,7 +14893,6 @@ packages: dependencies: es5-ext: 0.10.62 next-tick: 1.1.0 - dev: false /tiny-glob@0.2.9: resolution: {integrity: sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==} @@ -14506,7 +14949,6 @@ packages: /toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} - dev: false /totalist@3.0.1: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} @@ -14547,6 +14989,11 @@ packages: typescript: 5.4.3 dev: true + /ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + dev: true + /ts-essentials@9.4.1(typescript@5.4.3): resolution: {integrity: sha512-oke0rI2EN9pzHsesdmrOrnqv1eQODmJpd/noJjwj2ZPC3Z4N2wbjrOEqnsEgmvlO2+4fBb0a794DCna2elEVIQ==} peerDependencies: @@ -14560,7 +15007,6 @@ packages: /ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: true /ts-morph@19.0.0: resolution: {integrity: sha512-D6qcpiJdn46tUqV45vr5UGM2dnIEuTGNxVhg0sk5NX11orcouwj6i1bMqZIz2mZTZB1Hcgy7C3oEVhAT+f6mbQ==} @@ -14569,7 +15015,7 @@ packages: code-block-writer: 12.0.0 dev: true - /ts-node@10.9.2(@types/node@20.11.30)(typescript@5.4.3): + /ts-node@10.9.2(@types/node@20.12.7)(typescript@5.4.3): resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true peerDependencies: @@ -14588,7 +15034,7 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.11.30 + '@types/node': 20.12.7 acorn: 8.11.3 acorn-walk: 8.3.2 arg: 4.1.3 @@ -14624,11 +15070,24 @@ packages: /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: false /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + /tsutils@3.21.0(typescript@5.4.3): + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + dependencies: + tslib: 1.14.1 + typescript: 5.4.3 + dev: true + + /tween-functions@1.2.0: + resolution: {integrity: sha512-PZBtLYcCLtEcjL14Fzb1gSxPBeL7nWvGhO5ZFPGqziCcr8uvHp0NDmdjBchp6KHL+tExcg0m3NISmKxhU394dA==} + dev: true + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -14652,11 +15111,9 @@ packages: /type@1.2.0: resolution: {integrity: sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==} - dev: false /type@2.7.2: resolution: {integrity: sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==} - dev: false /typed-array-buffer@1.0.0: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} @@ -14807,12 +15264,10 @@ packages: /universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} - dev: true /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - dev: false /unstorage@1.10.1(idb-keyval@6.2.1): resolution: {integrity: sha512-rWQvLRfZNBpF+x8D3/gda5nUCQL2PgXy2jNG4U7/Rc9BGEv9+CAJd0YyGCROUBKs9v49Hg8huw3aih5Bf5TAVw==} @@ -14899,13 +15354,11 @@ packages: resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} dependencies: tslib: 2.6.2 - dev: true /upper-case@2.0.2: resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} dependencies: tslib: 2.6.2 - dev: true /uqr@0.1.2: resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} @@ -15052,7 +15505,7 @@ packages: - zod dev: false - /viem@2.9.16(typescript@5.4.3)(zod@3.22.4): + /viem@2.9.16(typescript@5.4.3): resolution: {integrity: sha512-FQRfN4G7uKEUs5DYvVrH/kZmTkwcSDpTBxnadpwG1EEP8nHm57WDpSaGN7PwSPVgJ6rMo5MENT5hgnqaNTlb2w==} peerDependencies: typescript: '>=5.0.4' @@ -15073,8 +15526,31 @@ packages: - bufferutil - utf-8-validate - zod + dev: false + + /viem@2.9.27(typescript@5.4.3)(zod@3.22.4): + resolution: {integrity: sha512-C+5tispAKzUywf+G5fxNVxThtKrNtvDRvvF34hC10LeSsrd5l4tlKpf0B4xYVcpL0YYZd+YEordLzlWToPjUnQ==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/bip32': 1.3.2 + '@scure/bip39': 1.2.1 + abitype: 1.0.0(typescript@5.4.3)(zod@3.22.4) + isows: 1.0.3(ws@8.13.0) + typescript: 5.4.3 + ws: 8.13.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod - /vite-node@0.32.4(@types/node@20.11.30): + /vite-node@0.32.4(@types/node@20.12.7): resolution: {integrity: sha512-L2gIw+dCxO0LK14QnUMoqSYpa9XRGnTTTDjW2h19Mr+GR0EFj4vx52W41gFXfMLqpA00eK4ZjOVYo1Xk//LFEw==} engines: {node: '>=v14.18.0'} hasBin: true @@ -15084,7 +15560,7 @@ packages: mlly: 1.5.0 pathe: 1.1.2 picocolors: 1.0.0 - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) transitivePeerDependencies: - '@types/node' - less @@ -15096,7 +15572,7 @@ packages: - terser dev: true - /vite-node@1.5.0: + /vite-node@1.5.0(@types/node@20.12.7): resolution: {integrity: sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -15105,7 +15581,7 @@ packages: debug: 4.3.4 pathe: 1.1.2 picocolors: 1.0.0 - vite: 5.1.3 + vite: 5.1.3(@types/node@20.12.7) transitivePeerDependencies: - '@types/node' - less @@ -15128,13 +15604,30 @@ packages: debug: 4.3.4 globrex: 0.1.2 tsconfck: 3.0.3(typescript@5.4.3) - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /vite-tsconfig-paths@4.3.2(typescript@5.4.3)(vite@5.1.3): + resolution: {integrity: sha512-0Vd/a6po6Q+86rPlntHye7F31zA2URZMbH8M3saAZ/xR9QoGN/L21bxEGfXdWmFdNkqPpRdxFT7nmNe12e9/uA==} + peerDependencies: + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + debug: 4.3.4 + globrex: 0.1.2 + tsconfck: 3.0.3(typescript@5.4.3) + vite: 5.1.3(@types/node@20.12.7) transitivePeerDependencies: - supports-color - typescript dev: true - /vite@4.5.3(@types/node@20.11.30): + /vite@4.5.3(@types/node@20.12.7): resolution: {integrity: sha512-kQL23kMeX92v3ph7IauVkXkikdDRsYMGTVl5KY2E9OY4ONLvkHf04MDTbnfo6NKxZiDLWzVpP5oTa8hQD8U3dg==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -15162,7 +15655,7 @@ packages: terser: optional: true dependencies: - '@types/node': 20.11.30 + '@types/node': 20.12.7 esbuild: 0.18.20 postcss: 8.4.38 rollup: 3.29.4 @@ -15170,7 +15663,7 @@ packages: fsevents: 2.3.3 dev: true - /vite@5.1.3: + /vite@5.1.3(@types/node@20.12.7): resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -15198,6 +15691,7 @@ packages: terser: optional: true dependencies: + '@types/node': 20.12.7 esbuild: 0.19.12 postcss: 8.4.38 rollup: 4.12.0 @@ -15213,7 +15707,18 @@ packages: vite: optional: true dependencies: - vite: 4.5.3(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) + dev: true + + /vitefu@0.2.5(vite@5.1.3): + resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 + peerDependenciesMeta: + vite: + optional: true + dependencies: + vite: 5.1.3(@types/node@20.12.7) dev: true /vitest-fetch-mock@0.2.2(vitest@0.32.4): @@ -15272,7 +15777,7 @@ packages: dependencies: '@types/chai': 4.3.11 '@types/chai-subset': 1.3.5 - '@types/node': 20.11.30 + '@types/node': 20.12.7 '@vitest/expect': 0.32.4 '@vitest/runner': 0.32.4 '@vitest/snapshot': 0.32.4 @@ -15292,8 +15797,8 @@ packages: strip-literal: 1.3.0 tinybench: 2.6.0 tinypool: 0.5.0 - vite: 4.5.3(@types/node@20.11.30) - vite-node: 0.32.4(@types/node@20.11.30) + vite: 4.5.3(@types/node@20.12.7) + vite-node: 0.32.4(@types/node@20.12.7) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -15347,8 +15852,64 @@ packages: strip-literal: 2.0.0 tinybench: 2.6.0 tinypool: 0.8.3 - vite: 5.1.3 - vite-node: 1.5.0 + vite: 5.1.3(@types/node@20.12.7) + vite-node: 1.5.0(@types/node@20.12.7) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vitest@1.5.0(@types/node@20.12.7): + resolution: {integrity: sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.5.0 + '@vitest/ui': 1.5.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.12.7 + '@vitest/expect': 1.5.0 + '@vitest/runner': 1.5.0 + '@vitest/snapshot': 1.5.0 + '@vitest/spy': 1.5.0 + '@vitest/utils': 1.5.0 + acorn-walk: 8.3.2 + chai: 4.4.1 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.9 + pathe: 1.1.2 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 2.0.0 + tinybench: 2.6.0 + tinypool: 0.8.3 + vite: 5.1.3(@types/node@20.12.7) + vite-node: 1.5.0(@types/node@20.12.7) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -15507,6 +16068,14 @@ packages: dependencies: isexe: 2.0.0 + /which@4.0.0: + resolution: {integrity: sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==} + engines: {node: ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + isexe: 3.1.1 + dev: true + /why-is-node-running@2.2.2: resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} engines: {node: '>=8'} @@ -15540,7 +16109,6 @@ packages: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -15731,7 +16299,6 @@ packages: /yocto-queue@1.0.0: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} - dev: true /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}